美文网首页
2018-03-02 python super() 调用机制 和

2018-03-02 python super() 调用机制 和

作者: 罗兆峰 | 来源:发表于2018-03-05 11:09 被阅读0次

super(class, object or type)  不用管第2个参数是self 还是cls. 只是用来类型检查,返回值都是根据第一个参数的MRO 继承顺序作出修改。

super 函数的伪代码如下:

def super(class_name,  self):

    mro  = self.__class__.mro()

return mro[mro.index(class_name) + 1]

super(CurClass, self).__init__()  实则是查询类的继承顺序中CurClass 后的 一个类

__new__ 方法的使用

class object:

@staticmethod

    def __new__(cls, *more):

T.__new__(S,...)  //return a new object with type S, a subType of T

        pass

object.__new__(cls[,...])

Called to create a new instance of classcls.__new__()is a staticmethod (special-cased so you need not declare it as such) that takes the classof which an instance was requested as its first argument.  The remainingarguments are those passed to the object constructor expression (the call to theclass).  The return value of__new__()should be the new object instance(usually an instance ofcls).

__new__的return 值 可以写成是父类的返回值(因为可以自动递归到object类中),也可以将object的__new__()出来的实例返回

class Person(object):

    def __new__ (cls, *args, **kw):

        return super(Person,cls).__new__(*args,**kw)

    def __init__(self, *args, **kw):        

当调用Person() 时, 第一个被调用的函数是 __new__ 函数, 然后才是 __init__ 函数

如果要得到当前类的实例, 应当在当前类中的__new__ 函数中调用父类的__new__ 方法。(父类一般为object, object.__new__(cls[,...])方法返回 cls 的新实例,然后调用对象的__init__函数增加其属性)

事实上如果类中没用重写__new__方法, 则调用该类的父类的__new__方法来构建该类的实例,如果该类的父类也没有定义,则此规则追溯到object 的__new__方法中。(该new方法中不接受任何参数,所以下面的代码中new 只传入cls 参数)

总结:

class MyType(type):

    def __call__(cls,*args,**kw):

        obj = cls.__new__(cls,*args,**kw)

        print(dir(obj))## The fact is calling the __new__ function recursively.

        obj.__init__(*args,**kw)

        print(dir(obj))

        return obj

class Foo(metaclass= MyType):

    def __init__(self,*args,**kw):

        self.name = 'name'

    def __new__(cls,*args,**kw):

        print("I am called")

        return super(Foo,cls).__new__(cls)

    def __call__(cls,*args,**kw):

        print("avoid call the type function.")

        return cls.__new__(cls,*args,**kw)

def f1(a,b,c = 3 , *args, **kw):

    print('a = ',a,'b = ',b,'c = ',c,'args = ',args,'kw = ', kw)

if __name__ == '__main__':

    f= Foo(a = 1)

打印结果如下:

I am called

['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']

当解释器遇到class Foo 关键词时, 调用 meta class中的type.__init__方法创建Foo 类(metaclass 的作用只是重载Type class)

当遇到Foo() 生成实例时,不会调用自身的def __call__函数 (自身的__call__ 是被Foo 的实例调用),而是调用Foo 作为Type 实例的 __call__ 函数, 该函数在metaclass 中指向的Customize type中被定义 (type 是所有类对象的类生成器,object 是所有类对象的父类)

type 中的__call__函数不重写的话,只负责两个事情。

A. 生成Foo 的实例

B. 调用实例的__init__ 方法体

相关文章

  • 2018-03-02 python super() 调用机制 和

    super(class, object or type) 不用管第2个参数是self 还是cls. 只是用来类型检...

  • python 面向对象: super()

    python 关于 super 的使用 子类对象调用父类方法 :super(B,b).hh() 子类中调用父类方法...

  • Python的继承

    #Python继承的特点 总是从某个类继承 不要忘记调用 super().init 一定要用 super(Teac...

  • self和super的区别

    self和super的区别 self调用自己方法,super调用父类方法 self是类,super是预编译指令 [...

  • 面试问题总结

    1.runtime的缓存机制是什么?答案:根据runtime类的数据结构。调用某个方法,首先通过isa和super...

  • python 神奇的super()

    我们都知道在python继承中,子类调用父类的方法是使用super()函数,在2.X里格式是super(mycla...

  • self和super区别

    self:调用自己方法,它是类super:调用父类方法,它是预编译指令【self class】和【super cl...

  • OC消息机制和super关键字

    阅读原文请到我的博客OC消息机制和super关键字 消息发送 在Objective-C里面调用一个方法[objec...

  • ★06.复用类

    Java异常机制:try,finally; 子类构造函数可以通过调用super()来构造基类。 子类可以通过sup...

  • ES6 类\继承\接口

    super方法 子类必须在constructor方法中调用super方法调用super方法必须放到this初始化实...

网友评论

      本文标题:2018-03-02 python super() 调用机制 和

      本文链接:https://www.haomeiwen.com/subject/ppeaxftx.html