Reputation: 325
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
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