在下面的 python 代码中(我使用的是 3.8),从类 A 派生的类 B 的对象调用访问父级成员的方法 bar
和 foo
通过 super()
函数调用类。因此,我希望得到与直接在 A 上调用 bar
和 foo
相同的结果。奇怪的是,返回的内容受到 p
参数化的影响B 的情况,这不应该发生,因为 A 应该免受其子级的影响,不是吗?!这是要重现的代码:
class A(object):
@property
def p(self):
return 3
def bar(self):
return self.p
def foo(self):
return self.bar()
class B(A):
@property
def p(self):
return 6
def bar(self):
return super().p
def foo(self):
return super().bar()
a, b = A(), B()
print(a.p) # prints 3, OK
print(b.p) # prints 6, OK
print(a.bar()) # prints 3, OK
print(b.bar()) # prints 3, OK, since where accessing super().p
print(a.foo()) # prints 3, OK
print(b.foo()) # prints 6, NOT OK, because we are accessing super().bar() and expect 3
我已经失去了理智,所以如果有人能够阐明这种行为的基本原理并展示一种避免这种行为的方法,这将是最有帮助的。非常感谢。
最佳答案
欢迎来到super
的复杂性!
super()
这里是 super(B, self)
的快捷方式。它返回一个代理,该代理将在类 MRO 中查找 B 之前的类,因此 A 和 super().bar() 会实际调用:
A.bar(self)
不改变原来的b
对象...
而A.bar(self)
实际上是...b.p
并且会给出6
如果您习惯了其他面向对象的语言,例如 C++,那么一切都会发生,就好像 Python 中的所有方法都是虚拟的(Java 措辞中的非 final方法)
关于python - 父类(super class)似乎错误地引用了派生类的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70579256/