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}

实例化成功了,

原文地址:https://www.cnblogs.com/xudachen/p/8660844.html