为什么str(super(B,b))不等于super(B,b).__ str __()? [英] Why is str(super(B, b)) not equivalent to super(B, b).__str__()?

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

问题描述

  • 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().

文档说明 str(object)在基本调用中返回 object .__ str __()

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:


请注意 super()实现为显式点状属性查找的绑定过程的一部分,例如 super().__ getitem __(name)。它通过实现自己的 __ getattribute __()方法来实现,它以可预测的顺序搜索类,支持协作多重继承。因此,对于使用语句或运算符(例如 super()[name] )的隐式查找, super()未定义。

Note that super() is implemented as part of the binding process for explicit dotted attribute lookups such as super().__getitem__(name). It does so by implementing its own __getattribute__() method for searching classes in a predictable order that supports cooperative multiple inheritance. Accordingly, super() is undefined for implicit lookups using statements or operators such as super()[name].


推荐答案

str() doesn'通过常规属性查找过程查找 __ str __ 方法。相反,它直接搜索 __ str __ 方法在其参数的类层次结构的 __ dict __ 中,在 MRO 订单。这找到 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 __ <的代理/ code>转发它。因此,任何不通过<​​code> __ 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()甚至避免了类上的函数的正常属性查找过程。它仅检查 tp_str (如果这是NULL,那么 tp_repr )班级的插槽。所以它甚至不调用元类的 __ 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 __()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆