Alan S
Alan S

Reputation: 325

Python - Should I use read-only @property without init or setter?

Trying to get my head around property decorators. I found a solution posted for setting read-only attributes here. Setting a private attribute and then providing a @property getter method makes sense if you can specify the attribute in init. But what about the case where you want to use a function to calculate a read-only attribute? Let's say you have a class that calls an attribute (e.g. state) from another class and then calculates a new value that will be made available as an attribute:

class MyState(object):
    def __init__(self, starting_value):
        self._foo = starting_value

    @property
    def foo(self):
        return self._foo

    @foo.setter
    def foo(self, value):
        self._foo = value


class MyClass(object):
    def __init__(self, name=None):
        self.name = name

    @property
    def bar(self):
        state = MyState.foo
        return id(state)

>mystate = MyState('chuff')
>myclass = MyClass()
>myclass.bar = 183097448L

In everything I have seen about property decorators, I have only see display methods reflected in the @property getter function, never functions that set the value of the variable. However, from reading the docs my understanding is that @setter requires an argument, which I don't have in this case. Is there any problem with calculating the read-only value of a class attribute in the @property getter method as opposed to simply passing an attribute that already exists?

Upvotes: 2

Views: 1849

Answers (1)

Evan
Evan

Reputation: 2357

There is no problem. @property is just doing less than you think. All it is is a bit of syntactic sugar to replace: a = foo.x with a = foo.x.getter(), and foo.x = bar with foo.x.setter(bar). That is, it allows you to replace attribute access with method calls. Those methods are allowed to do anything they like, which is the purpose of the property. I think you were being led astray by your first example where the property just passes through to an underlying hidden variable to make a psuedo-read-only variable. That is not really the standard use case. A very common example might be:

class Rectangle(object):
    def __init__(self, w, h):
        self.w = w
        self.h = h
    @property
    def area(self):
        return self.w * self.h

Area is a property of a rectangle, but it is derived from the width and height, and setting it doesn't really make any sense.

Upvotes: 2

Related Questions