eager2learn
eager2learn

Reputation: 1488

Usefulness of @property in this case

Given the following class:

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

I don't understand why they use the property function in this case. Using the property decorator for the input_size function allows one to call input_size on an object, let's call it cell, of that class, but why don't they just simply call cell._input_size? Can anybody tell me why this is useful please?

Upvotes: 10

Views: 1146

Answers (2)

tdelaney
tdelaney

Reputation: 77347

(humble opinion mode: ON)

I think its an abuse of properties. Back in the day, C++ and Java programmers realized that exposing public class members can make their code fragile. You can't change your mind about how the data for that variable is generated without changing the class interface and breaking backwards compatibility. So, people started using getters and setters (functions that access private members) for added flexibility and there was a push to hide all members... just in case.

When other languages formalized properties they sometimes had the same problem with class interfaces. You couldn't change from a variable to a property without changing the interface and once again breaking backwards compatibility. So, there was a push to make all variables properties... just in case.

Python isn't that way. You can have member foo today, change it to a property tomorrow and the class interface doesn't change. To my eye, this is just a defensive coding practice from another language and is not needed here.

(humble opinion mode: OFF)

Upvotes: 4

Ami Tavory
Ami Tavory

Reputation: 76297

The use of Python properties has advantages compared to the direct member access you suggest.

Consider the implementation

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

vs.

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

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

Suppose you have foo = Foo(). In the former case, you access the member as foo.bar. This means that you can do

print foo.bar
foo.bar = 3

I.e., you have no control of limiting modifications to bar. In the latter case, though - relying on the convention not to access things prefixed with _, admittedly - you can do

print foo.bar

but

foo.bar = 3

will raise an exception.

Moreover, using property setters, you can control how bar is modified, and do validations and other cool stuff:

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

Upvotes: 9

Related Questions