I want to set a read-only attribute inside a class method.
I have already tried this:
class Foo(object):
def __init__(self, v):
self._set('_v', v)
def _set(self, attr, v):
setattr(self, attr, v)
setattr(Foo, attr[1:], property(lambda self: getattr(self, attr)))
but it is horrible. Is there another way? What I need to do is setting the property:
class Foo(object):
def __init__(self, v):
self._v = v
@ property
def v(self):
return self._v
>>> f = Foo(42)
>>> f.v
42
>>> f.v = 41
AttributeError: can't set attribute ## This is what I want: a read-only attribute
but I need to do it inside a method. Is there another way?
Thank you,
rubik
P.S. I have already checked this post, but it does not solve my problem: Using Python property() inside a method
EDIT: I cannot use property
, because I want to set it inside a method. I can use property
only from outside:
class Foo(object):
def __init__(self, v):
self._v = v
@ property
def v(self):
return self._v
## ...OR
def getv(self):
return self._v
v = property(getv)
And I can't do that because I don't know the property name and I have to set it dynamically. Something like this:
class Foo(object):
def __init__(self, v):
self._set_property_from_inside('v', v)
>>> f = Foo(42)
>>> f.v
42
property() is exactly the solution here. Why shouldn't is solve your problem? Overriding the setter an getter method allows you exactly what you want and need: full control over the property.
Please check with official documentation like
http://docs.python.org/library/functions.html#property
in order to understand the whole story.
I've thought of what I think is a cleaner solution for implementing a pure read-only attribute, if that's all you want. It's a variant of the solution tangentstorm gave, but dispenses with the need for a
__getattr__
method altogether.It works like this:
Making a read-only attribute read-write again is easy:
In my first attempt at writing this idea I used
self.__readonly
instead ofself.readonly
, but that leads to a problem with actually setting the__readonly
attribute, since I'd need to do un-munge the "private" attribute to check for its presence (hasattr(self, "_Foo__readonly")
), and this is discouraged.Then:
I think you're looking for python descriptors.
Here you can do whatever you want to control access in the
__get__
and__set__
methods. If you call obj.get_v in__get__
and obj.set_v in__set__
, this is very close to the actual implementation of a property, as you can see in the above link.Edit: Fixed. I should have read that page better myself. Quoting:
So if you put descriptors in the
__dict__
of the instance, they'll simply get overwritten when you set that attribute to a new value.