4

I'm switching from Java to Python and am having trouble understanding the @Property decorator. I realized in OOP languages (such as Java) I don't fully understand the point of mutator methods in the following sense:

Say we have a private variable x. So we need to make a mutator method

public void setX(int val) {
  x = val;
}

Now if x had been public then we could have just did x = val and it would have been easier and there would have been no difference. Now in a more complicated scenario, we could add restrictions, perhaps it doesn't make sense for x to be less than 10

public void setX(int val) {
  if(x < 10)
    x = 10;
  else
    x = val;
}

So in a sense is the point of having mutator methods to impose restrictions on the data? So it's to achieve encapsulation? I'm thinking of this because with Python's @Property (correct me if I'm wrong) you're not calling a mutator method but in effect it works the same way in the sense additional logic can happen before the value is changed.

A corolary question is, if we do have such a simple mutator method as in the first example, should the variable just be made public?

northerner
  • 149
  • 3
  • 2
    Possible duplicate of [Why shouldn't I be using public variables in my Java class?](https://softwareengineering.stackexchange.com/questions/176876/why-shouldnt-i-be-using-public-variables-in-my-java-class) – gnat Apr 18 '17 at 05:42
  • see also: [Are Java's public fields just a tragic historical design flaw at this point?](https://softwareengineering.stackexchange.com/q/50225/31260) – gnat Apr 18 '17 at 05:44
  • Mutators may not be the best option, as they still expose property details. Properties should be mutated through behaviors (hence the *set* and *get* verb prefixes): https://goo.gl/66O59F. Setters still expose the property (informing other types that there's an `x` property). What if you decide to switch to a `Vector`? Should you expose a `setVector`, cluttering the API? If you exposed a `move` behavior, you'd be able to keep the property info completely hidden, yet still interact with the object as desired (modifying `x` via a behavior that doesn't expose property details) – Dioxin Apr 21 '17 at 15:19

2 Answers2

7

To answer your last question first - in Java you should always use accessor and mutator methods, because if you make a public field and later decide it needs extra logic - you're gonna have a bad time. If you are lucky and your code is not a library "all" it'll take is cleaning the build product, rebuilding, and going through countless places where you access that variable, changing them by hand. If you are a library - though luck. You're gonna break your users code...

In Python - it doesn't matter. Attribute syntax(and AFAIK implementation) is the same for fields and properties. The only difference is whether your custom method will be called or the default __getattribute__/__setattribute__ which will look inside the __dict__(or set a value in it). So if you don't need the extra logic - just use a regular field. You can always change it later.

As for the "why" - the most common reason for using a @property in Python is that you don't store the actual , direct value inside the object.

For example:

class Vector2D(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def length(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

    @length.setter
    def length(self, value):
        multiplier = value / self.length
        self.x *= multiplier
        self.y *= multiplier

We don't store the length directly - we only store x and y. But we can still get and set the length like it was an ordinary property - and our @property code does the work behind the scenes for us.

Idan Arye
  • 12,032
  • 31
  • 40
  • *If you are lucky and your code is not a library "all" it'll take is cleaning the build product, rebuilding, and going through countless places where you access that variable, changing them by hand.* .... Or put the cursor in the field declaration, alt+shift+r, select "encapsulate field" from the menu, then press enter s couple of times. (This is for eclipse... Other ides may have different sequences) – Jules Apr 18 '17 at 21:21
2

As stated here:

https://stackoverflow.com/questions/14594120/python-read-only-property

I've also seen the @property decorator used to signify that a field is "read-only". For example:

class Thing(object):
    def __init__(self, path):
        self._path = path

    @property
    def path(self):
        return self._path

Of course, we're all consenting adults in Python and this isn't actually read-only, but you won't be able to assign through the path property, only through the _path field.

PythonJin
  • 123
  • 5