In Python there is a simple way to make methods behave like properties using the @property decorator. But this only covers the getter side of things. What if you want to have a setter function for this “property”? Well there is a way. 🙂
Consider the following example:
import json
class SomeModel(object):
_foo = '{"foo":["bar", "baz"]}'
@property
def foo(self):
return json.loads(self._foo)
@foo.setter
def foo_setter(self, new_value):
self._foo = json.dumps(new_value)
m = SomeModel()
Now you can use the
foo()
method like a property.
>>> m.foo
{u'foo': [u'bar', u'baz']}
This is a simple way to have a property contain a JSON string but access it as a Python dict, doing (de-)serialization on the fly.
So what if you want to set the value using a dict?
>>> m.foo = ["foo", "bar"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
This is can easily trip up even seasoned Python developers. I’ve read code that did exactly this and I (as a novice) had to find out why the code failed. m(
The solution is quite simple … but “non-obvious” (as in: I wouldn’t have thought of that without consulting the docs) 🙁
@foo.setter
def foo(self, new_value)
self._foo = json.dumps(new_value)
Notice the method name? The setter and the getter methods have to have the same name!