本文介绍了为什么str(super(B,b))不等于super(B,b).__ str __()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  • 假设 A B 和<$的父类c $ c> b 是 B 的实例。然后可以使用: super(B,b).method()

  • Assume A is the parent class of B and b is an instance of B. Then an overriden method of A 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 __()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 07:56