在这种情况下@property的用处

时间:2016-03-20 18:20:03

标签: python python-decorators

鉴于以下课程:

class BasicRNNCell(RNNCell):
  """The most basic RNN cell."""

  def __init__(self, num_units, input_size=None):
    self._num_units = num_units
    self._input_size = num_units if input_size is None else input_size

  @property
  def input_size(self):
    return self._input_size

  @property
  def output_size(self):
    return self._num_units

  @property
  def state_size(self):
    return self._num_units

  def __call__(self, inputs, state, scope=None):
    """Most basic RNN: output = new_state = tanh(W * input + U * state + B)."""
    with vs.variable_scope(scope or type(self).__name__):  # "BasicRNNCell"
      output = tanh(linear([inputs, state], self._num_units, True))
    return output, output

我不明白为什么他们在这种情况下使用属性函数。使用input_size函数的属性装饰器允许一个人调用一个对象上的input_size,让我们称之为该类的单元格,但为什么不调用cell._input_size呢?谁能告诉我为什么这有用呢?

2 个答案:

答案 0 :(得分:7)

与您建议的直接成员访问相比,使用Python属性具有优势。

考虑实施

class Foo(object):
    def __init__(self):
        self.bar = ...

VS

class Foo(object):
    def __init__(self):
        self._bar = ...

    ...
    @property
    def bar(self):
        return self._bar

假设您有foo = Foo()。在前一种情况下,您以foo.bar的身份访问该成员。这意味着你可以做到

print foo.bar
foo.bar = 3

即,您无法控制对bar的修改。在后一种情况下,尽管如此 - 无可否认地依赖于convention not to access things prefixed with _ - 你可以做到

print foo.bar

foo.bar = 3

会引发异常。

此外,使用property setters,您可以控制bar的修改方式,并进行验证和其他很酷的内容:

class Foo(object):
    def __init__(self):
        self._bar = ...

    ...
    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, value):
        if something_of_value(value):
              raise Whatever
        self._bar = value

答案 1 :(得分:4)

(拙见意见模式:ON)

我认为这是滥用财产。在当天,C ++和Java程序员意识到暴露公共类成员会使他们的代码变得脆弱。在不改变类接口和破坏向后兼容性的情况下,您无法改变关于如何生成该变量的数据的想法。因此,人们开始使用getter和setter(访问私有成员的函数)以增加灵活性,并且有一种隐藏所有成员的推动......以防万一。

当其他语言形式化属性时,它们有时会遇到类接口的相同问题。如果不更改接口并再次破坏向后兼容性,则无法从变量更改为属性。因此,推动所有变量属性......以防万一。

Python不是这样的。您今天可以拥有成员foo,明天将其更改为属性,类界面不会更改。在我看来,这只是一种来自另一种语言的防御性编码实践,在这里不需要。

(拙见意见模式:OFF)