• python概念-其实只要简单了解一下,但是却讲了将近两个小时的知识点:元类


    说实话,我真心不太想总结这个东西,算了,炒一下egon的吧

    1 引子

    1 class Foo:
    2     pass
    3 
    4 f1=Foo() #f1是通过Foo类实例化的对象

    python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)

    上例可以看出f1是由Foo这个类产生的对象,而Foo本身也是对象,那它又是由哪个类产生的呢?

    1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的
    2 print(type(f1)) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
    3 print(type(Foo)) # 输出:<type 'type'>  

    2 什么是元类?

    元类是类的类,是类的模板

    元类是用来控制如何创建类的,正如类是创建对象的模板一样

    元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例Foo类是 type 类的一个实例)

    type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象

    3 创建类的两种方式

    方式一:

    1 class Foo:
    2     def func(self):
    3         print('from func')

    方式二:

    1 def func(self):
    2         print('from func')
    3 x=1
    4 Foo=type('Foo',(object,),{'func':func,'x':1})

    4 一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的创建,工作流程是什么)

     自定制元类
     自定制元类纯净版
     自定制元类精简版
    复制代码
     1 #元类总结
     2 class Mymeta(type):
     3     def __init__(self,name,bases,dic):
     4         print('===>Mymeta.__init__')
     5 
     6 
     7     def __new__(cls, *args, **kwargs):
     8         print('===>Mymeta.__new__')
     9         return type.__new__(cls,*args,**kwargs)
    10 
    11     def __call__(self, *args, **kwargs):
    12         print('aaa')
    13         obj=self.__new__(self)
    14         self.__init__(self,*args,**kwargs)
    15         return obj
    16 
    17 class Foo(object,metaclass=Mymeta):
    18     def __init__(self,name):
    19         self.name=name
    20     def __new__(cls, *args, **kwargs):
    21         return object.__new__(cls)
    22 
    23 '''
    24 需要记住一点:名字加括号的本质(即,任何name()的形式),都是先找到name的爹,然后执行:爹.__call__
    25 
    26 而爹.__call__一般做两件事:
    27 1.调用name.__new__方法并返回一个对象
    28 2.进而调用name.__init__方法对儿子name进行初始化
    29 '''
    30 
    31 '''
    32 class 定义Foo,并指定元类为Mymeta,这就相当于要用Mymeta创建一个新的对象Foo,于是相当于执行
    33 Foo=Mymeta('foo',(...),{...})
    34 因此我们可以看到,只定义class就会有如下执行效果
    35 ===>Mymeta.__new__
    36 ===>Mymeta.__init__
    37 实际上class Foo(metaclass=Mymeta)是触发了Foo=Mymeta('Foo',(...),{...})操作,
    38 遇到了名字加括号的形式,即Mymeta(...),于是就去找Mymeta的爹type,然后执行type.__call__(...)方法
    39 于是触发Mymeta.__new__方法得到一个具体的对象,然后触发Mymeta.__init__方法对对象进行初始化
    40 '''
    41 
    42 '''
    43 obj=Foo('egon')
    44 的原理同上
    45 '''
    46 
    47 '''
    48 总结:元类的难点在于执行顺序很绕,其实我们只需要记住两点就可以了
    49 1.谁后面跟括号,就从谁的爹中找__call__方法执行
    50 type->Mymeta->Foo->obj
    51 Mymeta()触发type.__call__
    52 Foo()触发Mymeta.__call__
    53 obj()触发Foo.__call__
    54 2.__call__内按先后顺序依次调用儿子的__new__和__init__方法
    55 '''
    复制代码
  • 相关阅读:
    阅读任务
    自我介绍
    学习总结
    第十二周课程总结
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
    第四周课程总结&实验报告
    第3周Java编程总结
    学习总结
  • 原文地址:https://www.cnblogs.com/DragonFire/p/6764125.html
Copyright © 2020-2023  润新知