第一步
继承默认元类type
class Mymeta(type): # 继承默认元类的一堆属性
def __init__(self, class_name, class_bases, class_dic):
print("Mymeta__init__")
super(Mymeta, self).__init__(class_name, class_bases, class_dic)
class People(object, metaclass=Mymeta):
country = 'China'
def __init__(self, name, age):
print("people__init__")
self.name = name
self.age = age
def talk(self):
print('%s is talking' % self.name)
p1= People("a",1)
print("--------")
p2 = People("b",2)
输出如下:
Mymeta__init__
people__init__
--------
people__init__
第二步
__call__
方法的使用,对象调用时候,会调用该方法
class People(object,metaclass=type):
def __init__(self,name,age):
self.name=name
self.age=age
def __call__(self, *args, **kwargs):
print(self,args,kwargs)
p1= People("a",1)
p1(1,2)
print("--------")
p2 = People("b",2)
p2(2,3)
输出如下:
E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
<__main__.People object at 0x04B713B0> (1, 2) {}
--------
<__main__.People object at 0x04B714F0> (2, 3) {}
如果说类People是元类type的实例,那么在元类type内肯定也有一个call,会在调用People(‘egon’,18)时触发执行,然后返回一个初始化好了的对象obj
第三步
class Mymeta(type): #继承默认元类的一堆属性
def __init__(self,class_name,class_bases,class_dic):
print("Mymeta__init__")
print(self,class_name,class_bases,class_dic)
super(Mymeta,self).__init__(class_name,class_bases,class_dic)
def __call__(self, *args, **kwargs):
print("Mymeta__call__",self)
#self=People
print(self,args,kwargs) #<class '__main__.People'> ('orz', 18) {}
#1、实例化People,产生空对象obj
obj=object.__new__(self)
#2、调用People下的函数__init__,初始化obj
self.__init__(obj,*args,**kwargs)
#3、返回初始化好了的obj
return obj
class People(object,metaclass=Mymeta):
country='China'
def __init__(self,name,age):
print("People__init__",self)
self.name=name
self.age=age
def talk(self):
print('%s is talking' %self.name)
obj1=People('orz',18)
print(obj1.__dict__) #{'name': 'orz', 'age': 18}
print("------------------")
obj2=People('safly',10)
print(obj2.__dict__) #{'name': 'safly', 'age': 10}
输出如下:
E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
Mymeta__init__
<class '__main__.People'> People (<class 'object'>,) {'__module__': '__main__', '__qualname__': 'People', 'country': 'China', '__init__': <function People.__init__ at 0x036D28E8>, 'talk': <function People.talk at 0x036D27C8>}
Mymeta__call__ <class '__main__.People'>
<class '__main__.People'> ('orz', 18) {}
People__init__ <__main__.People object at 0x036D1E30>
{'name': 'orz', 'age': 18}
------------------
Mymeta__call__ <class '__main__.People'>
<class '__main__.People'> ('safly', 10) {}
People__init__ <__main__.People object at 0x036D1DF0>
{'name': 'safly', 'age': 10}
Process finished with exit code 0
第四步
class Mymeta(type): #继承默认元类的一堆属性
def __init__(self,class_name,class_bases,class_dic):
print("Mymeta__init__")
super(Mymeta,self).__init__(class_name,class_bases,class_dic)
def __call__(self, *args, **kwargs):
print("Mymeta__call__")
#1、调用self,即People下的函数__new__,在该函数内完成:1、产生空对象obj 2、初始化 3、返回obj
obj=self.__new__(self,*args,**kwargs)
#2、一定记得返回obj,因为实例化People(...)取得就是__call__的返回值
return obj
class People(object,metaclass=Mymeta):
country='China'
def __init__(self,name,age):
print("People__init__")
self.name=name
self.age=age
def talk(self):
print('%s is talking' %self.name)
def __new__(cls, *args, **kwargs):
print("People__new__")
obj=object.__new__(cls)
cls.__init__(obj,*args,**kwargs)
return obj
obj=People('safly',18)
print(obj.__dict__) #{'name': 'egon', 'age': 18}
print("-------------")
obj1 = People("orz",18)
print(obj1.__dict__)
输出如下:
E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
Mymeta__init__
Mymeta__call__
People__new__
People__init__
{'name': 'safly', 'age': 18}
-------------
Mymeta__call__
People__new__
People__init__
{'name': 'orz', 'age': 18}
Process finished with exit code 0
第五步
定制元类实现单例模式
class Mymeta(type):
def __init__(self,name,bases,dic): #定义类Mysql时就触发
print("Mymeta __init__")
self.__instance=None
super().__init__(name,bases,dic)
def __call__(self, *args, **kwargs): #Mysql(...)时触发
print("Mymeta __call__")
if not self.__instance:
self.__instance=object.__new__(self) #产生对象
self.__init__(self.__instance,*args,**kwargs) #初始化对象
#上述两步可以合成下面一步
# self.__instance=super().__call__(*args,**kwargs)
return self.__instance
class Obj(metaclass=Mymeta):
def __init__(self,host='127.0.0.1',port='3306'):
print("Obj __init__")
self.host=host
self.port=port
def __new__(cls, *args, **kwargs):
print("Obj new")
obj1=Obj()
print("-----------")
obj2=Obj()
print(obj1 is obj2)
输出如下:
E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
Mymeta __init__
Mymeta __call__
Obj __init__
-----------
Mymeta __call__
True
如果替换为注释的代码self.__instance=super().__call__(*args,**kwargs)
输出如下:
Mymeta __init__
Mymeta __call__
Obj new
-----------
Mymeta __call__
Obj new
True
Mymeta中的__call__
直接调用Obj中的__new__
方法