本文介绍了如何使用使用名称列表作为参数的装饰器向类添加属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 :-)

这篇关于如何使用使用名称列表作为参数的装饰器向类添加属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 18:52