我正在尝试使用变量方法名称来调用超类的方法。通常,我会看到以下两行代码是等效的:
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
。
答案 0 :(得分:5)
不要使用__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参考。)
答案 1 :(得分:0)
获取example
对象的B
属性会生成B.example
的绑定副本。调用此方法将导致递归错误。你打电话给A.__getattribute__()
是无关紧要的;你还有B
个对象。