元类
1. 先梳理一下
一个类只要继承了type类, 就会成为元类: class MyMeta(type):, 这说明一个类只要拥有type类中的部分方法或属性, 它就是元类
只要是类, 不管是类还是元类, 类体中的所有代码就会在定义后会被exec方法执行,放到class_dict中准备传给type(class_name, class_bases, class_dict)生成对象或类(类本身也是对象)
类体中的方法内部不会被 执
wef
wef
2q3q23r2q3r
q23r
行 行
行
1. e
# 运行下面代码:
classMyMeta(type):
print('my_meta')# 执行
def__new__(mcs,*args,**kwargs):
print('my_meta_new')# 未执行
returntype.__new__(mcs,*args,**kwargs)
def__init__(cls,*args,**kwargs):
print('my_meta_init')# 未执行
super().__init__(*args,**kwargs)
def__call__(cls,*args,**kwargs):
print('my_meta_call')# 未执行
super().__call__(*args,**kwargs)
# 打印结果:
my_meta
当类在定义时指定了元类metaclass=MyMeta时,在代码块被加载完成后,会将代码块生成的三个参数class_name、class_bases、class_dict三个参数传给指定的元类进行实例化,生成我们普通的类。即:type(class_name, class_bases, class_dict)
classMyMeta(type):
print('my_meta')# 1
def__new__(mcs,*args,**kwargs):
print('my_meta_new')# 3
print(mcs)# 3 <class '__main__.MyMeta'>
returntype.__new__(mcs,*args,**kwargs)
def__init__(cls,*args,**kwargs):
print('my_meta_init')# 4
print(cls)# 4 <class '__main__.MyClass'>
super().__init__(*args,**kwargs)
def__call__(cls,*args,**kwargs):
print('my_meta_call')
print(cls)
super().__call__(*args,**kwargs)
class MyClass(metaclass=MyMeta): print('my_class') # 2
def __new__(cls, *args, **kwargs):
print('my_class_new')
print(cls)
return super().__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
print('my_class_init')
print(self)
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
print('my_class_call')
print(self)
打印结果:
my_metamy_classmy_meta_new<class 'main.MyMeta'>my_meta_init<class 'main.MyClass'>
```python
class MyMeta(type):
print('my_meta') # 1
def __new__(mcs, *args, **kwargs):
print('my_meta_new') # 3
print(mcs) # 3 <class '__main__.MyMeta'>
return type.__new__(mcs, *args, **kwargs)
def __init__(cls, *args, **kwargs):
print('my_meta_init') # 4
print(cls) # 4 <class '__main__.MyClass'>
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
print('my_meta_call') # 5
print(cls) # 5 <class '__main__.MyClass'>
return super().__call__(*args, **kwargs)
class MyClass(metaclass=MyMeta):
print('my_class') # 2
def __new__(cls, *args, **kwargs):
print('my_class_new') # 6
print(cls) # 6 <class '__main__.MyClass'>
return super().__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
print('my_class_init') # 7
print(self) # 7 <__main__.MyClass object at 0x0000014471934850>
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs):
print('my_class_call')
print(self)
c = MyClass()
# 打印结果:
my_meta
my_class
my_meta_new
<class '__main__.MyMeta'>
my_meta_init
<class '__main__.MyClass'>
my_meta_call
<class '__main__.MyClass'>
my_class_new
<class '__main__.MyClass'>
my_class_init
<__main__.MyClass object at 0x0000023C2F604850>
从上面的结果可以大致看出,一个类被调用时,构造过程:
调用该类的元类为类定义的__call__ 方法
这里要注意我的用法,必须是该类的元类,给该类定义的__call__方法
类自己内部定义的__call__方法,不管是类方法还是实例方法,都无效,必须是元类中为类定义的,由于元类都继承了type类,所以元类中都会有__call__方法
这里注意:对象要想变为可调用对象,那么对象的类同样要满足上述条件,即 类在主体代码中要为对象创建__call__方法,而对象在生成过程中后追 加的__call__方法或属性,均无效
call方法会调用