This has been previously asked on Stack Overflow, but none of the answers seem to address exactly what I need to do. In my case, I want these dynamically-added properties to be a shortcut to store and read values from a database, so unfortunately it's not as easy as in this answer (where a lambda
function was used) or this one (where values where stored in a dictionary): I must call other methods of the class.
This is my attempt:
import operator
class Foo(object):
def get_value(self, name):
# read and return value from database
return -1
def set_value(self, name, value):
# store value in database
pass
def add_metadata_property(name):
getter = operator.methodcaller('get_value', name)
setter = operator.methodcaller('set_value', name) # gets value at runtime
setattr(Foo, name, property(getter, setter))
add_metadata_property('spam')
f = Foo()
f.spam # works!
f.spam = 2
The last line, however, raises:
Traceback (most recent call last):
File "<stdin>", line 27, in <module>
TypeError: methodcaller expected 1 arguments, got 2
Any ideas on how to achieve this?