Python 动态创建指向属性的属性';s属性
我希望通过类的实例(无需继承)直接访问类的属性中的属性。所以基本上如果我有:Python 动态创建指向属性的属性';s属性,python,oop,properties,Python,Oop,Properties,我希望通过类的实例(无需继承)直接访问类的属性中的属性。所以基本上如果我有: class A: @property def foo(self): print("foo") @property def bar(self): print("bar") class B: def __init__(self): self._a = A() 我希望能够做b.bar,而不是做b.bar。基于此,我在B班尝试了以下方法
class A:
@property
def foo(self):
print("foo")
@property
def bar(self):
print("bar")
class B:
def __init__(self):
self._a = A()
我希望能够做b.bar
,而不是做b.bar
。基于此,我在B班尝试了以下方法:
class B:
def __init__(self):
self._a = A()
attrs = [attr for attr in dir(self._a)
if not callable(self._a.__getattribute__(attr))
and not attr.startswith("__")]
for attr in attrs:
setattr(self.__class__, attr,
property(lambda s: s._a.__getattribute__(attr)))
但在实例化和测试它时,我得到了一个奇怪的python时刻:
>>> b = B()
foo
bar
>>> b.foo
bar
>>> b.bar
bar
创建实例时会打印
bar
和foo
,因为执行\u a.\u getattribue\u(“foo”)
和\u a.foo
都会调用属性对象以获取值
在B
中设置的两个属性都使用lambdas从A
获取正确的属性。这是调用lambdas时的常见错误。由于attr
值是从外部范围继承的,因此在计算lambda时不会冻结该值。相反,它只是与封闭范围的attr
引用相同的attr
,并相应地更改。因此,所有lambda都将具有相同的attr
值
您可以定义一个方法。当普通属性查找失败时调用此方法
class B:
def __init__(self):
self._a = A()
def __getattr__(self, name):
return getattr(self._a, name)
b = B()
b.bar
# bar
b.foo
# foo
创建实例时会打印bar
和foo
,因为执行\u a.\u getattribue\u(“foo”)
和\u a.foo
都会调用属性对象以获取值
在B
中设置的两个属性都使用lambdas从A
获取正确的属性。这是调用lambdas时的常见错误。由于attr
值是从外部范围继承的,因此在计算lambda时不会冻结该值。相反,它只是与封闭范围的attr
引用相同的attr
,并相应地更改。因此,所有lambda都将具有相同的attr
值
您可以定义一个方法。当普通属性查找失败时调用此方法
class B:
def __init__(self):
self._a = A()
def __getattr__(self, name):
return getattr(self._a, name)
b = B()
b.bar
# bar
b.foo
# foo
你的第二个问题在这里有一个更详细的答案:你的第二个问题在这里有一个更详细的答案:谢谢你的回答和链接到另一个问题!我曾想过定义\uu getattr\uuu
,但在我看来,它会覆盖标准属性访问器。只有在标准访问器失败时才会调用它,这似乎是合乎逻辑的(至少对我来说是方便的)。与我最初的尝试相比,它最终也是一种更干净的代码。直到lambdas很好,但可能会产生危险的误导…谢谢你的回答和其他问题的链接!我曾想过定义\uu getattr\uuu
,但在我看来,它会覆盖标准属性访问器。只有在标准访问器失败时才会调用它,这似乎是合乎逻辑的(至少对我来说是方便的)。与我最初的尝试相比,它最终也是一种更干净的代码。直到lambdas很好,但可能会产生危险的误导。。。