先抄一下官方的文档:官网文档链接
class super([type[, object-or-type]])
返回一个代理对象,它会将方法调用委托给 type 的父类或兄弟类。 这对于访问已在类中被重载的继承方法很有用。
object-or-type 确定用于搜索的 method resolution order。 搜索会从 type 之后的类开始。
举例来说,如果 object-or-type 的 mro 为 D -> B -> C -> A -> object 并且 type 的值为 B,则 super() 将会搜索 C -> A -> object。
object-or-type 的 mro 属性列出了 getattr() 和 super() 所共同使用的方法解析搜索顺序。 该属性是动态的,可以在任何继承层级结构发生更新的时候被改变。
如果省略第二个参数,则返回的超类对象是未绑定的。 如果第二个参数为一个对象,则 isinstance(obj, type) 必须为真值。 如果第二个参数为一个类型,则 issubclass(type2, type) 必须为真值(这适用于类方法)。
super 有两个典型用例。 在具有单继承的类层级结构中,super 可用来引用父类而不必显式地指定它们的名称,从而令代码更易维护。 这种用法与其他编程语言中 super 的用法非常相似。
第二个用例是在动态执行环境中支持协作多重继承。 此用例为 Python 所独有而不存在于静态编码语言或仅支持单继承的语言当中。 这使用实现“菱形图”成为可能,即有多个基类实现相同的方法。 好的设计强制要求这样的方法在每个情况下都具有相同的调用签名(因为调用顺序是在运行时确定的,也因为这个顺序要适应类层级结构的更改,还因为这个顺序可能包括在运行时之前未知的兄弟类)。
对于以上两个用例,典型的超类调用看起来是这样的:
class C(B):
def method(self, arg):
super().method(arg) # This does the same thing as:
# super(C, self).method(arg)
除了方法查找之外,super() 也可用于属性查找。 一个可能的应用场合是在上级或同级类中调用 描述器。
请注意 super() 是作为显式加点属性查找的绑定过程的一部分来实现的,例如 super().getitem(name)。 它做到这一点是通过实现自己的 getattribute() 方法,这样就能以可预测的顺序搜索类,并且支持协作多重继承。 对应地,super() 在像 super()[name] 这样使用语句或操作符进行隐式查找时则未被定义。
还要注意的是,除了零个参数的形式以外,super() 并不限于在方法内部使用。 两个参数的形式明确指定参数并进行相应的引用。 零个参数的形式仅适用于类定义内部,因为编译器需要填入必要的细节以正确地检索到被定义的类,还需要让普通方法访问当前实例。
———————————————————————————————————————————————————————
写一下我的场景和问题:
我有一个基类,有四个子类继承基类,有一个孙类继承四个子类,原先只有基类有属性,子类只有方法无子类属性,现在给某几个子类增加了属性
我的需求是:孙类能继承基类、指定子类的属性和方法
直接上代码吧:
class A:
def __init__(self):
print('Enter A init')
self.a = 2
self.b = 'aaa'
def aa(self, m):
print('self is {0} @A.add'.format(self))
self.a += m
class C(A):
def __init__(self):
print('Enter C init')
super().__init__()
self.b = 'ccc'
def cc(self, m):
print(self.a)
class B(A):
def __init__(self):
print('Enter B init')
super().__init__()
self.b = 'bbb'
def bb(self, m):
print('self is {0} @B.add'.format(self))
print(self.a)
class D(A):
def dd(self, m):
print(self.a)
————————————————————————————————————————————————————————————————————————————————
class E(D,C,B):
def __init__(self):
super().__init__()
print('**********')
def ee(self, m):
print(self.a)
print(self.b)
ee = E() #实例化时,MRO为D→C→B→A
print(ee.b) #D无属性,则找C ,找到了
运行结果:
Enter C init
Enter B init
Enter A init
**********
ccc
————————————————————————————————————————————————————————————————————————————————
#修改为:
class E(D,C,B):
def __init__(self):
super(D, self).__init__()
print('**********')
def ee(self, m):
print(self.a)
print(self.b)
ee = E() #实例化时,MRO为C→B→A
print(ee.b) #D无属性,则找C ,找到了
运行结果:
Enter C init
Enter B init
Enter A init
**********
ccc
————————————————————————————————————————————————————————————————————————————————
#修改为:
class E(D,C,B):
def __init__(self):
super(C, self).__init__()
print('**********')
def ee(self, m):
print(self.a)
print(self.b)
ee = E() #实例化时,MRO为B→A
print(ee.b) #B的b属性为bbb
运行结果:
Enter B init
Enter A init
**********
bbb
————————————————————————————————————————————————————————————————————————————————
#修改为:
class E(D,C,B):
def __init__(self):
super(B, self).__init__()
print('**********')
def ee(self, m):
print(self.a)
print(self.b)
ee = E() #实例化时,MRO为A
print(ee.b) #A的b属性为aaa
运行结果:
Enter A init
**********
aaa
从上面代码可以直观的看出对孙类实例化时执行的过程,就可以控制孙类继承的属性