Object Oriented Programming for Python Beginners

You have probably used it if you’re an experienced developer, if not, you have probably heard of it. Object oriented programming (OOP) allows us to break code down into objects which will utilize attributes and behaviors to perform tasks. Generally, objects represent real world objects (think: car, bike, light switch, toothbrush, etc.) but not always. These objects will be derived from what is called a class, which is like a blueprint of the object. From this blueprint we can create as many objects as we would like. If I had a simple class for students, that defined just an ID, name, and grade attribute, I could then create as many different students as I wanted and of course they would all have distinct differences. Student #1 may have ID: 01, name: “John Doe”, grade: 87 and student #2 might be ID:02, name: “Jane Doe”, grade: 90. The behaviors of these students could be vast, but to keep it simple, the class could define a behavior for the student to attend class, and a behavior for a student to show their grade. In python programming these behaviors are called methods, and they are simply just functions that can only be called on an object of the class they live in. When we create an object from a class blueprint, it’s called instantiating an instance. If we create three student objects, we have created three student instances.

OOP requires analysis and design, meaning we must analyze the problem first to find out what the objects will be and how they will interact with each other. A commonplace for OOP in python is video game development. Because python reads like English i.e., isn’t verbose, many beginners like to use it to learn game dev over other languages like c#. If I wanted to build a python game called space invaders, I would most likely identify at least 4 objects (user_ship, enemie_ship, laser, asteroid). How will they interact with each other? What will their behaviors and states be? We can actually use the dreaded UML or Unified Markup Language diagram to help us design everything before we start to code it (this is called Object Oriented Design). Below you will see and example of some UML relating to space invaders.

What’s beautiful about UML is there are no strict rules to creating and using them. UML diagrams can be as simple or complex as we want, as you can see above. For someone who already understands syntax this may be all they need to spin up a fully functional pygame called space invaders as it helps them understand how the objects needed for the game should work, of course there will probably be nuances and other requirements.

Classes

Let’s talk about less about theory now and more about the code. When we start writing the code for OOP, we will generally build the classes first (remember this is the blueprint for the object). Let’s use a car class for an example. To do this we start off with the class keyword.

class Car:
def __init__(self, make, model):
self.make = make
self.model = model

Notice it’s good practice to use a Pascal case when naming your class, which requires first letter of each word to be uppercase, for example class ElectricCar. Simple enough, but what about the code underneath? Let’s Discuss it, this is what’s called a magic or dunder method, I like to call them dunder because it’s short for double underscore. This particular dunder method is called the initializer (or constructor). Python will recognize this method and automatically run it when we instantiate an instance of the class, making it useful for defining all attributes of the object. We must then pass in any parameters that should be user defined like make and model. This of course allows the user to define the make and model when creating the instance. Keep in mind, that just like any other function we can have default or optional parameters. Ok so that leaves us wondering, what is self ? Self is a reference to the object or instance, it is required, and allows us to not only separate instances from each other, but to globalize their attributes so that every other method in the class has access to them. Let’s instantiate an instance so we can get a clearer picture of what is happening.

class Car:
def __init__(self, make, model):  # this is the initializer dunder method
self.make = make
self.model = model
car1 = Car("toyota", "camry")  # this is how we instantiate an instance/create an object
# car1: self.make = make --------> car1.make = toyota
# car1: self.model = model --------> car1.model = camry
car2 = Car("honda", "civic")
# car2: self.make = make --------> car2.make = honda
# car2: self.model = model --------> car2.model = civic

This is a very simple class, it only has 1 method, the __init__. The other methods should represent behaviors that the object can perform, or the behaviors that can be performed on them by other objects. Because we know that some behaviors of cars are drive, brake, and honk, we can build those behaviors in the form of methods. Reminder: methods are simply functions that depend on an object, whereas functions can be called anywhere without objects, think print() or input().

Class Car:
def __init__(self, make, model):  # this is the initializer dunder method
self.make = make
self.model = model

def drive(self):
print(f"the {self.make},{self.model} is driving!")

def brake(self):
print(f"the {self.make},{self.model} is braking!")

def honk(self):
print(f"the {self.make},{self.model} is honking!")

car1 = Car("toyota", "camry")  # <------- instantiate our instance
car2 = Car("honda", "civic")

car1.drive()  # to call the method we use the dot operator on our instance variable
car2.drive()
car1.honk()
car2.brake()

# ========OUTPUT========
"""
the toyota,camry is driving!
the honda,civic is driving!
the toyota,camry is honking!
the honda,civic is braking!
"""

Inheritance

So now that we know the basics of creating classes and objects, let’s talk about some other important concepts. Inheritance: extremely important for code reusability. If I have a car class but I now want to make a class for an electric car, should I rewrite everything from scratch? We can use our car class as a parent and inherit from it. The class Car will become the parent and the class ElectricCar will become the child class. It’s important to realize, that the child class holds a higher degree of access, meaning that it has the ability to access methods inside the parent class, as well as override methods of the parent class.

class Car:  
  def __init__(self, make, model):  # this is the initializer dunder method self.make = make                
      self.model = model 
  def drive(self): 
      print(f"the {self.make},{self.model} is driving!") 

class ElectricCar(Car): 
   def __init__(self, make, model, battery_size): 
          super().__init__(make, model)  # using the super  method to initialize the parent class        
          self.battery_size = battery_size

If you look closely at the ElectricCar class, you will notice the parentheses where we pass the class we want to inherit from (in this case Car). It’s good practice to use the super method to access the parents class initializer, super().__init__(make, model). This allows us skip attribute assignment, and run anything else that may be important to the parent class, because, for example it may be loading a database.

Encapsulation

This is the process of essentially wrapping our code so that there is no direct access. A good example of this may be the cover around a house fan, we would want anyone to have direct access to the blades as it could be dangerous, but also because its unnecessary. As long as the fan properly circulates and blows air, the user will be happy.

Abstraction

This is very much like encapsulation, with some slight differences. Abstraction is the process of giving only what is needed, for example, the user only needs access to the buttons that control the fan speed. However, the appliance repair man will need access to the internals of the fan. We need to be able to design with this principle in mind.

Learning OOP

OOP can get complex, and  you can’t learn everything about it by simply reading an article. You must practice writing in OOP ourselves. The internet is the best resource for finding OOP projects that you can replicate. Here at Practity yo may find multiple Python challenges solved with OOP like games, desktop applications or real-life assignments.

    Practity
    Register New Account
    Shopping cart