Python对象可以具有嵌套属性吗?

12

我有一个定义如下的对象

class a():
    @property
    def prop(self):
        print("hello from object.prop")
        @property
        def prop1(self):
            print("Hello from object.prop.prop")

当我打电话时

>>> obj = a()
>>> obj.prop
hello from object.prop
>>> obj.prop.prop

我得到了以下的回溯错误:

Traceback (most recent call last):
  File "object_property.py", line 13, in <module>
    a.prop.prop1
AttributeError: 'NoneType' object has no attribute 'prop1'

我想了解的是,是否可以为对象定义嵌套属性?


1
该属性必须返回第二个属性。仅仅在第一个属性中声明第二个属性并不会使其成为属性。 - ApproachingDarknessFish
1
@ValekHalfHeart:返回一个属性对象是行不通的。你需要返回一个包含属性对象实例的类的实例。 - Blckknght
2个回答

12

这个回溯是因为你的属性没有 return 语句,因此返回了 NoneType,显然不能具有自己的属性。你的属性可能需要返回一个不同类的实例,该实例具有自己的 prop 属性。像这样:

class a():
    def __init__(self):
        self.b = b()
    @property
    def prop(self):
        print("hello from object.prop")
        return self.b

class b():
    @property
    def prop(self):
        print("Hello from object.prop.prop")

x = a()
print x.prop.prop
>> hello from object.prop
>> Hello from object.prop.prop
>> None

1
这不是问题中所要求的“嵌套属性”。 - hago
@hago,我认为是这样的。因为它确实达到了问题所要解决的目标。对于我来说也很有效,因为我之前也有类似的问题。 - Jeroen Vermunt

4
一般情况下,无法包装除自身以外的对象属性访问。当然,并没有像嵌套语法一样可以整洁地嵌套的东西(你可以在属性函数中声明一个类,但很快就会变得丑陋)。也就是说,在表达式obj.prop_a.prop_b 中,顶层对象obj 无法直接控制发生在另一个对象上的prop_b 属性访问。
例如,考虑以下语句序列:
foo = obj.prop_a
bar = foo.prop_b
bar 的赋值与 obj.prop_a.prop_b 相同,但该语句并没有直接引用到 obj

如果您愿意涉足包装器对象的混沌世界,可能可以实现您想要的内容,但这种方法不会像基本属性那样简洁。就像 @qwwqwwq 的答案中一样,您可以让 obj.prop_a 返回一个类的实例,该类具有自己的 @property 修饰函数 prop_b

您甚至可以在 prop_a 函数内部声明该类,如果您不担心外部世界能够访问它。但对于任何复杂的内容,它将变得非常混乱。

相反,考虑一下通过直接在 obj 上公开属性或方法(例如 obj.prop_a_b)是否更好地暴露了您想要从 obj.prop_a.prop_b 访问的内容。我猜您会发现这种方式的设计更好。


你认为Style属性及其属性是否可以在ipywidgets中没有这样的技巧设计得更好? - garej

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接