3) Inheritance Lesson

Python Object Composition Example

6 min to complete · By Martin Breuss

On this page, you'll see an example implementation of the classes mentioned earlier that you'll then compose to build a Kitchen() composite class. Give it a try yourself before reading over this code. Once you give it a shot and have a working example, come back here and compare your code to the one below:

# Define a class for a stove
class Stove:
    def __init__(self, num_burners):
        self.num_burners = num_burners
        self.on = False

    def turn_on(self):
        self.on = True
        print("Stove is now on")

    def turn_off(self):
        self.on = False
        print("Stove is now off")

# Define a class for a sink
class Sink:
    def __init__(self, num_faucets):
        self.num_faucets = num_faucets
        self.water_on = False

    def turn_water_on(self):
        self.water_on = True
        print("Water is now on")

    def turn_water_off(self):
        self.water_on = False
        print("Water is now off")

# Define a class for a fridge
class Fridge:
    def __init__(self, num_shelves, capacity):
        self.num_shelves = num_shelves
        self.capacity = capacity
        self.contents = []

    def add_food(self, food):
        self.contents.append(food)
        print(f"Added {food} to the fridge")

    def remove_food(self, food):
        self.contents.remove(food)
        print(f"Removed {food} from the fridge")

# Define a class for a countertop
class Countertop:
    def __init__(self, length, width):
        self.length = length
        self.width = width
        self.items = []

    def add_item(self, item):
        self.items.append(item)
        print(f"Added {item} to the countertop")

    def remove_item(self, item):
        self.items.remove(item)
        print(f"Removed {item} from the countertop")

# Define a class for a kitchen using composition
class Kitchen:
    def __init__(self, stove, sink, fridge, countertop):
        self.stove = stove
        self.sink = sink
        self.fridge = fridge
        self.countertop = countertop

# Create instances of `Stove`, `Sink`, `Fridge`, and `Countertop`
stove = Stove(4)
sink = Sink(2)
fridge = Fridge(3, 200)
countertop = Countertop(10, 5)

# Create an instance of `Kitchen` using the smaller objects
kitchen = Kitchen(stove, sink, fridge, countertop)

# The `kitchen` object has access to the methods and attributes of the component objects
kitchen.stove.turn_on()  # "Stove is now on"
kitchen.fridge.add_food("Milk")  # "Added Milk to the fridge"
kitchen.countertop.add_item("Mixing bowl")  # "Added Mixing bowl to the countertop"

Composition Meaning and Benefits

By using composition, you can define the Kitchen() composite class in terms of the smaller component objects that it has, rather than through inherited properties of a shared parent class. This allows you to reuse the code for Stove(), Sink(), Fridge(), and Countertop() in other circumstances:

class TinyBathroom:
    def __init__(self, sink)
        self.sink = sink

bathroom_sink = Sink(1)  # There's only 1 sink in the bathroom
bathroom = TinyBathroom(bathroom_sink)

Better Relationships

Additionally, this structure can make it more straightforward to understand the relationships between the objects in your program. The relationships are explicit and defined through the objects that you compose together.

Better Code

It may also make it more straightforward to modify and maintain your code because changes to a composite object will not affect the behavior of any other objects that use the component objects:

class Kitchen:
    def __init__(self, stove, fridge, countertop):
        self.stove = stove
        self.fridge = fridge
        self.countertop = countertop

Even though you removed the sink from your kitchen, you can still use Sink() in your TinyBathroom(), so the change in the design of your kitchen won't break any other objects.

Whether it's a good idea to build a kitchen without a sink is a different question, though. And one more thing: you should probably .turn_off() that stove again before leaving this page!!

In the coming lesson, you'll recap the fundamentals of object-oriented programming that you've learned in the previous sections. You'll also see a complete code snippet of an example implementation of the Ingredient() and Spice() classes as you've built them over the previous lessons.

Summary: Python Composition Example

  • Composition is a useful technique in Python when building larger objects from smaller ones
  • Composition allows greater flexibility and reuse of code and facilitates code maintenance
  • In some cases, inheritance might be better than composition; it depends on each specific case