Question

I have an object defined as follows

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

When I call

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

I get the following traceback error

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

What I am trying to figure out is if I can define nested properties for objects?

No correct solution

OTHER TIPS

The traceback is because your property doesn't have a return statement, hence it returns NoneType, which obviously can't have attributes of its own. Your property would probably need to return an instance of a different class, that has its own prop attribute. Something like this:

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

In general, no, there's no way to wrap up the attribute access of an object other than yourself. Certainly there's nothing with a syntax that can be nested neatly (you can declare a class within your property function, but it gets ugly fast).

That is, in an expression like obj.prop_a.prop_b, the top level object obj can't directly control what happens with the prop_b attribute access, which is happening on a different object.

As an example, consider the following sequence of statements:

foo = obj.prop_a
bar = foo.prop_b

The value assigned to bar is the same as obj.prop_a.prop_b, but that statement didn't directly refer to obj at all.

If you're willing to get into the murky world of wrapper objects, it might be possible to do what you want, but it's not going to be as neat as a basic property. Like in @qwwqwwq's answer, you can have obj.prop_a return an an instance of a class with its own @property decorated function prop_b.

You could even declare the class inside of the prop_a function, if you weren't worried about it being accessible from the outside world. For anything complicated though, it will get messy fast.

Instead, consider if what you want to be accessible through obj.prop_a.prop_b could be better exposed through a property or method directly on obj, such as obj.prop_a_b. I suspect you'll find a much better design this way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top