【问题标题】:Calling variable superclass method调用变量超类方法
【发布时间】:2011-04-20 08:39:55
【问题描述】:

我正在尝试通过使用变量方法名称来调用超类的方法。通常,我会看到以下两行代码是等效的:

someObj.method()
someObj.__getattribute__( 'method' )()

事实上我相信,这也是我使用第一行时实际发生的情况。然而,在下面的例子中,第二行产生了一个奇怪的问题。

我使用super构造一个超对象,调用超类的方法。直接按预期执行,但使用__getattribute__ 先获取方法,会导致无限循环,一次又一次地调用子类的方法。

见以下代码:

class A:
    def example ( self ):
        print( 'example in A' )

class B ( A ):
    def example ( self ):
        print( super( B, self ).example )
        print( super( B, self ).__getattribute__( 'example' ) )
        super( B, self ).example()
        #super( B, self ).__getattribute__( 'example' )()

        print( 'example in B' )

x = B()
x.example()

如果您运行该代码,一切都会按预期运行,并且您应该得到类似以下的输出:

<bound method B.example of <__main__.B object at 0x01CF6C90>>
<bound method B.example of <__main__.B object at 0x01CF6C90>>
example in A
example in B

所以这两种方法,一种是直接访问,另一种是通过__getattribute__,看起来是一样的。但是,如果您将方法调用替换为已注释掉的行,则会出现递归运行时错误。

为什么会发生这种情况,更重要的是,当我使用工作行时,我如何才能以与 python 内部相同的方式实际访问该方法?

编辑

当我认为我已经尝试了所有方法时,我发现它正在工作:

super.__getattribute__( super( B, self ), 'example' )()

实际上等于super( B, self ).example

【问题讨论】:

  • 你不应该使用getattr(obj, 'attrname') 而不是obj.__getattr__('attrname') 吗?
  • 哦,你是对的!出于某种原因,我认为obj.x 将等同于obj.__getattribute__( 'x' ),而实际上它等同于getattr( obj, 'x' )。不过,getattr 到底有什么魔力呢? – 此外,您可能想将其发布为答案。

标签: python super superclass


【解决方案1】:

不要为此使用__getattribute__:它不会像您认为的那样做。 (它是 Python 机器的一个专门部分,主要用于实现新的属性访问魔法。)

对于正常的属性访问,使用 getattr / setattr / delattr 内置函数:

self.example           == getattr(self, 'example')
super(B, self).example == getattr(super(B, self), 'example')

(如果您想了解 __getattribute__ 的作用,请阅读 Descriptor HowTo Guide 和 Python Data model 参考。)

【讨论】:

    【解决方案2】:

    获取B 对象的example 属性会生成B.example 的绑定副本。调用它会导致递归错误。你打电话给A.__getattribute__() 是无关紧要的;你还有一个B 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-19
      • 2023-03-19
      • 1970-01-01
      • 2018-11-17
      • 1970-01-01
      • 2011-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多