Python 中的继承之Super用法

来源:互联网 发布:淘宝客服接待人数 编辑:程序博客网 时间:2024/05/18 01:23

Python 中的Super用法

最近学习Python,发现其继承机制比较有意思,尤其是其Super关键,甚是神奇,故写博客记之。

super的官方解释

以下Copy自官方文档说明,可点击查看官网源文

翻译内容属于德德自译,有不当之处请指正,勿喷。。。

翻译括弧中是德德自己理解,通过代码验证的,勿喷。。。

super(type[, object-or-type])


Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.

返回一个代理对象,该对象可以把方法调用委托给父类或者兄弟类(返回类型为super类型,值为一个对象)。这对于一个类访问继承的被重写函数很有用的(比较绕,意思就是这个可以访问父类或者兄弟类的被重写函数)。查找顺序和getattr()一样,但本身类型要跳过(getattr()的顺序是什么。。。自己查去吧,但是下面有讲,他的顺序为MRO方式的顺序)。


The mro attribute of the type lists the method resolution search order used by both getattr() and super(). The attribute is dynamic and can change whenever the inheritance hierarchy is updated.

一个类型(我觉得他想表达的是类class,新型类而不是所有的type)的_mro_属性列举了 getattr()&super()两个函数的方法调用顺序(调用算法是C3,有兴趣自己上网搜啊,德德觉得了解原理没啥用处,哈哈)。这个属性是动态变化的,它根随继承层次结构的更新而变化。


If the second argument is omitted, the super object returned is unbound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true (this is useful for classmethods).

如果第二个参数被省略(缺省),返回的super对象就是未绑定的(德德没明白啥意思哈,感觉本菊花没用。。或者作者的意图是告诉你他不能省略,省略了就绑定不了对象)。如果第二参数为一个对象,那么isinstance(obj,type)一定为true,如果第二个参数是一个类,那么issubclass(obj,type)一定得为true。(本段话超级有内涵啊。。。一般人还真不容易读懂,当然德德不是一般人啦 哈哈。首先本段讲的是super的使用方法,根据定义可以看到第一个参数是一个类型,第二个参数可以是缺省,对象,或者类型。缺省嘛。。。德德表示没有用或者德德不会用,不解释。对象吗,貌似最常见的就是对象了,不多解释,解释就是掩饰。然后重点来了,类型,类型的话咋个用来。。。 德德表示不告诉你。O(∩_∩)O,首先要告诉你的是一个小窍门,super的返回值和其第二个参数是一样的,如果第二个参数是对象,则返回的也是一个对象,如果第二个参数是一个类则返回的也是一个类型。也就是说有 class A,class B(A),b = B() 你可以super(A,b).__init__() 来用 也可以super(A,B).__init__(b)来用。。。自己敲一下代码就知道了)


感觉德德是个话捞子。。。。好多啊,但是木有办法精简啊,而且貌似排版有点小乱。。。表示markdown用的不熟。。O(∩_∩)O


Note super() only works for new-style classes.

There are two typical use cases for super. In a class hierarchy with single inheritance, super can be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use closely parallels the use of super in other programming languages.

注意super()只适用于新型类(新型类就是object的子类,也就是说class A(object),继承了object的A就是新型类了)

super用两个经典的用法。在单继承的层次结构里,super用来直接引用父类,而不是用类名来引用。这样可以使代码更加可维护。这个用法和其他编程语言差不多。(该用法类似于java中的super,java只支持单继承)

The second use case is to support cooperative multiple inheritance in a dynamic execution environment. This use case is unique to Python and is not found in statically compiled languages or languages that only support single inheritance. This makes it possible to implement “diamond diagrams” where multiple base classes implement the same method. Good design dictates that this method have the same calling signature in every case (because the order of calls is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime).

第二种用法,就是支持动态执行环境下相互联系多继承方式。(这句话不好翻译,因为需要理解着翻译。最简单的例子就是class A(object), class B(A), class C(A) ,class D(B,C),然后A,B,C,D就形成了cooperative multiple inheritance).这个用法是python特有的,并没有出现在静态编译语言或者单继承方式的语言。这使它可以实现”钻石结构图” ,也就是多个基类实现同一个方法(德德忍不住吐槽一下,太tm绕了,德德也是在多次分析研究下弄明白了该句话的意思。最可气的是文档作者还用了一个比喻的修辞手法,尼玛呀。。。我们这种英语菜的小虫虫怎么知道什么叫做‘钻石图’啊,次奥。。。不多解释,我上面关于cooperative multiple inheritance的例子就是‘钻石图’^_^)。好的设计要求一个方法在每种情况下都一同一种调用形式(这里是小括号翻译,因为调用顺序实在运行时决定的,因为顺序可以适配类结构图的变化,因为顺序中可能包括兄弟类运行时未知优先级顺序)。(忍不住啦,次奥。。。 这句话告诉我们Python的这种功能,利于更好的设计,因为在运行的时候,调用顺序,类结构,兄弟类的优先级都是不可控的。。。)

For both use cases, a typical superclass call looks like this:

对于两种用法,一个经典的调用方式示例如下:

class C(B):    def method(self, arg):        super(C, self).method(arg)

突然想感谢那些默默无闻的翻译大牛们,不得不说翻译太。。。。


Note that super() is implemented as part of the binding process for explicit dotted attribute lookups such as super().getitem(name). It does so by implementing its own getattribute() method for searching classes in a predictable order that supports cooperative multiple inheritance. Accordingly, super() is undefined for implicit lookups using statements or operators such as super()[name].

注意super()可以作为部分绑定进程点属性查找,例如super().__getitem__(name)。当然也可以用于方法__getattribute__() 来通过MRO的顺序查找类。因此super()未定义语句的隐式查找或super()[name]这种操作符。(德德的英语有点跟不上啊,德德只测试了__getitem__()函数,表示完全能用,也就是说super对于内部函数还是支持的,值得注意的是object类对内部函数没怎么实现,也就是说再object的直接子类里不要用super。但是super()[name]不能使用,有点混乱,一般__getitem__()是和[]操作符是绑定的,但是不知道咋回事他就是不支持。。。可能是德德理解的不够深刻)


Also note that super() is not limited to use inside methods. The two argument form specifies the arguments exactly and makes the appropriate references.

同时需要注意的是super()在内部函数是不受限制的,两个参数的形式表示能够精确的指定参数和作出准确的引用

For practical suggestions on how to design cooperative classes using super(), see guide to using super().

想要更使用的解说,参考向导using super().

New in version 2.2.

super 是python 2.2 以上新出的

哭了,太多了,太累了。。。。

不得不说,啃爹呀,本来还想发展一下翻译的副产业。。。。

最后上德德的测试代码

#!/usr/bin/env python# -*- coding: utf-8 -*-class A(object):    def __init__(self):        print("Enter A")        print("Leave A")    def prt(self):        print 'my name is A'    def __getitem__(self,key):        print 'here'        if(key == 'classname'):            return 'A'class B(A):    def __init__(self):        print("Enter B")        super(B, self).__init__()        print("Leave B")    def prt(self):        print 'my name is B'    def __getitem__(self,key):        print super(B, self).__getitem__(key)        if(key == 'classname'):            return 'B'    class C(A):    def __init__(self):        print("Enter C")        super(C, self).__init__()        print("Leave C")    def prt(self):        print 'my name is C'    def __getitem__(self,key):        print super(C, self).__getitem__(key)        if(key == 'classname'):            return 'C'         class BC(C,B):    def __init__(self):        print 'Enter BC'        print super(B,BC)        print type(super(C,BC))        super(BC,self).__init__()        print 'Leave BC'    def prt(self):        print 'my name is BC'    def __getitem__(self,key):        print super(BC,self).__getitem__(key)        if(key == 'classname'):            return 'BC'     if __name__ == '__main__':    print '********************'    bc = BC()    clist =  BC.__mro__    bc.prt()    super(C,BC).__init__(bc)    BC.prt(bc)    print issubclass(B,BC)    print issubclass(BC,C)    print clist    print bc['classname']

输出结果:

---------- python_debug ----------********************Enter BC<super: <class 'B'>, <BC object>><type 'super'>Enter CEnter BEnter ALeave ALeave BLeave CLeave BCmy name is BCEnter BEnter ALeave ALeave Bmy name is BCFalseTrue(<class '__main__.BC'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <type 'object'>)hereABCBC

累了。。。。

0 0
原创粉丝点击