python - 如何使用将名称列表作为参数的装饰器向类添加属性?

标签 python decorator

我想通过装饰器向类添加许多虚拟属性,如下所示:

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.xMyClass.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/

相关文章:

python - Django:限制用户仅访问自己的对象

python - 为什么 tensorflow 常数是可馈送的 true

python - 如何根据 Numpy 中另一个数组的分组值生成数组?

python - 我如何模拟 python 构造函数的一部分只是为了测试?

java - 如何从 Java 中的装饰器模式中删除装饰对象

javascript - 未知选项 : package. json.presets

python - .quantize() 的小数舍入不使用原始上下文

zend-framework - zend 表单装饰器

python - 装饰器类和装饰器函数的区别

带有选项的 Python 装饰器