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)