Python 为什么调用super().foo和super()之间有区别
我原以为super()总是尝试在基类中使用方法(或属性)运行,直到遇到一个用例,它使用Python 为什么调用super().foo和super()之间有区别,python,python-3.x,super,Python,Python 3.x,Super,我原以为super()总是尝试在基类中使用方法(或属性)运行,直到遇到一个用例,它使用super()获取子类的属性。简化代码如下所示 class Base: value = "base" def foo(self): print(f"Base foo, {self.value}") class Derived(Base): value = "derived" def foo(self
super()获取子类的属性。简化代码如下所示
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()
输出
Derived bar derived
base
derived
Base foo, derived
Derived foo, derived
这有点超出了我之前的理解,只是\uuu getattribute\uu
是一个例外吗?我不能得到任何进一步的细节与此,希望任何人都可以帮助我更清楚地理解这一点,谢谢
编辑以遵循\uuuu getattribute\uuuu
问题,如下所示:
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()
输出为:
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
Derived get attr,bar
基本属性
导杆
基础
基本获取属性,值
衍生
更具体地说,super
在查找某些属性/方法时基本上跳过了当前类。在单继承的情况下,这相当于查找基类。这总是发生在上面
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()
跳过\uuuuuu main\uuuuuu.Derived
,在\uuuuuuuu main\uuuuuuuuuuu.Base
中查找,没有找到任何内容,最后在对象中查找\uuuuuuuuu getattribute\uuuuuuu
。然后,它不会神奇地使其他所有属性访问跳过派生。实际上,object.\uuuu getattribute\uuuu
无论如何都会发生,注意:
因此,当您将“foo”
传递给对象时,这一点也没有什么不同
In [41]: object.__getattribute__(d, 'foo')
Out[41]: <bound method Derived.foo of <__main__.Derived object at 0x7f927ba46460>>
super()。因此:
super().foo
在super
代理上查找foo
super()
值得注意的是,任何一个的结果都不知道它是通过super
查找的:对结果的任何进一步操作都将正常进行。当查找的对象是数据描述符(如方法或属性)时,它绑定到初始的self
,而不是super
最后,在通常情况下,查找super()。\uuuuu getattribute\uuuuu
只会直接或通过包装器找到标准的对象。\uuuu getattribute\uuuuu
并将其绑定到self
。因此,调用super()。\uuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(“foo”)
相当于对象
比较表达式super().foo
和super()。\uuuu getattribute\uuuu(“foo”)
的分解方式可能会有所帮助:
#super().foo
s=超级()
foo=s.foo
#超级()
s=超级()
g=s.。\uu getattribute__
foo=g(“foo”)
在第二种情况下,super
代理不参与查找.foo
它总是在基类中获取属性/方法(而是方法解析顺序中的下一个类)。你认为super
到底在哪里做不到这一点?也许,这会揭示:object.\uuuu getattribute\uuud(value')
最近有人发布了一个非常类似的问题:@juanpa.arrivillaga:我一直认为super()
实际上返回了基类的对象。我花了很长时间才明白,它只是一个查找一次属性的代理。@SergeBallesta你从哪里得到这个它只是一个查找一次属性的代理
?我想让我困惑的是为什么super().xxx
没有调用对象。
谢谢,我仍然对super()有点困惑。
当你说没有找到任何东西,然后最后,在object
中找到了
中的,Base
中没有值
属性,为什么找不到它?我在Functiontbar
中尝试了另一种方法,当我使用super()时,bar
会因为AttributeError而失败:“super”对象没有属性“bar”
,为什么它不会返回到对象。uuu_ugetAttribute_uud,'bar')
?@kuixiongvalue
是不相关的,super()
正在解析\uuuu getattribute\uuu
,而不是值
super()。\uuuuGetAttribute\uuuuuuuuuuuuuuuuuuuu是对象。\uuuuuuuuuuuuuuuu属性
。谢谢,我想现在我得到了一个表面的原因,super()。\uuuuuuuuuuuGetAttribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是你知道为什么super().value
不像d.value
那样调用\uuu getattribute\uuuu
吗?@kuixiong它确实调用super
的\uuuu getattribute\uuuuu
因为super().value
正在调用super
对象上的.value
。为什么?我以为\uuuuuuGetAttribute\uuuuuu
会在您每次访问一个实例的属性时被调用,谢谢,您的回答真的让我明白了,我从来没有意识到s.\uuuuuuGetAttribute\uuuuuuuuuu
和s.\uuuuuuuu getattribute('foo')
在这种情况下是两个步骤(只是忘记了当与此super()
调用结合使用时,函数
也是一个可调用对象)。
In [41]: object.__getattribute__(d, 'foo')
Out[41]: <bound method Derived.foo of <__main__.Derived object at 0x7f927ba46460>>
In [42]: Base.foo(d)
Base foo, derived