在这种情况下@property的用处

eag*_*arn 9 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
Run Code Online (Sandbox Code Playgroud)

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

Ami*_*ory 7

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

考虑实施

class Foo(object):
    def __init__(self):
        self.bar = ...
Run Code Online (Sandbox Code Playgroud)

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

    ...
    @property
    def bar(self):
        return self._bar
Run Code Online (Sandbox Code Playgroud)

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

print foo.bar
foo.bar = 3
Run Code Online (Sandbox Code Playgroud)

即,你无法控制限制修改bar.在后一种情况下,虽然 - 依据惯例不能访问带有前缀的东西_,不可否认 - 你可以做到

print foo.bar
Run Code Online (Sandbox Code Playgroud)

foo.bar = 3
Run Code Online (Sandbox Code Playgroud)

会引发例外.

此外,使用属性设置器,您可以控制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
Run Code Online (Sandbox Code Playgroud)