Schedule A

Another lame blog

Schedule A header image 1

Accessors: Why Python Doesn’t Have Them

July 19th, 2009 · 4 Comments

Consider the following Object Oriented code:

class Foo
{
    private int bar;

    public int getBar()
    {
        return this.bar;
    }

    public bool setBar(int i)
    {
        this.bar = i;
        return true;
    }
}

When learning the art of writing code, especially if you start in a language like Java, you are told to keep your data private and always use accessor methods to get or set it. But why is that? I was never really told why (maybe I just didn’t ask enough). Consider the alternative in Python:

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

Python being dynamic whatever attributes you set on the instance in the initializer (__init__) dictate what is available in the instance. In this case the data is public and can be accessed though foo.bar if foo is an instance of Foo.

When I started coding in Python suddenly everything was public and all the getter and setter methods were gone replaced with methods which actually did a logical unit of work. Part of the reason for this openess was a C philosophy of trusting the programmer. If someone uses your class and messes with the private data in a bad way, the program will crash, and it will be their fault. The best way to fight back against that would be to write a simple well documented API. Practically, for my uses thus far this have worked well.

Back to the accessors in Java, C++, and C#. Why are they such a must? The first step in the progression tends to be that by keeping your data private, you protect your interface from abuse. Specifically your clients will be less likely to write incorrect code. Having public data is also leaky: clients can write code based on implementation details like the int bar in Foo which an implementer may want to change. Using private data the compiler can enforce this encapsulation.

But really you want the client to have access to the data, that is why you write accessors in the first place. Writing the accessors allow you to control access to this private data. The value of a member variable can be restricted valid ones, and values being read can be validated before being returned. This excellent when it is needed, but most often the trivial accessors are all that is needed. Simply setting the value and returning is all you need. In that case wouldn’t it just be easier to use a public value? It would, but this would define a difficult to change interface. An interface you might want to change when you discover in the future you really want to restrict values for this data.

The interface is the key. The is why writing accessor in the first place is encouraged and the difference between Java and Python. The reason Python doesn’t need accessors.

If you use public data in Java, the client would access the data with foo.bar, and that defines the interface If the implementer were to change it to suddenly require an accessor all of the client code would have to be recompiled with something like foo.getBar() in place of foo.bar. By always using accessors, whenever it is decide that accessing private data needs to be controlled the implementer can add it, no client changes needed.

Great right? Except you have to write all of the accessors (most of the time). Really if the data is so important as to be publicly accessible what is the harm in writing accessors? None really. But in Python you don’t have to.

This is because in Python foo.bar is actually a flexible interface. In the case plan public data, it gives you access to it. But if the need arises and you need to protect the data you can using properties:

class Foo:
    _private_bar = 0 # accessible but understood as don't touch.
    def _get_bar(self):
        return self._private_bar
    def _set_bar(self, i):
        #Do something interesting like ensure i is an int
        self._private_bar = i
     bar = property(_get_bar, _set_bar)

Now foo.bar implicitly calls _get_bar and foo.bar = 5 implicitly calls _set_bar. In Python implicit is bad, but here it preserves the interface which is good. If clients are used to accessing bar, they still can while you make the logic behind the access arbitrarily complex, only when needed. I think that is a good thing.

Beyond language features I thought this was interesting because it show how important syntax is when designing a language. How any construct is an interface, and the semantics of that interface can effect how easy or how difficult it is to do something in the confines of that language. A flexible interface increases power, but unclear semantics decreases readability.

Tags: design · programming

4 responses so far ↓

  • 1 Darwin O'Connor // Jul 20, 2009 at 9:09 am

    In Delphi you can do this with

    Foo = class
    private
    FBar : integer;
    public
    property Bar : integer read FBar write FBar;
    end;

    The values after read and write can be either the variable itself a function that read or writes the value. If it is the variable, then it implicitly creates the reading or writing function for you.

    Delphi is an older language then Java. I’m surprised the Java doesn’t have this feature.

  • 2 Albert // Jul 20, 2009 at 9:18 am

    In Delphi would having a public Bar: integer; be frowned upon? If so why?

    Python in some sense is older than Java (or at least the same age). That being said properties of some form may have been added to the language. Even though C# kind of lacked imagination, I think it probably also has a similar property feature. I am sure commenters will give correct details.

  • 3 Darwin O'Connor // Jul 21, 2009 at 8:34 am

    I think they are used so you can change how your data is stored in your class to eliminate the variable, while making it appear that it is still there to the code that uses it.

    I do admit that that isn’t very likely to happen and it probably generally not worth it, unless you are writing a library that is going to be widely used by third parties. I don’t use it very often myself.

  • 4 Albert // Jul 21, 2009 at 8:56 am

    Not surprising. Properties aren’t used in Python very much either. Only when the pattern makes sense.

Leave a Comment