创建一个类级装饰器以自动添加属性

Gra*_*rdx 3 python properties python-2.7 python-3.x python-decorators

我想创建一个类级装饰器,它自动向对象添加属性,包括适当的getter和setter方法以及一个后备变量.例如:

@autoproperty("foo", can_get=True, can_set=True, allow_null=False, default_value=0)
@autoproperty("baz", can_get=True, can_set=False, allow_null=True, default_value=0)
@autoproperty("bar")
class SomeNonTrivialClass(object):
   def __init__(self):
      #lots of stuff going on here

   def discombobulate(self):
      #this is obviously a very trivial example
      local_foo = self.foo;

      if (local_foo > 10):
         raise RuntimeError("Foo can never be more than 10")
      else:
         #do whatever with foo

if __name__ == '__main__':
   test = SomeNonTrivialClass()

   test.foo = 5
   test.discombobulate()
   test.foo = 11
   test.discombobulate()
Run Code Online (Sandbox Code Playgroud)

我经常发现自己创建了许多"半复杂"的getter/setter(它们可以只使用一个简单的属性来完成,但它们需要默认值和null保护.我希望能够指定一个装饰器来完成繁重的工作在类的新实例上创建属性.

如果我在这种方法中偏离基础,我对同样可行的方法持开放态度.

任何帮助,将不胜感激.

我正在使用python 3.X和python 2.7,所以在任何一个中工作的东西都是首选但不是必需的.

更新:我在我正在寻找的内容中添加了更多种类.一般来说,我需要能够创建很多这些简单的自动属性(ala C#auto-property,但具有更大的灵活性).我不一定要公开后备存储,但我确实想确保对实例化对象(不一定是类)的检查显示已创建的属性.

Mar*_*ers 8

以下类装饰器会这样做:

def autoproperty(name, can_get=True, can_set=True, allow_null=False, default_value=0):
    attribute_name = '_' + name
    def getter(self):
        return getattr(self, attribute_name, default_value)
    def setter(self, value):
        if not allow_null and value is None:
            raise ValueError('Cannot set {} to None'.format(name))
        setattr(self, attribute_name, value)

    prop = property(getter if can_get else None, setter if can_set else None)

    def decorator(cls):
        setattr(cls, name, prop)
        return cls

    return decorator
Run Code Online (Sandbox Code Playgroud)

但你也可以创建一个属性工厂:

def autoproperty(attribute_name, can_get=True, can_set=True, allow_null=False, default_value=0):
    def getter(self):
        return getattr(self, attribute_name, default_value)
    def setter(self, value):
        if not allow_null and value is None:
            raise ValueError('Cannot set {} to None'.format(name))
        setattr(self, attribute_name, value)
    return property(getter if can_get else None, setter if can_set else None)
Run Code Online (Sandbox Code Playgroud)

然后在类中设置:

class SomeNonTrivialClass(object):
    # ...

    foo = autoproperty('_foo', can_get=True, can_set=True, allow_null=False, default_value=0)
Run Code Online (Sandbox Code Playgroud)

如果您需要创建多个属性(可能具有相互依赖性),那么类装饰器会更有意义.