zoukankan      html  css  js  c++  java
  • 深入解析类对象与类实例的创建过程

    
    
    class MyType(type):
    def __init__(self,*args,**kwargs):
    print("init")
    super(MyType, self).__init__(*args,**kwargs)

    def __new__(cls, *args, **kwargs):
    print("new")
    print("mro",cls.__mro__)
    # 调用父类的__new__ 方法来实例出一个Base类对象
    return super(MyType, cls).__new__(cls, *args, **kwargs)

    def __call__(self, *args, **kwargs):
    # self = Base类对象
    # 调用object类的__new__方法,创建Base的实例对象
    obj = object.__new__(self)
    # 执行 构造方法
    obj.__init__()
    print('obj',obj)
    return obj


    class Base(metaclass=MyType):
    def __init__(self):
    print("Base init")

    def __new__(cls, *args, **kwargs):
    ret = super(Base, cls).__new__(cls, *args, **kwargs)
    print("Base ret",ret)
    return ret

    a = Base()
    print(a,'a的返回值')

      Base是一个对象,Base()则调用创建该类的__call__方法。执行__call__方法本质上是首先执行Base类中的__new__方法,然后再执行__init__方法,最终将生成的经过初始化的实例对象返回给a。也就是说,__call__方法的返回值是什么,生成的实例对象就是什么。需要注意的是,在__call__方法中,self指的是Base对象,因此 obj = object.__new__(self) 生成的是Base类的对象, obj.__init__() 执行的是Base的__init__方法,至此完成了创建Base类实例的过程。

      需要说明的是,我在元类的__call__方法中以手动的方式执行 __new__和__init__,但也可以用  super(MyType, self).__call__(*args, **kwargs) 完成相同的效果,这里只是为了说明   super(MyType, self).__call__(*args, **kwargs) 的内部执行流程。

    super补充

      首先要明确的是,super是一个类,不是一个函数。以 super(MyType, self).__call__(*args, **kwargs) 为例,super(cls,ins)获得是cls在ins的mor表中的下一个类对象,再通过该对象调用该对象下的__call__方法,如果此类中没有__call__方法,那么再按照ins的mro表继续向下查找,无论如何,一定可以在object类中找到__call__方法,在__call__方法中首先创建一个cls的实例,然后执行该实例的__init__方法,从而完成cls类的实例。

     
  • 相关阅读:
    为什么富人越来越富,穷人越来越穷?
    计算几何基础_点_向量_极角排序
    滑窗模板_双向队列
    后缀数组
    AC自动机
    RMQ_ST表
    二叉树求逆序对(伪AC 23333)
    分块
    莫队
    树状数组_二维
  • 原文地址:https://www.cnblogs.com/liuyinzhou/p/9728369.html
Copyright © 2011-2022 走看看