![](/img/trans.png)
[英]Difference between super(Foo, self) and super(Foo, self.__class__)?
[英]why is there difference between calling super().foo and super().__getattribute__("foo")
我認為 super() 總是會嘗試使用基礎 class 中的方法(或屬性)運行,直到我遇到一個用super().__getattribute__("foo")
獲取子 class 屬性的用例。 簡化代碼如下所示。
class Base:
value = "base"
def foo(self):
print(f"Base foo, {self.value}")
class Derived(Base):
value = "derived"
def foo(self):
print(f"Derived foo, {self.value}")
def bar(self):
print(f"Derived bar {self.value}")
print(super().value)
print(super().__getattribute__("value"))
super().foo()
super().__getattribute__('foo')()
d = Derived()
d.bar()
output,
Derived bar derived
base
derived
Base foo, derived
Derived foo, derived
有點超出我之前的理解,難道只有__getattribute__
是個例外嗎? 我無法獲得此文檔的更多詳細信息,希望任何人都可以幫助我更清楚地理解這一點,謝謝!
編輯以遵循__getattribute__
問題,如下所示:
class Base:
value = "base"
def foo(self):
print(f"Base foo, {self.value}")
def __getattribute__(self, k):
print(f"Base get attr {self}, {k}")
return super().__getattribute__(k)
class Derived(Base):
value = "derived"
def foo(self):
print(f"Derived foo, {self.value}")
def __getattribute__(self, k):
print(f"Derived get attr {self}, {k}")
return super().__getattribute__(k)
def bar(self):
print("Derived bar")
print(super().value)
print(super().__getattribute__("value"))
d = Derived()
d.bar()
output 是:
Derived get attr <__main__.Derived object at 0x7fb0621dba90>, bar
Base get attr <__main__.Derived object at 0x7fb0621dba90>, bar
Derived bar
base
Base get attr <__main__.Derived object at 0x7fb0621dba90>, value
derived
super()
助手創建了一個代理,該代理修改了對自身的屬性訪問。 像這樣:
super().foo
在super
代理上查找foo
。super().__getattribute__
在super
代理上查找__getattribute__
。 值得注意的是,任何一個的結果都不知道它是通過super
查找的:對結果的任何進一步操作都會正常進行。 當查找的事物是數據描述符(如方法或屬性)時,它綁定到初始self
,而不是super
。
最終,查找super().__getattribute__
在通常情況下只會直接或通過包裝器找到標准object.__getattribute__
並將其綁定到self
。 因此,調用super().__getattribute__("foo")
等價於object.__getattribute__(self, "foo")
- 沒有super
參與查找.foo
。
比較表達式super().foo
和super().__getattribute__("foo")
如何被分解可能會有所幫助:
# super().foo
s = super()
foo = s.foo
# super().__getattribute__("foo")
s = super()
g = s.__getattribute__
foo = g("foo")
在第二種情況下, super
代理不參與查找.foo
。
更具體地說, super
在查找某些屬性/方法時基本上會跳過當前的 class。 在單個 inheritance 的情況下,這相當於在基礎 class 中查看。 這總是在上面發生。
In [38]: class Base:
...: value = "base"
...:
...: def foo(self):
...: print(f"Base foo, {self.value}")
...:
...: class Derived(Base):
...: value = "derived"
...:
...: def foo(self):
...: print(f"Derived foo, {self.value}")
...:
...:
...: def bar(self):
...: print(f"Derived bar {self.value}")
...: print(super().value)
...: print(super().__getattribute__("value"))
...: super().foo()
...: super().__getattribute__('foo')()
...:
...: d = Derived()
In [39]: Derived.mro()
Out[39]: [__main__.Derived, __main__.Base, object]
我懷疑讓你感到困惑的是:
super().__getattribute__("value")
好吧,在這種情況下, super()
跳過__main__.Derived
,在__main__.Base
中查找,沒有找到任何東西,然后最后在object
中找到__getattribute__
。 然后它不會神奇地使所有其他屬性訪問跳過Derived
。 事實上, object.__getattribute__
無論如何都會發生,注意:
In [40]: object.__getattribute__(d, 'value')
Out[40]: 'derived'
因此,當您將"foo"
傳遞給object.__getattribute__
時,這沒有什么不同,
In [41]: object.__getattribute__(d, 'foo')
Out[41]: <bound method Derived.foo of <__main__.Derived object at 0x7f927ba46460>>
現在,當您調用super().foo
時,它會跳過__main__.Derived
,查找__main__.Base
並找到一個foo
,因此本質上是:
In [42]: Base.foo(d)
Base foo, derived
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.