动态地向类添加属性 [英] Dynamically adding a property to a class
问题描述
之前在 Stack Overflow 上已经问过这个问题,但似乎没有一个答案能准确地解决我需要做的事情.就我而言,我希望这些动态添加的属性成为从数据库中存储和读取值的快捷方式,因此不幸的是,这并不容易 就像在这个答案中(其中使用了 lambda
函数)或 这个(其中值存储在字典中的位置):我必须调用该类的其他方法.
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.
这是我的尝试:
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
然而,最后一行提出:
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?
推荐答案
我不知道你为什么在这里使用 operator.methodcaller
.当您调用 f.spam=2
时,它会调用 setter.setter = operator.methodcaller('set_value', name)
表示 setter(r) = r.set_value(name)
.在你的情况下毫无意义.
I don't know why you use operator.methodcaller
here.
When you call f.spam=2
, it will invoke setter.
setter = operator.methodcaller('set_value', name)
means setter(r) = r.set_value(name)
. Make no sense in your case.
我建议你这样写,使用@classmethod
:
I suggest you write this way, using @classmethod
:
class Foo(object):
@classmethod
def get_value(self, name):
# read and return value from database
return -1
@classmethod
def set_value(self, name, value):
# store value in database
pass
def add_metadata_property(name):
setattr(Foo, name, property(Foo.get_value, Foo.set_value))
add_metadata_property('spam')
f = Foo()
f.spam # works!
f.spam = 2
如果这对您有帮助,请确认为答案.谢谢!
If this helped you, please confirm it as the answer. Thanks!
这篇关于动态地向类添加属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!