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类的实例。

     
  • 相关阅读:
    OneNote2007产品密钥及激活方法
    穿着马甲的编码方式链式
    String 转换NameValueCollection 的方法 , 这是原创 嘎嘎
    TransactionScope分布式事务无法使用时, 配置并启动 MSDTC 的解决方案
    Spirit越狱3.1.3/3.2固件(Windows)
    智能感知 不正常的解决方法
    HttpHandler HttpModule入门篇
    Microsoft.Practices.Unity依赖注入使用实例
    ViewEngine 深入解析与应用实例
    打开chm文件提示“已取消到该网页的导航”的解决方案
  • 原文地址:https://www.cnblogs.com/liuyinzhou/p/9728369.html
Copyright © 2011-2022 走看看