是否有更快的方法将@property用于类中的多个属性?

时间:2015-01-14 17:56:47

标签: python python-decorators

是否有更短的方法为类添加属性并进行设置验证而不是使用@property方法?以下代码是一个示例。我希望能够在类中的许多属性将被验证,并且这样做似乎是多余的。非常感谢任何建议!

def valid_max(max_val=10):
"""
Decorator to check for valid value of a number between min and max

"""
def valid_value_decorator(func):
    def func_wrapper(wraps,value):
        if value <= max_val:
            return func(wraps,value)
        else:
            raise(Exception('Value above max'))
    return func_wrapper
return valid_value_decorator

class Test(object):
    def __init__(self):
        self._x=0
        self._y=0

    @property
    def x(self):
        return self._x

    @x.setter
    @valid_max(max_val=10)
    def x(self,data):
       self._x = data

    @property
    def y(self):
        return self._y

    @y.setter
    @valid_max(max_val=10)
    def y(self,data):
        self._y = data

1 个答案:

答案 0 :(得分:2)

您可以编写factory function来生成属性:

def CustomProp(name, maxval):
    name = '_' + name

    @property
    def pro(self):
        return getattr(self, name)

    @pro.setter
    def pro(self, val):
        if not isinstance(val, (int, float)):
            # In Python 2 -> '' > 10(or any number) is True, so better check the type as well.
            raise TypeError('Only integers and floats are allowed.')
        if val > maxval:
            raise ValueError("Value {!r} above maximum {!r}.".format(val, maxval))
        else:
            setattr(self, name, val)

    return pro

class Test(object):
    x = CustomProp('x', 10)
    y = CustomProp('y', 20)
    z = CustomProp('z', 30)

    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

<强>演示:

>>> t = Test(1, 2, 3)
>>> t.x = 10
>>> t.y = 11
>>> t.x = 11

Traceback (most recent call last):
  File "<pyshell#41>", line 1, in <module>
    t.x = 11
  File "/home/ashwini/py/so.py", line 14, in pro
    raise ValueError("Value {!r} above maximum {!r}.".format(val, maxval))
ValueError: Value 11 above maximum 10.
>>> t.x = 'Python'

Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    t.x = 'Python'
  File "/home/ashwini/py/so.py", line 12, in pro
    raise TypeError('Only integers and floats are allowed.')
TypeError: Only integers and floats are allowed.
>>> t.z = 31

Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    t.z = 31
  File "/home/ashwini/py/so.py", line 14, in pro
    raise ValueError("Value {!r} above maximum {!r}.".format(val, maxval))
ValueError: Value 31 above maximum 30.
>>> t.x, t.y, t.z
(10, 11, 3)