我想创建一个类级装饰器,它自动向对象添加属性,包括适当的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()
我经常发现自己创建了许多“半复杂”的getter / setter(它们只需要一个简单的属性即可完成,但它们需要默认值和null保护。我希望能够指定一个装饰器在类的新实例上创建属性的繁重工作。
如果我不采用这种方法,我愿意接受同样可行的方法。
任何帮助都将不胜感激。
我正在使用python 3.X和python 2.7,所以在任何一个中工作的东西都是首选但不是必需的。
更新:我在我想要的内容中添加了更多种类。一般来说,我需要能够创建很多这些简单的自动属性(ala C#auto-property,但具有更大的灵活性)。我不一定要公开后备存储,但我确实想确保对实例化对象(不一定是类)的检查显示已创建的属性。
答案 0 :(得分: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
但您也可以创建一个属性工厂:
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)
然后在类中设置:
class SomeNonTrivialClass(object):
# ...
foo = autoproperty('_foo', can_get=True, can_set=True, allow_null=False, default_value=0)
如果您需要创建多个属性(可能具有相互依赖性),那么类装饰器会更有意义。
答案 1 :(得分:1)
这是一种更直接的方法,可以避免装饰课程。
class SomeNonTrivialClass(object):
def __init__(self):
#lots of stuff going on here
foo = autoproperty("foo", can_get=True, can_set=True, allow_null=False, default_value=0)
def discombobulate(self):
#this is obviously a very trivial example
local_foo = self.foo;
class autoproperty(property):
def __init__(self, name, can_get, can_set, allow_null, default_value):
...