动态地向类添加属性 [英] Dynamically adding a property to a class

查看:57
本文介绍了动态地向类添加属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

之前在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆