- super的使用场景
- super的技巧
- 再读文档
文档
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.
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.
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).
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.
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).
For both use cases, a typical superclass call looks like this:
class C(B):
def method(self, arg):
super().method(arg) # This does the same thing as:
# 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].
Also note that, aside from the zero argument form, super() is not limited to use inside methods. The two argument form specifies the arguments exactly and makes the appropriate references. The zero argument form only works inside a class definition, as the compiler fills in the necessary details to correctly retrieve the class being defined, as well as accessing the current instance for ordinary methods.
For practical suggestions on how to design cooperative classes using super(), see guide to using super().
总结为一下:
- super方法返回的是一个proxy类型对象
- 找父类的顺序为mro属性
- python3才引入,引入的目的是不必显示应用父类
super的使用场景
Python中有两种类(old-style classes)和(new-style classes),两者写法如下,在2.2版本之前,只有旧式类,在3.0版中,无论是否继承自object,都为新式类
# 新式类
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
# 旧式类
class OldStyleClass():
pass
相较于旧式类,新式类主要添加了super关键字,修改了MRO等。
旧式类只能通过父类名来初始化父类,新式类可以通过super来初始化,以下例子均使用的新式类
class A(object):
def __init__(self):
print 'A'
class B(A):
def __init__(self):
print 'B'
b = B()
# output: B
python 不会自动初始化父类,所以上边的代码只会输出一个B,下面使用super对A类进行初始化
class A(object):
def __init__(self):
print 'A'
class B(A):
def __init__(self):
super(B, self).__init__()
print 'B'
# output: A
# B
Super返回的是MRO中的下一个类
这样,很容易让人误以为super就是调用父类的意思,其实不然
MRO全称Method Resolution Order,它代表了类继承的顺序,而super返回的是MRO中的下一个类
MRO全称Method Resolution Order,它代表了类继承的顺序,而super返回的是MRO中的下一个类
super就是干这个的:
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
输出AB的那个例子,在尾部添加一行代码 print b.class.mro() 输出如下:
[<class '__main__.B'>, <class '__main__.A'>, <type 'object'>]
很清晰的一个类继承顺序。结合super代码马上就会理解为什么会初始化A类了。