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?
Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details. What if you need to change the accessed field's type? You also have to change the accessor's return type.
Getters and Setters in python are often used when: We use getters & setters to add validation logic around getting and setting a value. To avoid direct access of a class field i.e. private variables cannot be accessed directly or modified by external user.
Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.
The private getter/setter methods provide a place for adding extra behavior or error checking code. They can provide a place for logging state changes or access to the fields.
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."
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With