Q1: Coming from an OO background (Java, Ruby, Smalltalk), what would be the preferred way of naming accessor and mutator methods when writing classes in Python? For example if I have:
class Account :
def __init__(self, owner) :
self.__owner = owner
self.__amount = 0
def owner(self) :
return self.__owner
Should I call my accessor methods after the name of the attribute like owner()
to access the private attribute __owner
as is custom in languages like Smalltalk and Ruby, or rather call it get_owner
which would be the snake-case equivalent of how you would call an accessor in Java. I assume the Java way would be prefered?
Q2: Similar question for mutator methods: should I call them set_owner
à la Java or rather something else?
Q3: Final question: if my attributes are public, as in:
class Account :
def __init__(self, owner) :
self.owner = owner
self.amount = 0
Should I even bother to write accessor and mutator methods for them then, since I can access and assign these attributes from outside the class anyway?
AFAIK private attributes aren't as emphasized in Python as other languages. Every attribute is easily accessed, so dedicated getters/setters that get around "private" attributes is mostly honor system. So this would be the go-to:
class Account :
def __init__(self, owner) :
self.owner = owner
self.amount = 0
a = Account("Kim")
a.owner
a.amount
a.owner = "Carol"
a.amount = 100
Now, people have mentioned properties. That's a way to "fake" nonexistent attributes with getters and setters so you get to still use the attribute syntax x.y = z
. It does the same thing as x.set_y(z)
, so if this aesthetic isn't a concern to you, feel free not to use properties; instance method calls are not any less "Pythonic" than attribute access.
Properties aren't used in Python to implement privacy, usually. They're used on getters/setters that calculate values on the fly. Units conversion is a good example:
class Temperature:
def __init__(self, Kelvin = 0.0):
self.K = Kelvin
@property
def C(self):
return self.K - 273.15
@C.setter
def C(self, Celsius):
self.K = Celsius + 273.15
@property
def F(self):
return self.C * 9/5 + 32
@F.setter
def F(self, Fahrenheit):
self.C = (Fahrenheit - 32) * 5/9
So, instead of storing the same temperature in 3 different units, you store it in Kelvin and use getters/setters to get Celsius or Fahrenheit. Properties just provide the aesthetic symmetry of temp.K, temp.C, temp.F
instead of temp.K, temp.getC(), temp.getF()
.