Composition in Python

In this video, you’ll be introduced to one of the important concepts in object-oriented programming: Composition.

Composition forms a “has-a” relationship between two classes where one class has another class as one of its members. Following are some examples illustrating how composition works in Python.

# Composition example

class Course:
  def __init__(self, cid, title, credits):
    self._cid = cid
    self._title = title
    self._credits = credits
    
class Student:
  def __init__(self, sid, firstname, lastname, cid, title, credits):
    self._sid = sid
    self._firstname = firstname
    self._lastname = lastname
    self._course = Course(cid, title, credits) # Composition
    

In the example Python code shown above, the Student class has a property called self._course which is assigned the Course class. Since it is a part of the Student property (anything that attaches to self is a property), we say the Student class is composed of a Course class, thus forming a “has-a” relationship.

Note: The use of an underscore in naming properties (e.g. _course, _title, _sid, etc.) is a common convention in Python only for indicating private. Python has no special access modifiers (such as private, public, protected) like other statically typed languages have.

Consider the following changes to the Student class above.

# Composition example

class Course:
  def __init__(self, cid, title, credits):
    self._cid = cid
    self._title = title
    self._credits = credits
    
class Student:
  def __init__(self, sid, firstname, lastname):
    self._sid = sid
    self._firstname = firstname
    self._lastname = lastname

  def register(self, cid, title, credits):
  	self._course = Course(cid, title, credits)

Even though the self._course was not initially instantiated in the constructor function, this is still a composition because as soon as the register() function is invoked, it would have established the _course object which will be a property of the student object. This is allowed and can occur because Python is a dynamically typed language. This is not possible in a statically language such as Java, C#, or C++.

Consider another example:

# Composition example

class Course:
  def __init__(self, cid, title, credits):
    self._cid = cid
    self._title = title
    self._credits = credits
    
class Student:
  def __init__(self, sid, firstname, lastname):
    self._sid = sid
    self._firstname = firstname
    self._lastname = lastname

  def register(self, cid, title, credits):
  	course = Course(cid, title, credits)  # Not a field
    

The above example also uses the Course class in the Student class, but it is not a composition because course is declared as a local object only and not a property (field) of the Student. In other words, the course object is not attached to the self object.

Want to learn more? My recommendations:

Learn Python 3 the Hard Way: A Very Simple Introduction to the Terrifyingly Beautiful World of Computers and Code (Zed Shaw’s Hard Way Series)

Head First Python: A Brain-Friendly Guide

Introduction to Computing and Programming in Python (3rd Edition)