面向对象(一)--魔术方法(特殊方法)

1、__new__方法

__new__方法:创建对象调用的方法

__init__方法:初始化对象调用的方法

一个类如果重写了__new__方法,又没有调用父类的__new__方法创建对象,那__init__方法也不会调用

class MyTest(object):

def __init__(self, *args, **kwargs):
print("这是初始化对象的方法")

def __new__(cls, *args, **kwargs):
print("这是new方法,创建对象调用的方法")


m = MyTest()
print(m)
没有调用__init__初始化方法,因为__new__方法没有调用父类的new方法创建对象,故初始化方法不会自动调用

 2、单例模式

a、什么是单例模式?

单例模式:一个类只能创建一个对象,这个类就是一个单例模式的类

b、单例模式的实现

1)重写__new__方法实现单例模式

class MyTest(object):
obj = None # 定义一个类属性,存储创建的对象,如果对象存在,则返回该对象,如果对象不存在则创建对象

def __init__(self, *args, **kwargs):
print("这是初始化对象的方法")

def __new__(cls, *args, **kwargs):
if not cls.obj:
cls.obj = super().__new__(cls,*args,**kwargs)
return cls.obj


m1 = MyTest()
m2 = MyTest()
m3 = MyTest()
print("{}:内存地址:{}".format(m1, id(m1)))
print("{}:内存地址:{}".format(m2, id(m2)))
print("{}:内存地址:{}".format(m3, id(m3)))

2)使用装饰器实现单例模式

"""
通过装饰器实现单例模式,只要任意一个类使用该装饰器装饰,那么就会变成一个单例模式的类
"""

status = {"obj": None} # 定义一个全局变量,存储创建的类


# 装饰器
def test_decorator(func):
def wrapper(*args, **kwargs):
if not status["obj"]:
status["obj"] = func(*args, **kwargs)
return status["obj"]

return wrapper


# 被装饰的类
@test_decorator
class MyTest(object):

def __init__(self, *args, **kwargs):
print("这里是初始化方法")


m1 = MyTest()
m2 = MyTest()
m3 = MyTest()

print("{}:内存地址:{}".format(m1, id(m1)))
print("{}:内存地址:{}".format(m2, id(m2)))
print("{}:内存地址:{}".format(m3, id(m3)))

c、单例模式的作用

单例模式的作用:节省内存开销

 

例子:

"""
实现一个类,前五次创建对象,每次都可以返回一个新的对象,第六次开始,每次创建,都随机返回前5哥对象中的一个
"""
import random


class CreateObject(object):
obj_list = []

def __init__(self):
pass

def __new__(cls, *args, **kwargs):
if len(cls.obj_list) < 5:
obj = super().__new__(cls, *args, **kwargs)
cls.obj_list.append(obj)
return obj
else:
return random.choice(cls.obj_list)


for c in range(10):
obj = CreateObject()
print("对象第{}次创建,内存地址:{}".format(c + 1, id(obj)))

 

 

3、上下文管理器---with

1)迭代器协议是由__iter__方法和__next__方法这两个魔术方法组成的。

__iter__方法:会在使用内置函数iter(obj),将可迭代对象转换为迭代器时调用。

__next__方法:会在使用内置函数next(obj),对迭代器进行迭代操作时调用。

2)为什么with去打开文件进行操作,会自动关闭文件呢?

因为with启动了文件操作对象的上下文管理器

3)上下文管理器协议的构成:__enter__方法和__exit__方法

__enter__方法:启动上下文时会自动调用

__exit__方法:退出上下文时会自动调用

4)如果说一个对象实现了__enter__方法和__exit__方法,那么这个对象就实现了上下文管理器协议,就可以使用with这个关键字来开启对象的上下文管理。

class FileOpen(object):

def __init__(self, file, mode, encoding):
self.file = file
self.mode = mode
self.encoding = encoding

def __enter__(self):
print("-----进入enter方法----")
self.io = open(self.file, self.mode, encoding=self.encoding)
return self.io

def __exit__(self,exc_type, exc_value, exc_traceback):
print("异常的类型:{}".format(exc_type))
print("异常的值:{}".format(exc_value))
print("异常的溯源:{}".format(exc_traceback))
self.io.close()


with FileOpen("d06_new.py", "r", "utf-8") as f:
file_content = f.read()
# raise AssertionError
print(file_content)

4、__call__方法

1)一切皆对象,其实函数也是对象,函数是可调用的对象

callable(obj):输出bool,判断对象是否可调用

name = "123"
print(callable(name)) # 输出False
print(callable(str)) # 输出True

象是否可调用

2)__call__方法:实现了该方法的对象,该对象是可调用的对象(像调用函数一样调用对象)

class MyTest(object):

def __init__(self):
print("这是初始化方法")

def __call__(self, *args, **kwargs):
print("实现了call方法,对象可被调用")


m = MyTest()
print(callable(m))
m() # 对象调用的时候,执行的是__call__()方法

 

 3)通过类实现装饰器

class MyDecorator(object):

def __init__(self, func):
self.func = func

def __call__(self, *args, **kwargs):
print("装饰器扩展功能1")
res = self.func(*args, **kwargs)
print("装饰器扩展功能2")
return res


@MyDecorator # ==> worker = MyDecorator(worker)
def worker():
print("这是Worker功能函数")


worker()

 

 

5、__str__方法

1)print输出的内容:是用什么方法来控制的?

print输输出的其实就是对象的__str__返回的值

注意点:__str__方法必须要些返回值,返回值的类型只能是字符串

class MyTest:

def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender

def __str__(self):
return str(self.name)


m1 = MyTest("gen", 18, "dalao")
m2 = MyTest("fei", 18, "pingm")
print(m1)
print(m2)

 

posted @ 2021-10-21 21:35  %女王%  阅读(69)  评论(0编辑  收藏  举报