2012-09-07 34 views
3

我想实现一个类,其中尝试访问当前类或其任何祖先中不存在的任何属性的尝试将试图从成员访问这些属性。以下是我正在尝试做的简单版本。为什么__getattr__不会因缺失“神奇”调用的方法而被调用?

class Foo: 
    def __init__(self, value): 
     self._value = value 

    def __getattr__(self, name): 
     return getattr(self._value, name) 

if __name__ == '__main__': 
    print(Foo(5) > Foo(4)) # should do 5 > 4 (or (5).__gt__(4)) 

然而,这会产生一个TypeError。即使使用operator模块的attrgetter类也会执行相同的操作。我正在看the documentation regarding customizing attribute access,但我没有觉得它很容易阅读。我怎样才能解决这个问题?

+1

非常感谢您的简单示例 - 但是Bar的重点在哪?没有它,你的问题就没有什么不同。 –

+0

@ ron.rothman,*耸耸肩*这是我的代码正在做的基本要点。我进一步简化了它。 :) –

+0

此外,属性是字符串,而不是整数。你使用'Foo(5)'表示你可能混淆了这两者。 –

回答

7

如果我理解正确的话,你在做什么是正确的,但它仍然不会为你想用它来什么工作。原因是隐式魔法查找不使用__getattr__(或__getattribute__或任何其他类似的东西)。这些方法实际上必须明确地存在于它们的神奇名字中。你的方法适用于普通属性,但不适用于魔术方法。 (请注意,如果你这样做Foo(5).__lt__(4)明确,它会工作,这仅仅是隐含的“神奇”查找---比如,调用__lt__当使用<)---被阻止)

This post描述的方法进行。使用元类自动生成魔术方法。如果您只需要某些方法,则可以手动在类上定义它们。

+0

有趣。不过,我想知道是否可以手动创建这些方法的方式更不可读。 – ThiefMaster

+0

嗯。而不是从实现这些的自定义类中继承,也许使用装饰器会更好?只是看看我所有的选择。 –

+0

@mgilson,如果'Foo'“实现了''__gt__'和'__lt__',不应该吗? –

1

__*__方法将不会工作,除非它们确实存在 - 因此__getattr____getattribute__都不允许您代理这些调用。您必须手动创建每一种方法。

是的,这确实涉及到相当多的副本&粘贴。是的,在这种情况下它完全没问题。

您可能可以使用werkzeug LocalProxy类作为基础,而不是您自己的类;你的代码看起来像这样用LocalProxy时:

print(LocalProxy(lambda: 5) > LocalProxy(lambda: 4)) 
相关问题