首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态创建指向属性属性的属性

动态创建指向属性属性的属性
EN

Stack Overflow用户
提问于 2018-07-02 11:54:50
回答 1查看 33关注 0票数 0

我希望通过类的实例(而不是继承)使类的属性可以直接访问。所以基本上如果我有:

代码语言:javascript
复制
class A:
    @property
    def foo(self):
        print("foo")
    @property
    def bar(self):
        print("bar")

class B:
    def __init__(self):
        self._a = A()

我不想做b._a.bar,而是希望能够做b.bar。基于this answer here,我在B类中尝试了以下几点:

代码语言:javascript
复制
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时刻:

代码语言:javascript
复制
>>> b = B()
foo
bar
>>> b.foo
bar
>>> b.bar
bar
  1. 为什么在创建实例时同时打印“foo”和“bar”?
  2. “foo”属性如何指向与“bar”相同的getter?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-02 12:08:49

创建实例时会打印barfoo,因为执行_a.__getattribute__("foo")_a.foo都会调用属性对象来获取值。

B中设置的两个属性都使用lambda从A获得正确的property。当调用lambda时,这是一个常见的错误。因为attr值是从外部范围继承的,因此在计算lambda时不会冻结它。相反,它只是与封闭作用域的attr引用相同的attr,并进行了相应的更改。因此,所有的lambda都将具有相同的attr值。

您可以定义一个B.__getattr__方法。当普通属性查找失败时,将调用此方法。

代码语言:javascript
复制
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
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51135620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档