Learntofish's Blog

A blog about math, physics and computer science

Tutorial: Object Oriented Programming in Python – Part 9

Posted by Ed on December 25, 2011

This is the continuation of the Python OOP tutorial. Today I want to talk about private variables and methods.

Private variables
Consider the class below. It describes an airplane with the attributes fuel and maxFuel. The gas tank can hold up to 24000 liters. The method addFuel() allows us to refuel.

# module aircraft.py
class Airplane:
    fuel = 0
    maxFuel = 24000

    def addFuel(self, volume):
        self.fuel = self.fuel + volume

    def printStatus(self):
        print("Current fuel:", self.fuel)

Save the code in a file aircraft.py and run it in the Python-Shell (e.g. in IDLE by pressing F5). Then type the following in the Python-Shell:

>>> airbus = Airplane()
>>> airbus.printStatus()
Current fuel: 0
>>> airbus.addFuel(20000)
>>> airbus.printStatus()
Current fuel: 20000

– We have created an Airplane object and added fuel with the addFuel() method. We used the printStatus() method to check how much fuel is in the tank.
– Note that we have changed the value of the attribute fuel by using the addFuel() method.
– However, there is another way to change the value without using the method.
Type the following in the Python-Shell (directly after you’ve typed the above):

>>> airbus.fuel = 22000
>>> airbus.printStatus()
Current fuel: 22000

Here, we used the dot operator to access the attribute fuel and set it to 22000. And note that we didn’t need to use the method addFuel(). Then why did we even include the addFuel() in our class? Continue in the Python-Shell:

>>> airbus.fuel = 30000
>>> airbus.printStatus()
Current fuel: 30000

– Again, we have changed the fuel attribute by assigning directly a value to it (as opposed to using a method).
– However, this direct access to the fuel attribute causes a problem: Obviously, we have exceeded the maximum allowed value for the fuel volume (review the class again, the attribute maxFuel is set to 24000).
– We can solve this problem by prohibiting the direct access to the fuel attribute. In the Airport class add two underscores in front of the fuel attribute:

# module aircraft

class Airplane:
    __fuel = 0
    maxFuel = 24000
    
    def addFuel(self, volume):
        self.__fuel = self.__fuel + volume

    def printStatus(self):
        print("Current fuel:", self.__fuel)

Adding those two underscores makes the attribute private. Save the changes in aircraft.py and run it in the Python-Shell (e.g. in IDLE by pressing F5). Then type the following:

>>> airbus = Airplane()
>>> airbus.printStatus()
Current fuel: 0
>>> airbus.__fuel = 22000
>>> airbus.printStatus()
Current fuel: 0

– In line 4 we try to change the __fuel attribute by directly assigning the value 22000. Remember that we have renamed the fuel attribute to __fuel.
– However, line 6 shows that the change was not accepted. This is because the attribute __fuel is private. (We also say that __fuel is a private variable .)

Now, you will probably complain that using the method addFuel() we can also exceed the maxFuel limit, e.g. by using airbus.addFuel(50000). You are right. To prevent this from happening we have to change the addFuel() method:

# module aircraft

class Airplane:
    __fuel = 0
    maxFuel = 24000
    
    def addFuel(self, volume):
        if(self.__fuel + volume <= 24000):
            self.__fuel = self.__fuel + volume
        else:
            print("You are adding too much fuel!")
            print("Fuelling not possible!")

    def printStatus(self):
        print("Current fuel:", self.__fuel)

– Here, I’ve made changes from line 08 to 12. The if-else statements prevent us from exceeding the maxFuel limit. If we try to refuel too much we print an error message.
– Save the changes in aircraft.py and run the file in the Python-Shell. Then type the following:

>>> airbus = Airplane()
>>> airbus.printStatus()
Current fuel: 0
>>> airbus.addFuel(50000)
Error: You are adding too much fuel!
Fuelling not possible!
>>> airbus.addFuel(18000)
>>> airbus.printStatus()
Current fuel: 18000

– In line 4 we try to add more fuel than allowed. Our method addFuel() does not permit this.
– In line 7 we add 18000 which is allowed.

Private methods
We can even forbid using certain methods in the Python-Shell (or more general calling the method with the dot operator outside of the class). For example let’s add two underscores in front of the printStatus() method (see line 14 below):

# module aircraft

class Airplane:
    __fuel = 0
    maxFuel = 24000
    
    def addFuel(self, volume):
        if(self.__fuel + volume <= 24000):
            self.__fuel = self.__fuel + volume
        else:
            print("Error: You are adding too much fuel!")
            print("Fuelling not possible!")

    def __printStatus(self):
        print("Current fuel:", self.__fuel)

Save the changes in aircraft.py and run the file in the Python-Shell. Then type the following in the Python-Shell:

>>> airbus = Airplane()
>>> airbus.printStatus()
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: 'Airplane' object has no attribute 'printStatus'

Python responds with an error. This is because we have made the method printStatus() private now. However, we can still use it inside the class:

# module aircraft

class Airplane:
    __fuel = 0
    maxFuel = 24000
    
    def addFuel(self, volume):
        if(self.__fuel + volume &amp;amp;amp;amp;amp;lt;= 24000):
            self.__fuel = self.__fuel + volume
        else:
            print("Error: You are adding too much fuel!")
            print("Fuelling not possible!")
        self.__printStatus()

    def __printStatus(self):
        print("Current fuel:", self.__fuel)

We have added line 13. This will print the status everytime we call the addFuel() method. Save the changes in aircraft.py and run the file in the Python-Shell. Then type the following in the Python-Shell:

>>> airbus = Airplane()
>>> airbus.addFuel(20000)
Current fuel: 20000

Although we can’t use the method printStatus() outside of the class we can still use it inside the class, e.g. here we have used it inside the addFuel() method.

Questions:
1) What is a private variable and method?
2) How do we make variables and methods private?
3) Why is it not good to directly change an attribute with the dot operator (e.g. in the Python-Shell)?

Answers:
1) A private variable is an attribute that cannot be changed directly by using the dot operator, e.g. by assigning a value in the Python-Shell via myObject.attribute = someValue. Similarly, a private method cannot be used outside of the class by using the dot operator, e.g. by calling it in the Python-Shell via myObject.myMethod().
2) We make variables and methods private by adding two underscores in front of them.
3) Changing an attribute directly with the dot operator is not considered good practice since it can cause problems. We could change the attribute in such a way that the attribute takes undesired values. To prevent this we always use methods that change the attributes in a “controlled” way.

Note:
In Python things can not really be made private as opposed to Java, e.g. we can still change the variable outside of the class by typing the following in the Python-Shell:

>>> print(airbus._Airplane__fuel)
0
>>> airbus._Airplane__fuel = 17000
>>> print(airbus._Airplane__fuel)
17000

Read more here (references):
1. True privateness in Python
2. Why are Python’s ‘private’ methods not actually private?
3. Does python have ‘private’ variables in classes?
4. Private Variables and Methods in Python

Reference 2 explains the actual purpose of double underscores: the two underscores prevent subclasses (= derived classes) from changing an attribute of their superclass (= base class).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: