Python----面向对象---自定义元类控制类的实例化行为
一、知识储备
1、__call__方法
1 class Foo: 2 def __call__(self, *args, **kwargs): 3 print(self) 4 print(args) 5 print(kwargs) 6 7 obj = Foo() 8 obj() 9 10 结果为: 11 12 <__main__.Foo object at 0x000002AFE2B4BDA0> 13 () 14 {}
实例化时传参
1 obj(1, 2, 3, a=1, b=2, c=3) # 相当于执行obj.__call__(obj, 1, 2, 3, a=1, b=2, c=3) 2 3 结果为: 4 5 <__main__.Foo object at 0x000001A1799CBDA0> 6 (1, 2, 3) 7 {'a': 1, 'b': 2, 'c': 3}
元类内部也应该有一个__call__方法,会在调用Foo时触发执行
Foo(1, 2, x=1)相当于 Foo.__call__(Foo,1,2,x=1)
1 class Mymeta(type): 2 def __init__(cls, class_name, class_bases, class_dic): 3 4 if not class_name.istitle(): 5 raise TypeError('类名的首字母必须大写') 6 7 if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): 8 raise TypeError('必须有注释,且注释不能为空') 9 10 super(Mymeta, cls).__init__(class_name, class_bases, class_dic) 11 12 def __call__(cls, *args, **kwargs): 13 print('=====>') 14 15 16 class Chinese(object, metaclass=Mymeta): 17 ''' 18 xxx 19 ''' 20 21 country = 'China' 22 23 def __init__(self, name, age): 24 self.name = name 25 self.age = age 26 27 def talk(self): 28 print('%s is talking' % self.name) 29 30 31 obj = Chinese('egon', 18) 32 33 执行结果为: 34 35 =====>
可以看出,Chinese类实例化会触发它的父类的__call__方法,
我们先看一下__call__方法的传值
1 def __call__(cls, *args, **kwargs): 2 print(cls) 3 print(args) 4 print(kwargs) 5 6 结果为: 7 8 <class '__main__.Chinese'> 9 ('egon', 18) 10 {}
1 def __call__(cls, *args, **kwargs): 2 print(cls) # cls = Chinese 3 print(args) # args = ('egon',) 4 print(kwargs) # kwargs = {'age': 18} 5 6 obj = Chinese('egon', age=18) # Chinese.__call__(chinese,'egon',age=18)
要想控制Chinese类的实例化,就要在它的元类的__call__方法上下功夫
__call__方法会做3件事:
1、先造一个空对象obj
2、初始化obj
3、返回obj
1 def __call__(cls, *args, **kwargs): 2 # print(cls) # cls = Chinese 3 # print(args) # args = ('egon',) 4 # print(kwargs) # kwargs = {'age': 18} 5 obj = object.__new__(cls) 6 cls.__init__(obj, *args, **kwargs) 7 return obj 8 9 obj = Chinese('egon', age=18) # Chinese.__call__(chinese,'egon',age=18) 10 print(obj.__dict__) 11 12 结果为: 13 14 15 {'name': 'egon', 'age': 18}
实例化成功了,