5

Is there a difference between

class Example(object):
    def __init__(self, prop):
        self._prop = prop

    def get_prop(self):
        return self._prop

    def set_prop(self, prop):
        self._prop = prop

    prop = property(get_prop, set_prop)

and

class Example2(object):
    def __init__(self, prop):
        self._prop = prop

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, prop):
        self._prop = prop

They seem to do the same thing, which doesn't fit python's goal of there being only one obvious way to do things. Is there a prefered way? And if so, why?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
BoshWash
  • 5,320
  • 4
  • 30
  • 50
  • 1
    the decorator is just syntactic sugar - see http://stackoverflow.com/questions/17330160/python-how-does-the-property-decorator-work – dannymilsom Mar 17 '14 at 11:50
  • ok thanks, does anyone know why it was added? – BoshWash Mar 17 '14 at 11:54
  • you should take a look at this PEP. http://legacy.python.org/dev/peps/pep-0318/ – Jayanth Koushik Mar 17 '14 at 11:55
  • 1
    The `@someDecoratorFunction` was added to make the syntax prettier and easier to use. Like many things, it’s just syntactic sugar for other, more complex, language constructs. – poke Mar 17 '14 at 11:55
  • 1
    @BoshWash: Python 2.4 added decorators, Python 2.6 added the `property.setter()` (and sibling) decorators. `property` has existed since 2.2. – Martijn Pieters Mar 17 '14 at 11:59

2 Answers2

9

The @decorator syntax is just syntactic sugar. There are no differences between the two approaches other than the syntax, the end result is the same.

@property
def prop(self):
    return self._prop

is translated to:

def prop(self):
    return self._prop
prop = property(prop)

and the same applies to the setter:

@prop.setter
def prop(self, prop):
    self._prop = prop

becomes:

tmp = prop.setter
def prop(self, prop):
    self._prop = prop
prop = tmp(prop)

as the decorator expression (prop.setter) is evaluated first. See How does the @property decorator work? for how .setter() (and .deleter() and .getter()) works.

Note that the prop.setter() decorator (and the .getter() and .deleter() decorators) of property objects was only added in Python 2.6. In addition, property was added to Python in version 2.2, but decorators were only added to the language in Python 2.4.

As a result, a lot of documentation still uses the older property constructor method.

If you are coding for Python 2.6 or newer, however, you should be using the decorators syntax.

The @property and @prop.setter decorators give a clear early visual signal that you have property functions here, while the separate prop = property(...) line after the property functions is easily missed, especially if the property implementation is longer.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • @JayanthKoushik: Python has always had the ability to get certain things done in different ways with syntax. List comprehensions versus a loop, `try:`/`finally:` to open and close files vs. context managers and `with`. Newer syntax takes some time to become the preferred way, older documentation lingers, etc. That doesn't mean Python suddenly is inconsistent or that a principle is being violated. – Martijn Pieters Mar 17 '14 at 11:55
  • Thanks, I guess it was to new to be removed in python 3. – BoshWash Mar 17 '14 at 11:57
  • @BoshWash: *new to be removed*? The `property()` constructor signature is not going to go away, not in Python 3 either. It's just that the `@prop.setter()` syntax is relatively new and code that needs to support Python 2.4 or 2.5 cannot use it. – Martijn Pieters Mar 17 '14 at 12:01
  • Ok, so it will coexist as a different way of expressing the same thing, with a few more lines? – BoshWash Mar 17 '14 at 12:04
  • @BoshWash: They coexist but the `@property` syntax is cleaner. – Martijn Pieters Mar 17 '14 at 12:05
  • I'll promise to let it go after that, but why is it cleaner? – BoshWash Mar 17 '14 at 12:06
  • @BoshWash: The separate `prop = property(..)` line comes after the functions, and can more easily be missed. The `@property` and `@prop.setter()` syntax *before* each property function is a clearer visual signal that you have property functions there. – Martijn Pieters Mar 17 '14 at 12:08
0

For your exact code I made a comparison in Python 3.7. enter image description here

This shows that stack machine Python bitecode will be a bit different, but almost identical.

prosti
  • 42,291
  • 14
  • 186
  • 151