2022-04-26

元类

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方法会调用

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容