问题描述
-
假设
A
是B
和<$的父类c $ c> b 是B
的实例。然后可以使用:super(B,b).method()
。
Assume
A
is the parent class ofB
andb
is an instance ofB
. Then an overriden method ofA
can be called with super:super(B, b).method()
.
文档说明。
The docs state "str(object)
returns object.__str__()
" in its basic invocation.
应该遵循 str(super(B,b))== super(B,b).__ str __()
,但是情况并非如此():
It should follow that str(super(B, b)) == super(B, b).__str__()
, but that's not the case (interactive version):
class A:
def __str__(self):
return "A"
class B(A):
def __str__(self):
return "B"
b = B()
b_super = super(B, b)
print(str(b_super)) # "<super: <class 'B'>, <B object>>"
print(b_super.__str__()) # "A"
那我去哪了错误?超级机制不适用于魔术方法吗?在这种情况下, str
不会调用 __ str __
吗?是否与此段落有关:
So where did I go wrong? Does the super mechanism not work for magic methods? Does str
not invoke __str__
in this case? Is it related to this paragraph:
推荐答案
str()
doesn'通过常规属性查找过程查找 __ str __
方法。相反,它直接搜索订单。这找到 super .__ str __
,它提供< super:< class'B'>,< B object>>
。
str()
doesn't look up the __str__
method through the normal attribute lookup procedure. Instead, it performs a direct search for the __str__
method in the __dict__
s of its argument's class hierarchy, in MRO order. This finds super.__str__
, which gives "<super: <class 'B'>, <B object>>"
.
然而,当您手动查找 b_super .__ str __
时,会通过 super .__ getattribute __
,钩子 super
用于提供其特殊的属性查找行为。通过 __ getattribute __
查找将解析为 A .__ str __
并调用它。
However, when you look up b_super.__str__
manually, that goes through super.__getattribute__
, the hook super
uses to provide its special attribute lookup behavior. The lookup through __getattribute__
will resolve to A.__str__
and call that.
考虑这个类,它说明了差异(我希望):
Consider this class, which illustrates the difference (I hope):
class B(object):
def __init__(self, other):
self.other = other
def __getattribute__(self, name):
if name == 'other':
return object.__getattribute__(self, 'other')
elif name == '__str__':
return getattr(self.other, name)
else:
return name
def __str__(self):
return 'fun'
>>> str(B(1)) # calls B.__str__ because it doesn't invoke __getattribute__
'fun'
>>> B(1).__str__() # calls B.__getattribute__ to look up the __str__ method which returns (1).__str__
'1'
在这种情况下的问题以及 super
的问题是这些是依赖于 __ getattribute __ 转发它。因此,任何不通过 __ getattribute __
的函数或方法都不会转发。并且 str()
就是这样一个函数。
The problem in this case and likewise for super
is that these are proxies that rely on __getattribute__
to forward it. So any function or method that doesn't go through __getattribute__
doesn't forward. And str()
is such a function.
仅供参考完整性,因为它在评论和其他答案中被提及。
Just for completeness because it was mentioned in the comments and the other answer.
但是 str(x)
isn等于类型(x).__ str __(x)
因为 str()
甚至避免了类上的函数的正常属性查找过程。它仅检查(如果这是NULL,那么)班级的插槽。所以它甚至不调用元类的 __ getattribute __
, type(x).__ str __(x)
会做:
But str(x)
isn't equivalent to type(x).__str__(x)
because str()
even avoids the normal attribute lookup procedure of the "function on the class". It only checks the tp_str
(or if that's NULL the tp_repr
) slot of the class. So it doesn't even invoke __getattribute__
of the metaclass, which type(x).__str__(x)
would do:
class A(type):
def __getattribute__(self, name):
print(name)
if name == '__str__':
return lambda self: 'A'
else:
return type.__getattribute__(self, name)
class B(metaclass=A):
def __str__(self):
return 'B'
>>> b = B()
>>> str(b)
'B'
>>> type(b).__str__(b)
__str__
'A'
但是,由于缺少元类,可能有助于将 str(x)
视为等同于类型(x ).__ STR __(x)的
。但虽然(可能)有帮助,但这是不正确的。
However in the absense of a metaclass it might be helpful to think of str(x)
as equivalent to type(x).__str__(x)
. But while (potentially) helpful it's not correct.
这篇关于为什么str(super(B,b))不等于super(B,b).__ str __()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!