面向对象之元类,单例
元类
1 什么是元类:
源自一句话:在python中,一切皆对象,而对象都是由类实例化得到的 class OldboyTeacher: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) # tea1=OldboyTeacher('egon',18,'male') # # print(type(tea1)) # print(type(OldboyTeacher)) # 对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,那么OldboyTeacher也是一个对象,只要是对象 # 都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type
2.关系:
1. 调用元类---->自定义的类
2. 调用自定义的类---->自定义的对象
3.创建自定义类
自定义类的三个关键组成部分: 1. 类名 2. 类的基类们 3. 类的名称空间 class关键字创建自定义类的底层的工作原理,分为四步 1. 先拿到类名:'OldboyTeacher' 2. 再拿到类的基类们:(object,) 3. 然后拿到类的名称空间???(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec) 4. 调用元类实例化得到自定义的类: OldboyTeacher=type('OldboyTeacher',(object,),{...}) 不依赖class关键字创建一个自定义类 # 1. 拿到类名 class_name='OldboyTeacher' #2. 拿到类的基类们:(object,) class_bases=(object,) #3. 拿到类的名称空间 class_dic={} class_body=""" school = 'Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) """ exec(class_body,{},class_dic) print(class_dic)
4. 调用type得到自定义的类
OldboyTeacher=type(class_name,class_bases,class_dic) print(OldboyTeacher) # print(OldboyTeacher.school) # print(OldboyTeacher.score) tea1=OldboyTeacher('egon',18,'male') print(tea1.__dict__)
5.模板
class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类 def __init__(self,class_name,class_bases,class_dic): print(self) print(class_name) print(class_bases) print(class_dic) class OldboyTeacher(object,metaclass=Mymeta): OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...}) school = 'Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) 控制类的产生 1.类名必须用驼峰体 2.类体必须有文档注释,且文档注释不能为空 总结:对象之所以可以调用,是因为对象的类中有一个函数__call__ 推导:如果一切皆对象,那么OldboyTeacher也是一个对象,该对象之所可以调用,肯定是这个对象的类中也定义了一个函数__call__
二、单例模式
1.什么是单例
单例:一个类只能产生一个实例
2. 为什么要有单例:
1.该类需要对象的产生
2.对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
3.实现单例的方法:
方式一:模块
class Songs(): pass s1 = Songs() s2 = Songs() print(s1, s2) 对外提供的对象 song = Songs()
方式二:类方法
class Songs(): __instance = None @classmethod def getInstance(cls): # 对象没有创建返回,有直接返回 if cls.__instance == None: cls.__instance = cls() return cls.__instance 约定别用 类名() 来实例化对象,用类方法来获取唯一对象 s1 = Songs() s2 = Songs() print(s1, s2) s1 = Songs.getInstance() s2 = Songs.getInstance() print(s1, s2)
方式三:基于__new__
class Songs: __instance = None def __new__(cls, song_name, *args, **kwargs): if cls.__instance == None: cls.__instance = object.__new__(cls) cls.__instance.song_name = song_name return cls.__instance def change_song(self, song_name): self.song_name = song_name s1 = Songs('菊花爆满山') s2 = Songs('感觉身体被掏空') print(s1.song_name, s2.song_name) # 菊花爆满山 菊花爆满山 s2.change_song('感觉身体被掏空') print(s1.song_name, s2.song_name) # 感觉身体被掏空 感觉身体被掏空
方式四: 装饰器装饰类
def outer(cls): _instance = None def inner(*args, **kwargs): nonlocal _instance if _instance == None: _instance = cls(*args, **kwargs) return _instance return inner @outer # Songs = outer(Songs) class Songs: pass s1 = Songs() s2 = Songs() print(s1, s2)
方式五: 元类实现
class SingleMeta(type): __instance = None def __call__(cls, *args, **kwargs): if SingleMeta.__instance == None: SingleMeta.__instance = object.__new__(cls) cls.__init__(SingleMeta.__instance, *args, **kwargs) return SingleMeta.__instance class Songs(metaclass=SingleMeta): def __init__(self): pass pass s1 = Songs() s2 = Songs() print(s1, s2)