1

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?

Kim Mens
  • 325
  • 1
  • 13
  • 1
    Use properties instead. – Michael Butscher Aug 27 '21 at 20:00
  • 1
    Look into the `@property` decorator. – ddejohn Aug 27 '21 at 20:00
  • Does this answer your question? [How does the @property decorator work in Python?](https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work-in-python) – ddejohn Aug 27 '21 at 20:01
  • 2
    **don't use getter and setters in Python at all**. – juanpa.arrivillaga Aug 27 '21 at 20:05
  • 1
    Note, double-underscore name mangling is not really private. A single underscore is used to denote attributes that are not part of the public API. **and please don't write boilerplate getters and setters**. – juanpa.arrivillaga Aug 27 '21 at 20:06
  • I may need to add why I asked this question. I teach an introductory course on programming using Python as language. The course includes an introduction to object-oriented programming, since in a next course they will be switching to Java. Given the importance of member attributes and accessors and mutators in Java I wanted to introduce it in Python. I understand from the answers that @property decorators would be preferable, however, the introductory CS1 course already covers many concepts and decorators were one thing we deliberately left out. So I guess I'll stick to Java naming for now. – Kim Mens Aug 27 '21 at 20:17
  • @juanpa.arrivillaga I understood that double-underscore name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class. See for example [this question](https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-single-and-double-underscore-before-an-object-name) – Kim Mens Aug 27 '21 at 20:20
  • It has one, single use-case: preventing *accidental* name collisions in subclasses. – juanpa.arrivillaga Aug 27 '21 at 20:41
  • Look, I understand where you are coming from, but I very much disagree with teaching people "Java in Python" (you should just teach them Smalltalk :) ). Getter/Setter methods aren't some intrinsic property of object oriented languages. And note, I didn't *say* to use `property`, you **definitely should not use `property` here**, because your getters and setters *don't actually do anything except set and retreive the value*. You should just use regular attributes. That's the *beauty* of `property` (and descriptors), you get *encapsulation without boilerplate getters and setters* – juanpa.arrivillaga Aug 27 '21 at 20:47
  • Also, I might add, showing people how to use `property` doesn't really require understanding decorators at all. Is it any more magical than using `@override` in Java without understanding how Java annotations work? I think I didn't know exactly how they worked until I was using Java professionally for over a year. – juanpa.arrivillaga Aug 27 '21 at 20:49
  • 1
    "Which means that probably the best approximation would be to use Java style naming conventions and adding a footnote somewhere in the course that real Pythonistas would use decorators instead" *NO*. Again, the "real pythonista" way of doing this is *to just use a regular attribute*, i.e. your `Account` class would just be `__init__` with just `self.owner = owner` and `self.amount = 0` Take a look at [this answer I wrote to a related question](https://stackoverflow.com/a/67658208/5014455) that explains the reasoning behind the "don't write getters and setters" philosophy. – juanpa.arrivillaga Aug 27 '21 at 20:50
  • @juanpa.arrivillaga I agree one should not teach Java in Python. This is just an introductory CS1 programming course introducing programming to students unexperienced in programming. It touches upon OO concepts only near the end, because students will get in touch with such concepts in more detail in later courses in Java and perhaps other OO languages such as Ruby, Smaltalk, C++. While I believe that Python is indeed far from the best language to introduce OO I am stuck with it since that language happens to be the language that was chosen for a variety of reasons. There is no silver bullet. – Kim Mens Aug 27 '21 at 21:00
  • @KimMens I actually think Python is a fine language for learning OO. At least, as fine as Java (in a sense, Python is *better*, since it is *purely* object-oriented, unlike Java). Smalltalk would be ideal! Of course, this all depends on the details of the course, but in my experience, people often leave Java having learned how to write Java class definitions, not object orientation. E.g. the idea that "encapsulation" is synonymous with "a bunch of private attributes with public getters and setters". Anyway, do check out that link I posted. – juanpa.arrivillaga Aug 27 '21 at 21:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236497/discussion-between-kim-mens-and-juanpa-arrivillaga). – Kim Mens Aug 27 '21 at 21:10

1 Answers1

3

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().

BatWannaBe
  • 4,330
  • 1
  • 14
  • 23
  • "AFAIK private attributes aren't as emphasized in Python as other languages" Python *doesn't have access modifiers*, it's not a case of emphasis... but +1 – juanpa.arrivillaga Aug 27 '21 at 21:06
  • Well, there are naming conventions e.g. attributes named `_secret`. You're right in that it doesn't actually do anything real, but it's a part of the honor system between the dev and the user not to mess with this attribute. IIRC the only real way a single leading underscore name is different is that `from myModule import *` will ignore those names, but it's fairly rare to `import *` – BatWannaBe Aug 27 '21 at 21:12
  • Yes absolutely agree – juanpa.arrivillaga Aug 27 '21 at 21:12
  • Thanks for this answe @BatWannaBe; it is pretty close in spirit to the discussion I was having with @juanpa.arrivillaga – Kim Mens Aug 27 '21 at 21:34