day 49 索引,python遗留:元类,单例
元类metaclass
元类是什么?
单例
单例是什么?
是一种设计模式。是设计模式中比较简单的。
指的是 一个类有且仅有一个实例 就叫单例。
如何实现单例的思路?: 就是控制类生成对象的方式,通过判断是否已经创建过对象。
为什么要使用单例这种模式?
之前在创建对象时 每个对象中的数据不相同 ,对象实际上是数据和处理数据的方法的结合体。
当对象中的数据是 相同的、共享的时候 ,使用单例。
例如遇到以下情况:
u1 = user("张三",29,"man")
u2 = user("张三",29,"man")
u3 = user("张三",29,"man")
不同的对象, 我们发现3个对象有完全相同的数据 ,所以没有必要每个人保存一份。
u1 = user("张三",29,"man")
u2 = u1
u3 = u1
如此 可以减少内存资源开销 ,大家共享一个数据 只有一个对象。
单例实现方式一:通过类绑定方法
class User:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# 通过我们指定的方法来获取实例,而不是调用类来创建新对象。
instance = None
@classmethod #一种通过绑定类方法
def get_instance(cls,name,age,sex):
if not cls.instance:
cls.instance = cls(name,age,sex)
return cls.instance
@staticmethod #另一种通过非绑定方法
def get_instance2(name,age,sex):
if not User.instance:
User.instance = User(name,age,sex)
return User.instance
u1 = User.get_instance2("张三",20,"man")
print(u1)
u2 = User.get_instance2("张三",20,"man")
print(u2)
====》输出两个对象的内存地址一样,即为一个对象,实现单例。
注意有问题:通过classMethod 可以完成单例,但是还是可以通过直接调用类产生新对象。怎么办? 我们此时就需要用到元类。
u3 = User("张三",20,"man")
单例实现方式二:元类法
class MyMetaClass(type):
instance = None
def __call__(cls, *args, **kwargs):
if not MyMetaClass.instance:
# 利用object类内的_new_方法,创建空对象。
MyMetaClass.instance = object.__new__(cls)
print("创建新的播放器对象!")
#初始化出对象。
MyMetaClass.instance.__init__(*args,**kwargs)
#返回对象。
return MyMetaClass.instance
# 只能有一个播放器实例
class CDPlayer(metaclass=MyMetaClass):
def play(self,music):
print("切换音乐",music)
def __init__(self,music_name):
self.music_name = music_name
p1 = CDPlayer("你发如雪!")
p1.play("菊花台")
p1.play("菊花台2")
p1.play("菊花台3")
# 不会创建新对象
p1 = CDPlayer("你发如雪!")
p1 = CDPlayer("你发如雪!")
p1 = CDPlayer("你发如雪!")
p1 = CDPlayer("你发如雪!")
# 元类实现单例的原理: 就是 调用类时,拦截了CDPlayer类中的__init__的正常执行,
而是触发执行自定义元类内的_call_函数,使得创建对象都必须经过自己判断逻辑。

浙公网安备 33010602011771号