我想通过装饰器向类添加许多虚拟属性,如下所示:
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
:
a = MyClass()
a.x = 5
print a._x, a._y
>>> None, 5
a.y = 8
print a._x, a._y
>>> None, 8
我必须更改什么才能获得预期的行为?
最佳答案
您几乎成功了。只有一个尼特。创建内部函数时,将 attr_name
的当前值绑定(bind)到 getter 和 setter 函数中:
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
希望这对您有所帮助。装饰愉快:-)
关于python - 如何使用将名称列表作为参数的装饰器向类添加属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9125832/