8

Why - or why not - is it good practice to use getters and setters specifically in Python OOP?

My textbook states the following:

import random

class Die(object):
    """Simulate a generic die."""
    def __init__(self):
        self.sides = 6
        self.roll()

    def roll(self):
        """Updates the die with a random roll."""
        self.value = 1+random.randrange(self.sides)
        return self.value

    def getValue(self):
        """Return the last value set by roll()."""
        return self.value

def main():
    d1,d2 = Die(),Die()
    for n in range(12):
        print d1.roll(),d2.roll()

main()

The getValue() method, called a getter or an accessor, returns the value of the value instance variable. Why write this kind of function? Why not simply use the instance variable? We’ll address this in the FAQ’s at the end of this chapter.

However, there is no FAQ at the end of the chapter, and so it is never explained as to why getters are used in Python OOP.

I've tried reading other places, but I have not found a good explanation anywhere. Most answers on SO are about Java, and I've read that it is not relevant to Python...

Can someone please help me understand why it is good practice to use them? Or if not, why not?

TooTone
  • 7,129
  • 5
  • 34
  • 60
BBedit
  • 7,037
  • 7
  • 37
  • 50
  • 14
    It *isn't* good practice, actually. It is in Java, but not in Python. – Martijn Pieters Mar 28 '14 at 14:34
  • 4
    I guess the author isn't very familiar with Python. The opposite is true. – John La Rooy Mar 28 '14 at 14:38
  • 4
    Please don't close. The close votes reference a question that is generically OOP. A couple of the answers mention Python, but I think it is valid to have a Python specific version of this question. – Steven Rumbalski Mar 28 '14 at 14:43
  • @StevenRumbalski that was why I edited it. I'm an experienced C++ programmer and am starting on Python. I've only read Think Python on Python OOP, and quite surprised at how different Python OOP is to what I'd learnt previously, and I would be very interested in seeing answers to this. – TooTone Mar 28 '14 at 14:45
  • @StevenRumbalski: Any such answer would reiterate the Python-specific answers on that other question. Or any of the other languages that have true property support. – Martijn Pieters Mar 28 '14 at 14:46
  • 3
    I think the real question here is why you are modelling a `Die`, and why you feel it necessary to *remember* its `value`. – Karl Knechtel Mar 28 '14 at 14:46
  • See Eli Bendersky's [Getters and Setters in Python](http://eli.thegreenplace.net/2009/02/06/getters-and-setters-in-python/) and Fredrik Håård's [What's the point of properties in Python?](http://blaag.haard.se/What-s-the-point-of-properties-in-Python/) – Steven Rumbalski Mar 28 '14 at 14:47
  • 2
    @user2071506 In any case, I suggest you reach out to the author of the textbook and mention that you couldn't find the reference you mentioned. – Luis Mar 28 '14 at 14:52
  • @TooTone It is Steve Lott. His book is called "Building Skills in Python". He may have an account here: https://stackoverflow.com/users/10661/s-lott – BBedit Mar 28 '14 at 17:33
  • @user2071506 thanks, I can see the book is at http://www.itmaybeahack.com/homepage/books/index.html. I didn't realize it was freely available: I agree with what the previous commenter said in that it's worth contacting the author as resources like these are valuable and worth improving (in fact as I'm from a C++ background I may have a look through it myself). – TooTone Mar 28 '14 at 18:40
  • 1
    @StevenRumbalski I agree. I don't think this is a duplicate. This is a question specific for Python - the dupe is not. I've voted to reopen it. – Steinar Lima Apr 11 '14 at 22:31
  • @StevenRumbalski Also agree that this isn't a duplicate. – wheaties Feb 01 '16 at 13:55

2 Answers2

8

Because in Python you have properties:

 class Foo:
   def __init__(self, value):
     self.__value = value

   @property
   def value(self):
     return self.__value

   @value.setter
   def set_value(self, that):
     if that < 0:
       self.__value = 0
     else:
       self.__value = that

Properties make it appear that you are dealing with an attribute but in fact, you're dealing with setters and getters. This allow for better useage of one of Python's defining traits: Duck Typing.

Hence, I can do the following:

 class Bar:
   def __init__(self, value, other):
     self.value = value
     self.other = other

   def __str__(self):
     return ''.join(['Oh joy', str(self.value), str(self.other), '!'])

And then in the function:

 def stuff(x):
   return x.value + 1

I could pass either a type of Bar or a type of Foo and it wouldn't matter. Duck typing would let it "just work."

wheaties
  • 35,646
  • 15
  • 94
  • 131
  • -1 for the bit about duck typing, which I believe is entirely unrelated. Also, you may wish to change "dealing with a variable" to "dealing with an attribute". – Steven Rumbalski Mar 28 '14 at 14:59
  • 2
    @StevenRumbalski Actually I think the Duck Typing is highly relevant and central to the core of Python. But I agree, "attribute" is a better terminology. – wheaties Mar 28 '14 at 15:01
  • 1
    Sure, Python is all about duck typing, but that's not what properties are all about. They are about disguising a function call as attribute access. The nice thing is that they look exactly like attribute access, so you start out propertyless and then add them later if warranted. – Steven Rumbalski Mar 28 '14 at 15:07
  • Hmm, I actually don't understand. @property seems to be the same as 'get_value'. – BBedit Mar 31 '14 at 19:49
  • @user2071506 But it doesn't look like you're creating an accessor. It looks like a member variable. You use and treat it as if it were one (for most cases.) – wheaties Mar 31 '14 at 20:04
3

In Java you should use getters and setters :

It's considered a good practice because it encapsulates your object's inner state, therefore you can change the internals of the object and change the meaning of the value, doing complex things with it without changing its interface.

In python you can use getters and setters :

But it's not that much stressed on for accessing the value of an attribute, because python provides a facility that Java doesn't : properties !

class A(object):
    def __init__(self):
        self._x = 1
    @property
    def x(self):
        return self._x +2
    @x.setter
    def x(self, value):
        self._x = value

This is your built-in syntax to change the meaning of an attribute without changing its interface. And using it is just like using your average attribute syntax.

glglgl
  • 89,107
  • 13
  • 149
  • 217
ddelemeny
  • 1,891
  • 13
  • 18
  • 2
    The real reason you need them in Java, is that it's a pain to go refactor everything that uses attribute access when you need to add some extra behaviour. That "encapsultes" mumbo jumbo is just to cover up a poor language design decision. – John La Rooy Mar 28 '14 at 14:57
  • 2
    @gnibbler Exactly ! But I wouldn't say it that way because I know they're outside, java enthusiasts, they're legion and they're looking for blood. But I won't implement the accessor to my blood ! AH-HA ! – ddelemeny Mar 28 '14 at 15:03