0

I often see this pattern:

class Foo:
    def __init__(self, bar):
        self._bar = bar

    def bar(self):
        return _bar

Why would that be preferable to this?

 class Foo:
     def __init__(self, bar)
         self.bar = bar
Bill
  • 640
  • 2
  • 8
  • 18
  • 3
    This is for Java, but I think the spirit of it still answers your question [Why use getters and setters?](https://stackoverflow.com/questions/1568091/why-use-getters-and-setters). In python specifically, [see `@property`](https://stackoverflow.com/questions/6618002/python-property-versus-getters-and-setters) – Cory Kramer Jun 22 '17 at 19:20
  • 1
    because you cannot change `bar` reference without using `self._bar` in the first case. In the second case, anything is possible, the variable is less "protected". – Jean-François Fabre Jun 22 '17 at 19:20
  • @Jean-FrançoisFabre I think this answers the question most directly. The reason to use a method is that it protects the reference from being altered (assuming the user knows not to touch `_variables`) while making the value easily accessible. – Bill Jun 23 '17 at 19:27

2 Answers2

0

It de-couples the external representation of bar from its internal representation.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
0

In your first code, this would be preferable sometimes for some reasons. For one, in Python _name is just a naming convention that indicates to the developer that _name should not be accessed from outside the place where its define, be it a class, a module or whatever. This naming convention also helps to avoid name collisions, especially if the attribute is critical in terms of functionality.

Let's demonstrate with real examples. You'll find many examples of these in the os.py module, for instance:

# Helper for popen() -- a proxy for a file whose close waits for the process
class _wrap_close:
    def __init__(self, stream, proc):
        self._stream = stream
        self._proc = proc
              ...

_wrap_close is a wrapper class that's returned when you call os.popen ._proc. This doesn't just indicate that you shouldn't access this directly in your code, but also might be an indicator that this attribute is critical to the functionality of the class, if you look inside, os.popen you will probably see why:

# Supply os.popen()
def popen(cmd, mode="r", buffering=-1):
    # many code omitted here...
    if mode == "r":
        proc = subprocess.Popen(cmd,
                                shell=True,
                                stdout=subprocess.PIPE,
                                bufsize=buffering)
        return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
  # many code omitted here... (see os.py) 

_wrap_close is a wrapper class around the object returned by Popen and in fact _wrap_close delegates many operations and accesses to self._proc. _wrap_close itself uses _name naming convention.

In some cases:

def bar(self):
    return self._bar

typically there would be some processing and logic prior to returning self._bar. Also properties and descriptors can be used as well. Different developers use different features for different reasons.

GIZ
  • 4,409
  • 1
  • 24
  • 43
  • @Bill Is this what you're looking for? – GIZ Jun 22 '17 at 21:29
  • "typically there would be some processing and logic prior to returning self._bar" @direprobs my question is specifically about cases where there is no processing logic prior to returning. Why create the method at all in those cases? – Bill Jun 23 '17 at 19:22
  • @Bill Can you provide us with a real example where you encountered this? – GIZ Jun 24 '17 at 08:50
  • here's an example: class Lemma from the NLTK WordNet package http://www.nltk.org/_modules/nltk/corpus/reader/wordnet.html#Lemma @direprobs – Bill Jun 26 '17 at 19:58
  • 1
    @Bill It does seem the developers wanted to immune themselves from future changes before the introduction of properties That's if the need arises to shift from simple attributes to do some processing in the future instead of just returning a plain attribute, changing to functions would be difficult, because this would break a lot of codes. What's the likelihood of my speculation being right? The code is written in 2.X and that's only what I know. Anyway, don't agitate yourself! Just know that `_name` is a naming convention that denotes internal attributes of objects. – GIZ Jun 26 '17 at 21:05