Python:使用特殊设置行为编写“property”的子类

时间:2013-02-27 22:51:01

标签: python inheritance properties

我想写一个Python property的子类,它已经有一个setter,它在设置之前对值进行了特定的检查。

背景:我有一个具有许多属性的类,所有属性都不能为负。所以我想将它们全部用于属性并检查它们是否设置了非负值。但我不想多次写同一个setter。

请看下面的例子:

class Body(object):
  _mass = 0.
  _size = 0.

  @nonnegative
  def mass(self):
    return self._mass

  @nonnegative
  def size(self):
    return self._size

现在我想定义“非负”,它应该从“属性”继承。我的ansatz覆盖了__set__方法,但我被卡住了:

class nonnegative(property):
  def __set__(self, obj, value):
    if value < 0:
      raise ValueError, 'value must not be negative'
    ### then set the attribute to value, but how?
    ### how can I know the name of the attribute?

或许我应该覆盖fset?还是setter?有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

并不像这样简单:

class Body(object):
def __init__(self):
    self._mass = 0.
    self._size = 0.

    self.last = True

def __setattr__(self, name, val):
    if 'last' in self.__dict__:
        if val < 0:
            raise ValueError('value must not be negative')
            return
    self.__dict__[name] = val

def mass(self):
    return self._mass

def size(self):
    return self._size

“last”仅用于跳过您在init上提供的值。保持...最后。 显然,您可以检查attr名称是不是保留/特殊名称还是

if val < 0

将检查你在init之后设置的所有内容。

编辑:这将在您设置值时检查非负数,而不是在您获得时。如果要允许负值,但仅在检索时出现错误,请使用

__getattr__

或者(对于abarnert)经典的方式,但你必须为每个属性写setter / getter:

class Body(object):
    def __init__(self):
        self._mass = 0.
        self._size = 0.

    @property
    def mass(self):
        return self._mass

    @mass.setter
    def mass(self, value):
        if value < 0:
            raise ValueError('value must not be negative')
        self._mass = value

    @mass.getter
    def mass(self):
        return self._mass