问题描述
我想通过装饰器向类中添加许多虚拟属性,如下所示:
I would like to add many dummy-properties to a class via a decorator, like this:
def addAttrs(attr_names):
def deco(cls):
for attr_name in attr_names:
def getAttr(self):
return getattr(self, "_" + attr_name)
def setAttr(self, value):
setattr(self, "_" + attr_name, value)
prop = property(getAttr, setAttr)
setattr(cls, attr_name, prop)
setattr(cls, "_" + attr_name, None) # Default value for that attribute
return cls
return deco
@addAttrs(['x', 'y'])
class MyClass(object):
pass
不幸的是, decoarator似乎保留了 attr_name
的引用而不是其内容。因此, MyClass.x
和 MyClass.y
都访问 MyClass._y
:
Unfortunately, the decoarator seems to keep the reference of attr_name
instead of its content. Therefore, MyClass.x
and MyClass.y
access both MyClass._y
:
a = MyClass()
a.x = 5
print a._x, a._y
>>> None, 5
a.y = 8
print a._x, a._y
>>> None, 8
要获得预期的行为我必须更改什么?
What do I have to change to get the expected behavior?
推荐答案
您几乎可以正常使用。只有一尼特。创建内部函数时,将 attr_name
的当前值绑定到getter和setter函数中:
You almost had it working. There is just one nit. When creating the inner functions, bind the current value of attr_name
into the getter and setter functions:
def addAttrs(attr_names):
def deco(cls):
for attr_name in attr_names:
def getAttr(self, attr_name=attr_name):
return getattr(self, "_" + attr_name)
def setAttr(self, value, attr_name=attr_name):
setattr(self, "_" + attr_name, value)
prop = property(getAttr, setAttr)
setattr(cls, attr_name, prop)
setattr(cls, "_" + attr_name, None) # Default value for that attribute
return cls
return deco
@addAttrs(['x', 'y'])
class MyClass(object):
pass
这会产生预期结果:
>>> a = MyClass()
>>> a.x = 5
>>> print a._x, a._y
5 None
>>> a.y = 8
>>> print a._x, a._y
5 8
希望这会有所帮助。装饰快乐:-)
Hope this helps. Happy decorating :-)
这篇关于如何使用使用名称列表作为参数的装饰器向类添加属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!