88

Using get/set seems to be a common practice in Java (for various reasons), but I hardly see Python code that uses this.

Why do you use or avoid get/set methods in Python?

Avery Payne
  • 1,738
  • 2
  • 17
  • 31
  • Greate responses from everyone. Admittedly, this question is an offshoot of this one http://stackoverflow.com/questions/1022970/getters-and-setters-code-smell-necessary-evil-or-cant-live-without-them-clos however, it seems that I was raided by a horde of folks looking at it from a "J"-word perspective. Thanks again for restoring my faith in sanity... – Avery Payne Apr 10 '10 at 01:12
  • 1
    The context is important, and here Python and Java are simply different. (However, I removed Python from the title because we use tags for that on SO. ;) –  Oct 22 '10 at 23:50
  • Related: [What's the pythonic way to use getters and setters?](//stackoverflow.com/q/2627002) – Aran-Fey Oct 03 '18 at 12:09

8 Answers8

118

In python, you can just access the attribute directly because it is public:

class MyClass:

    def __init__(self):
        self.my_attribute = 0  

my_object = MyClass()
my_object.my_attribute = 1 # etc.

If you want to do something on access or mutation of the attribute, you can use properties:

class MyClass:

    def __init__(self):
        self._my_attribute = 0

    @property
    def my_attribute(self):
        # Do something if you want
        return self._my_attribute

    @my_attribute.setter
    def my_attribute(self, value):
        # Do something if you want
        self._my_attribute = value

Crucially, the client code remains the same.

blokeley
  • 6,726
  • 9
  • 53
  • 75
60

Cool link: Python is not Java :)

In Java, you have to use getters and setters because using public fields gives you no opportunity to go back and change your mind later to using getters and setters. So in Java, you might as well get the chore out of the way up front. In Python, this is silly, because you can start with a normal attribute and change your mind at any time, without affecting any clients of the class. So, don't write getters and setters.

mgv
  • 8,384
  • 3
  • 43
  • 47
  • 3
    plus setters/getters add performance cost, especially in Python. – Nick Dandoulakis Apr 05 '10 at 17:42
  • 4
    This *does* place an added burden on the class designer, in that instance variables implicitly become part of the class's public API. When laying out a class, explicitly think about which instance variables you want to be accessed externally vs those which are really just part of your class implementation. Prefix the internal implementation ones with a leading '_'. This is the Python warning sign that if the implementation changes, this variable might change too or even completely go away. Otherwise you'll find implementation knowledge leaking out of your class, making it hard to change later. – PaulMcG Apr 05 '10 at 17:57
  • 9
    @Nick D: I don't think accessors are the right place to do speed optimizations in Python. – wRAR Apr 05 '10 at 18:29
  • @wRAR, probably with the new setters/getters built-in support that's true. But in general, function calls are costly in Python. – Nick Dandoulakis Apr 05 '10 at 18:48
  • 1
    @Nick D: I mean, that's an interpreted language which encourages readability, not performance, so there will be a lot better places for optimizations in a program. – wRAR Apr 05 '10 at 18:58
  • @wRAR, sure, I agree with that ;-) – Nick Dandoulakis Apr 05 '10 at 19:09
  • @Paul: If the "public" instance attribute changes, isn't that nearly always the the same as changing "public" getters and setters? Design can be fragile, but I don't see a difference between attributes/properties and getters/setters in this respect. –  Oct 22 '10 at 23:49
  • @Roger: my point was that the designer of a library class may not realize that *every* internal attribute of a public class is visible to the outside world, and that an attribute that he/she thought was just used internally, if not named appropriately, is fair game for users of his module to access and become dependent upon. A well-intentioned effort to do some internal naming cleanup may in fact break external code, making for unexpected compatibility and upgrade problems. If an attribute is exposed as a property, it is less likely that the developer will unwittingly change the property name. – PaulMcG Oct 23 '10 at 06:55
  • 2
    @Paul: It's *not* an internal attribute unless it's named with one or two leading underscores (with the first form generally preferred as the latter does Python's unusual name mangling). If you don't want to write docs and this issue bothers you, simply use _name by default for all instance attributes. –  Oct 23 '10 at 07:25
  • @Roger: isn't that what I said in my original comment? Are we arguing? If so, what about? – PaulMcG Oct 23 '10 at 08:14
  • @Paul: I don't think we're arguing, I just don't see how "this does place an added burden on the class designer" is true. –  Oct 23 '10 at 08:17
  • @Roger: I guess I was referring to the added burden of "using _name by default for all instance attributes." Maybe I just don't think in leading underscores. – PaulMcG Oct 23 '10 at 08:24
  • @Paul: I read it as the opposite (that not using getters/setters added a burden), but I realize it can be hard to decipher what you meant six months later. –  Oct 23 '10 at 08:32
  • As I said in the twin posting of this one, 'Are we so undisciplined as programmers that we can't keep our hands off of things that are clearly marked "no touchy"?' It should be pretty obvious that if there is an *internal* method/property, it was internal for a reason - meaning, "don't go in there, here there be dragons." :) – Avery Payne Nov 25 '10 at 01:06
  • Then again, maybe it isn't as clear to another reader. Perhaps the thought process is simply "oh, look, the inner workings of this object happen to have a small cover over the top of what I think would be helpful to my project...I'll just sneak in there and connect to it, no-one will notice" Either way, there probably should be some general discussion in the programming community at large about why there are internals to begin with, and some basic guidelines on who can do what and when....just a thought. – Avery Payne Nov 25 '10 at 01:09
  • This is not true: "In Python, this is silly, because you can start with a normal attribute and change your mind at any time". You can start with normal attribute, then in the inherited class you replace it with property wo setter and bum! basic class cannot assign a value anymore. – Ayrat Nov 05 '12 at 11:26
  • @Ayrat, the quote comes from http://dirtsimple.org/2004/12/python-is-not-java.html and is in the context of using `property` to create getters/setters, *when they are needed.* The idea is that you don't bother using this *until you have to*, so you save time, space, and brainpower not bothering with it. – Avery Payne Aug 07 '14 at 00:43
32

Here is what Guido van Rossum says about that in Masterminds of Programming

What do you mean by "fighting the language"?

Guido: That usually means that they're trying to continue their habits that worked well with a different language.

[...] People will turn everything into a class, and turn every access into an accessor method,
where that is really not a wise thing to do in Python; you'll have more verbose code that is
harder to debug and runs a lot slower. You know the expression "You can write FORTRAN in any language?" You can write Java in any language, too.

Community
  • 1
  • 1
Nick Dandoulakis
  • 42,588
  • 16
  • 104
  • 136
17

No, it's unpythonic. The generally accepted way is to use normal data attribute and replace the ones that need more complex get/set logic with properties.

Max Shawabkeh
  • 37,799
  • 10
  • 82
  • 91
  • 14
    +1: "We're all adults here". The code is visible. "private" and "getter/setter" don't create any value when all the code can be seen. – S.Lott Apr 05 '10 at 18:19
7

The short answer to your question is no, you should use properties when needed. Ryan Tamyoko provides the long answer in his article Getters/Setters/Fuxors

The basic value to take away from all this is that you want to strive to make sure every single line of code has some value or meaning to the programmer. Programming languages are for humans, not machines. If you have code that looks like it doesn’t do anything useful, is hard to read, or seems tedious, then chances are good that Python has some language feature that will let you remove it.

Shane C. Mason
  • 7,518
  • 3
  • 26
  • 33
5

Your observation is correct. This is not a normal style of Python programming. Attributes are all public, so you just access (get, set, delete) them as you would with attributes of any object that has them (not just classes or instances). It's easy to tell when Java programmers learn Python because their Python code looks like Java using Python syntax!

I definitely agree with all previous posters, especially @Maximiliano's link to Phillip's famous article and @Max's suggestion that anything more complex than the standard way of setting (and getting) class and instance attributes is to use Properties (or Descriptors to generalize even more) to customize the getting and setting of attributes! (This includes being able to add your own customized versions of private, protected, friend, or whatever policy you want if you desire something other than public.)

As an interesting demo, in Core Python Programming (chapter 13, section 13.16), I came up with an example of using descriptors to store attributes to disk instead of in memory!! Yes, it's an odd form of persistent storage, but it does show you an example of what is possible!

Here's another related post that you may find useful as well: Python: multiple properties, one setter/getter

Community
  • 1
  • 1
wescpy
  • 10,689
  • 3
  • 54
  • 53
0

I had come here for that answer(unfortunately i couldn't) . But i found a work around else where . This below code could be alternative for get .
class get_var_lis: def __init__(self): pass def __call__(self): return [2,3,4] def __iter__(self): return iter([2,3,4]) some_other_var = get_var_lis
This is just a workaround . By using the above concept u could easily build get/set methodology in py too.

yunus
  • 2,445
  • 1
  • 14
  • 12
-11

Our teacher showed one example on class explaining when we should use accessor functions.

class Woman(Human):
    def getAge(self):
        if self.age > 30:
            return super().getAge() - 10
        else:
            return super().getAge()
  • I didn't give you the downvotes, but I thought I would chime in. The point of the discussion is "why do we need get() / set() to access properties directly in Python". In Java, there are language...features...that make this desirable. In Python, not so much. – Avery Payne May 11 '15 at 17:33
  • 7
    Apart from not really answering the question, the example used in this answer is offensive. The claim that your teacher used it does not justify its sexism. – thomasvakili Dec 30 '15 at 15:13
  • I doubt this shows sexism, merely your naivety. In my grandmother's generation many women joked that their age was some years younger than it actually was. Besides it has nothing to do with the answer anyway. – Johan Snowgoose Mar 14 '19 at 11:17