动态公开对象属性

时间:2018-06-21 17:19:35

标签: python

map

我想定义一种在Qux上调用任何属性并使它返回In [1]: class Foo(): ...: pass ...: In [2]: class Qux(): ...: def __init__(self): ...: item = Foo() ...: In [3]: a = Foo() In [4]: setattr(a, 'superpower', 'strength') In [5]: a.superpower Out[5]: 'strength' In [6]: b = Qux() In [7]: b.item = a In [8]: b.superpower --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-8-cf0e287006f1> in <module>() ----> 1 b.superpower AttributeError: Qux instance has no attribute 'superpower' 的方式。换句话说,要让getattr(Qux.item, <attributename>)没有明确定义的情况下工作:

b.superpower

我也不想失去对在@property def superpower(self): return getattr(self.item, 'superpower') 上定义的任何属性的访问,而是要公开在Qux上定义的属性(如果它们也不也在Foo上)。 / p>

2 个答案:

答案 0 :(得分:2)

定义__getattr__

class Qux(Foo):
    def __init__(self):
        self.item = Foo()
    def __getattr__(self, attr):
        return getattr(self.item, attr)

__getattr__每当有人尝试查找对象的属性时都会被调用,但通过常规方法失败。

它有一个名为__getattribute__的邪恶双胞胎,总是被召唤,必须非常谨慎地使用。

答案 1 :(得分:2)

您可以通过定义__getattr__而不是使用属性来实现。对于使用标准协议找不到 的任何属性,Python将调用类的__getattr__方法。

此外,要存储item,必须将其分配给self.item,否则将其抛出在Qux.__init__的末尾。

最后,在这种情况下,从Foo继承似乎是不必要的。

class Foo:
    def __init__(self, superpower):
        self.superpower = superpower

class Qux:
    def __init__(self, foo_item):
        self.item = foo_item

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

示例

f = Foo('strenght')
q = Qux(f)
print(q.superpower) # 'strenght'

继承

尽管如此,看来您半尝试通过继承来实现它。如果您的意图是通过Qux扩展Foo的行为,那么继承就可以了。

class Foo:
    def __init__(self, superpower):
        self.superpower = superpower

class Qux(Foo):
    def __getattr__(self, name):
        return getattr(self.item, name)

示例

q = Qux('strenght')
print(q.superpower)  # 'strenght'