# 元类
## 1. 先梳理一下
一个类只要继承了`type`类, 就会成为元类: `class MyMeta(type):`, 这说明一个类只要拥有type类中的部分方法或属性, 它就是元类
2. 只要是类, 不管是类还是元类, 类体中的所有代码就会在定义后会被exec方法执行,放到class_dict中准备传给`type(class_name, class_bases, class_dict)`生成对象或类(类本身也是对象)
---
1. 类体中的方法内部不会被 执
2. wef
2. wef
| 2q3 | q23r | 2q3r |
| ---- | ---- | ---- |
| | | |
| | q23r | |
| | | |
行
行
行
1. e
2.
3.
```python
# 运行下面代码:
class MyMeta(type):
print('my_meta') # 执行
def __new__(mcs, *args, **kwargs):
print('my_meta_new') # 未执行
return type.__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)`
```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')
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_meta
my_class
my_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>
```
从上面的结果可以大致看出,一个类被调用时,构造过程:
1. 调用该类的元类为类定义的`__call__` 方法
这里要注意我的用法,必须是该类的元类,给该类定义的`__call__`方法
类自己内部定义的`__call__`方法,不管是类方法还是实例方法,都无效,必须是元类中为类定义的,由于元类都继承了type类,所以元类中都会有`__call__`方法
这里注意:对象要想变为可调用对象,那么对象的类同样要满足上述条件,即 类在主体代码中要为对象创建`__call__`方法,而对象在生成过程中后追 加的`__call__`方法或属性,均无效
2. call方法会调用