Kodeclik Logo

Our Programs

Learn More

Schedule

Kodeclik Blog

How (and why) to nest classes in Python

Python supports object-oriented programming capabilities and very soon you will begin to encounter the need to explore and adapt these capabilities for use in your program. Like in other OOP languages, a class in Python can be viewed as a recipe for creating objects of that class.

For instance, let us create a class to denote “cash registers”. A cash register has a make (a string), a year of manufacture (an integer), and a balance (a floating point number). We can encapsulate these variables into a class like so:

class CashRegister:
  def __init__(self, make, year, bal):
    self.make = make
    self.year = year
    self.bal = bal

cr1 = CashRegister("Olivetti",2010,0)
cr2 = CashRegister("Honeywell",2022,0)

In the above program the CashRegister class has make, year, and bal (balance) attributes. In the last two lines we define two cash registers, called cr1 and cr2. cr1 is an Olivetti cash register manufactured in 2010 with a balance of $0. cr2 is a Honeywell cash register manufactured in 2022 and also set with a balance of $0.

We can write some useful methods for cash registers within the above class definition:

class CashRegister:
  def __init__(self, make, year, bal):
    self.make = make
    self.year = year
    self.bal = bal

  def ring_purchase(self, cost):
    self.bal = self.bal + cost

ring_purchase merely rings a purchase: it takes the cost of an item and adds it to the balance.

If we now try:

cr1 = CashRegister("Olivetti",2010,0)
cr2 = CashRegister("Honeywell",2022,0)

print(cr2.bal)
cr2.ring_purchase(10)
print(cr2.bal)

The output will be:

0
10

as expected.

We can also attempt to print a cash register as a whole:

print(cr1)

This will give some output such as:

<__main__.CashRegister object at 0x7fa6e1de91f0>

(your specific results might vary). This is because Python has not been told how to print cash register objects. Let us write a Python method for this purpose:

class CashRegister:
  def __init__(self, make, year, bal):
    self.make = make
    self.year = year
    self.bal = bal

  def ring_purchase(self, cost):
    self.bal = self.bal + cost

  def print(self):
    print("I am an " + self.make 
          +" cash register made in " 
          + str(self.year) + " with a balance of " 
          + str(self.bal))

Now if we try:

print(cr1)

You will still get the same output as before. This is because this print() is the same default system print() of Python. Instead you must do:

cr1.print()

Now you will get:

I am an Olivetti cash register made in 2010 with a balance of 0

Now you might argue that cash registers do not exist by themselves in the middle of a highway. They are usually found in stores or restaurants. So we might choose to create a class called “Restaurant” and nest the CashRegister class within that class.

Here is how that might work:

Nesting Python classes

Nesting Classes in Python

In the below code, we create a Restaurant class and completely nest all the code we have written thus far for cash registers inside this class, like so:

class Restaurant:

    class CashRegister:
      def __init__(self, make, year, bal):
        self.make = make
        self.year = year
        self.bal = bal

      def ring_purchase(self, cost):
        self.bal = self.bal + cost

      def print(self):
        print("I am an " + self.make +" cash register made in " + str(self.year) + " with a balance of " + str(self.bal))

    def __init__(self,name,address):
      self.name = name
      self.address = address
      self.cashregister = self.CashRegister("Honeywell",2021,0)

Note that the class Restaurant in its constructor has a name, an address, and a default cash register (which is setup to be a Honeywell cash register manufactured in 2021 with a balance of zero). We can access the inner class (ie CashRegister) in the outer class (ie Restaurant) using the self keyword.

We can now setup a restaurant like so:

r1 = Restaurant("McDonalds","123 Main Street")

We now have a McDonalds’ restaurant on 123 Main Street and inside this restaurant we know that it has a Honeywell cash register manufactured in 2021.

If we now try:

print(r1.name)
print(r1.address)
r1.cashregister.print()

we get:

McDonalds
123 Main Street
I am an Honeywell cash register made in 2021 with a balance of 0

as expected.

What is the big deal? We could do these same things before nesting the class. The fine print is in what you are NOT allowed to do anymore. For instance, let us try creating a cash register like before:

cr1 = CashRegister("Olivetti",2010,0)
cr2 = CashRegister("Honeywell",2022,0)

We will get an error like:

Traceback (most recent call last):
  File "main.py", line 20, in <module>
    cr1 = CashRegister("Olivetti",2010,0)
NameError: name 'CashRegister' is not defined

because CashRegister is nested inside the Restaurant class, we cannot access it directly. We can only access it “through” the Restaurant class.

When should you nest classes in Python?

You should nest classes when you have related concepts (like Restaurant and CashRegister) and you desire to not make the inner class accessible without the context of the outer classes. This also helps in information hiding and improved program comprehension.

For more Python object-oriented content, checkout our blogpost on method overloading in Python. Also to understand best practices in organizing Python code, learn about the Python import command!

For more Python content, checkout the math.ceil() and math.floor() functions! Also
learn about the math domain error in Python and how to fix it!

Interested in more things Python? Checkout our post on Python queues. Also see our blogpost on Python's enumerate() capability. Also if you like Python+math content, see our blogpost on Magic Squares. Finally, master the Python print function!

Want to learn Python with us? Sign up for 1:1 or small group classes.

Kodeclik sidebar newsletter

Join our mailing list

Subscribe to get updates about our classes, camps, coupons, and more.

About

Kodeclik is an online coding academy for kids and teens to learn real world programming. Kids are introduced to coding in a fun and exciting way and are challeged to higher levels with engaging, high quality content.

Copyright @ Kodeclik 2024. All rights reserved.