使用Python类中的lambda函数动态添加getter / setter

时间:2013-10-23 11:26:05

标签: python class dynamic properties lambda

我希望能够创建具有从字典动态定义的实例属性的python对象。我至少知道两种方法,只需调用setattr(self, k, v)或者调用setattr(FooClass, k, property(lambda x: v))。第一个选项完全正常,但我不能让第二个选项做我想要的。请考虑以下代码

class A(object):
    def __init__(self, d):
        for k in d:
            setattr(A, k, property(lambda x: ('Value(%s)' % d[k], 'Key(%s)' % k, d)))

>>> a = A({'foo':'1','bar':'2'})
>>> a.foo
('Value(2)', 'Key(bar)', {'bar': '2', 'foo': '1'})

为什么a.foo不会在字典中返回foo的值? property个对象及其获取者是截然不同的。

>>> A.foo, A.bar
<property at 0x1106c1d60>, <property at 0x1106c1d08>
>>> A.foo.__get__
<method-wrapper '__get__' of property object at 0x1106c1d60>
>>> A.bar.__get__
<method-wrapper '__get__' of property object at 0x1106c1d08>

关于SO有很多相关问题,最好的问题是How to add property to a class dynamically?)和Eevee的回答。但这并没有完全解释这种行为。

这些处理类实例上的属性,而不是类

上的Property个对象

更新

感谢Martijn Pieters的帮助(answer)。答案在于lambda函数的范围。

>>> A.bar.fget.__closure__[0], A.foo.fget.__closure__[0]
<cell at 0x1106c63d0: dict object at 0x7f90f699fe80>, <cell at 0x1106c63d0: dict object at 0x7f90f699fe80>

工作版:

class A(object):
    def __init__(self, d):
        for k, v in d.items():
            setattr(A, k, property(lambda x, v=v, k=k: ('Value(%s)' % v, 'Key(%s)' % k, d)))

虽然这实际上修改了类的每个实例以具有相同的属性值。

课:

  

注意循环中的lambda函数

0 个答案:

没有答案