Take Your Skills To The Next Level

More

Object-oriented Programming in Python: An Introduction

Object-oriented Programming in Python: An Introduction

On this article, we’ll dig into object-oriented programming (OOP) in Python. We gained’t go too deeply into the theoretical points of OOP. The principle purpose right here is to exhibit how we are able to use the object-oriented paradigm with Python.

In response to Statista, Python is the fourth most used programming language amongst builders. Why is that? Nicely, some say that it’s due to Python’s simplified syntax; others say it’s due to Python’s versatility. No matter the reason being, if we wish to research a trending programming language, Python ought to be one among our decisions.

Contents:

  1. The Fundamentals of OOP
  2. Lessons and Objects
  3. Defining a New Technique
  4. Entry Modifiers: Public, Protected and Personal
  5. Inheritance
  6. Polymorphism
  7. Technique Overloading
  8. Technique Overriding

The Fundamentals of OOP

Let’s begin with a delicate abstract of object-oriented programming. Object-oriented programming is a programming paradigm — a bunch of concepts that set a regular for the way issues should be completed.

The concept behind OOP is to mannequin a system utilizing objects. An object is a element of our system of curiosity, and it often has a particular goal and habits. Every object accommodates strategies and knowledge. Strategies are procedures that carry out actions on knowledge. Strategies would possibly require some parameters as arguments.

Java, C++, C#, Go, and Swift are all examples of object-oriented programming languages. The implementation of the OOP ideas in all of these languages is completely different, after all. Each language has its syntax, and on this article, we’ll see how Python implements the object-oriented paradigm.

To be taught extra about OOP typically, it’s price studying this text from MDN, or this fascinating dialogue about why OOP is so widespread.

Lessons and Objects

The primary essential idea of OOP is the definition of an object. Let’s say you've got two canines, referred to as Max and Pax. What have they got in widespread? They're canines and so they signify the thought of a canine. Even when they're of a unique breed or coloration, they nonetheless are canines. On this instance, we are able to mannequin Max and Pax as objects or, in different phrases, as situations of a canine.

However wait, what's a canine? How can I mannequin the thought of a canine? Utilizing lessons.

Diagram of a class and two objects

As we are able to see within the image above, a category is a template that defines the info and the habits. Then, ranging from the template supplied by the category, we create the objects. Objects are situations of the category.

Let’s take a look at this Python code:

class Canine():
  def __init__(self, identify, breed):
    self.identify = identify
    self.breed = breed

  def __repr__(self):
    return f"Canine(identify={self.identify}, breed={self.breed})"

max = Canine("Max", "Golden Retriever")
pax = Canine("Pax", "Labrador")
print(max)
print(pax)

On line 1, we declare a brand new class utilizing the identify Canine. Then we stumble upon a way referred to as __init__. Each Python class has this, as a result of it’s the default constructor. This methodology is used to initialize the item’s state, so it assigns values to the variables of the newly created object. As arguments of the constructor, we've the identify, the breed, and a particular key phrase referred to as self. It’s not a coincidence that that is the primary argument of the strategy.

Inside the category code, the self key phrase represents the present occasion of the category. Because of this every time we wish to entry a sure methodology or variable that belongs to an occasion of the category (max or pax are two completely different situations), we should use the self key phrase. Don’t fear if it’s not fully clear now; it will likely be within the subsequent sections.

Have a look at the primary line of the __init__ methodology — self.identify = identify. In phrases, this says to the Python interpreter: “Okay, this object that we’re creating can have a reputation (self.identify), and this identify is contained in the identify argument”. The identical factor occurs for the breed argument. Okay, so we might have stopped right here. That is the essential blueprint used to outline a category. Earlier than leaping to the execution of this snippet, let’s take a look at the strategy that was added after the __init__.

The second methodology is named __repr__. In Python, the __repr__ methodology represents the category object as a string. Often, if we don’t explicitly outline it, Python implements it in its personal manner, and we’ll now see the distinction. By default, if we don’t explicitly outline a __repr__ methodology, when calling the perform print() or str(), Python will return the reminiscence pointer of the item. Not fairly human-readable. As a substitute, if we outline a customized __repr__ methodology, we've a pleasant model of our object in a stringed vogue, which may also be used to assemble the item once more.

Let’s make a change to the code above:

class Canine:
  def __init__(self, identify, breed):
    self.identify = identify
    self.breed = breed

max = Canine("Max", "Golden Retriever")
pax = Canine("Max", "Golden Retriever")

print(max)
print(pax)
print(max == pax)

If we save and run this code, that is what we get:

<__main__.Canine object at 0x0000026BD792CF08>
<__main__.Canine object at 0x0000026BD792CFC8>
False

Wait, how can or not it's potential that they aren’t two equal canines, if they've the identical identify and the identical breed? Let’s visualize it utilizing the diagram we made earlier than.

Diagram of a class and two objects showing the memory addresses

First, once we execute print(max), Python will see that there’s no customized definition of a __repr__ methodology, and it'll use the default implementation of the __repr__ methodology. The 2 objects, max and pax, are two completely different objects. Sure, they've the identical identify and the identical breed, however they’re completely different situations of the category Canine. In actual fact, they level to completely different reminiscence areas, as we are able to see from the primary two strains of the output. This truth is essential for understanding the distinction between an object and a category.

If we now execute the primary code instance, we are able to see the distinction within the output once we implement a customized __repr__ methodology:

Canine(identify=Max, breed=Golden Retriever)
Canine(identify=Pax, breed=Labrador)

Defining a New Technique

Let’s say we wish to get the identify of the max object. Since on this case the identify attribute is public, we are able to merely get it by accessing the attribute utilizing max.identify. However what if we wish to return a nickname for the item?

Nicely, in that case, we create a way referred to as get_nickname() inside our class. Then, outdoors the definition of the category, we merely name the strategy with max.get_nickname():

class Canine:
  def __init__(self, identify, breed):
    self.identify = identify
    self.breed = breed

  def get_nickname(self):
    return f"{self.identify}, the {self.breed}"

  def __repr__(self):
    return f"Canine(identify={self.identify}, breed={self.breed})"

max = Canine("Max", "Golden Retriever")
pax = Canine("Pax", "Labrador")

print(max.identify)
print(max.get_nickname())

If we run this snippet, we get the next output:

> python snippet.py
Max
Max, the Golden Retriever

Entry Modifiers: Public, Protected and Personal

Let’s now contemplate entry modifiers. In OOP languages, entry modifiers are key phrases used to set the accessibility of lessons, strategies or attributes. It’s a unique scenario in C++ and Java, the place entry modifiers are express key phrases outlined by the language. In Python, there’s no such factor. Entry modifiers in Python are a conference fairly than a assure over entry management.

Let’s take a look at what this implies with a code pattern:

class BankAccount:
  def __init__(self, quantity, openingDate):
    
    self.quantity = quantity
    
    self._openingDate = openingDate
    
    self.__deposit = 0

On this snippet, we create a category referred to as BankAccount. Any new BankAccount object should have three attributes: a quantity, a gap date and an preliminary deposit set to 0. Discover the one underscore (_) earlier than openingDate and the double underscore (__) earlier than deposit.

Nice! In response to Python’s conference, the one underscore is used as a prefix for protected members, whereas the double underscore is for personal members. What does this imply in observe? Let’s attempt to add the code under below the category definition:

account = BankAccount("ABXX", "01/01/2022")
print(account.quantity)
print(account._openingDate)
print(account.__deposit)

If we attempt to execute this code, we’ll get one thing like this:

> python snippet.py
ABXX
01/01/2022
Traceback (most up-to-date name final):
  File "snippet.py", line 14, in <module>
    print(account.__deposit)
AttributeError: 'BankAccount' object has no attribute '__deposit'

We are able to print the account quantity as a result of it’s a public attribute. We are able to print the openingDate, even when, in keeping with the conference, it’s not suggested. We are able to’t print the deposit.

Within the case of the deposit attribute, the right technique to learn or modify its worth ought to be by get() and set() strategies. Let’s see an instance of this:

class BankAccount:
  def __init__(self, quantity, openingDate):
    self.quantity = quantity
    self._openingDate = openingDate
    self.__deposit = 0

  def getDeposit(self):
    return self.__deposit

  def setDeposit(self, deposit):
    self.__deposit = deposit
    return True

account = BankAccount("ABXX", "01/01/2022")
print(account.getDeposit())
print(account.setDeposit(100))
print(account.getDeposit())

Within the code above, we outline two new strategies. The primary one is named getDeposit, and the second is setDeposit. As their names suggest, they’re used to get or set the deposit. It’s a conference in OOP to create get and set strategies for all the attributes that must be learn or modified. So, as an alternative of instantly accessing them from outdoors the category, we implement strategies to try this.

As we are able to simply guess, executing this code provides the next output:

> python snippet.py
0
True
100

Inheritance

DRY. Don’t repeat your self. Object-oriented programming encourages the DRY precept, and inheritance is without doubt one of the methods used to implement the DRY precept. On this part, we’ll see how inheritance works in Python. Please notice that we’ll use the phrases mum or dad class and baby class. Different aliases would possibly embody base class for the mum or dad and derived class for the youngsters. Since inheritance defines a hierarchy of lessons, it’s fairly handy to distinguish between the mum or dad and all the youngsters.

Okay, so let’s begin with an instance. Let’s say we wish to mannequin a classroom. A classroom is made by a professor and various college students. What do all of them have in widespread? What relationship do all of them share? Nicely, they’re definitely all people. As such, they share a sure variety of options. For simplicity right here, we outline a category Individual as having two personal attributes, identify and surname. This class additionally accommodates the get() and set() strategies.

The picture under reveals a mum or dad class and two youngsters.

Image diagram showing a parent class and two children

As we are able to see, in each Pupil and Professor lessons we've all of the strategies and attributes outlined for the Individual class, as a result of they inherit them from Individual. Moreover, there are different attributes and strategies highlighted in daring which might be particular to the kid class.

Right here’s the code for this instance:

class Individual:
  def __init__(self, identify, surname):
    self.__name = identify
    self.__surname = surname

  def getName(self):
    return self.__name

  def getSurname(self):
    return self.__surname

  def setName(self, newName):
    self.__name = newName

  def setSurname(self, newSurname):
    self.__surname = newSurname

Then, we've two entities to mannequin, the Pupil and the Professor. There’s no must outline all of the issues we outline above within the Individual class for Pupil and Professor additionally. Python permits us to make the Pupil and the Professor class inherit a bunch of options from the Individual class (mum or dad).

Right here’s how we are able to try this:

class Pupil(Individual):
  def __init__(self, identify, surname, grade):
    tremendous().__init__(identify, surname)
    self.__grade = grade

  def getGrade(self):
    return self.__grade

  def setGrade(self, newGrade):
    self.__grade = newGrade

Within the first line, we outline a category utilizing the same old class Pupil() syntax, however contained in the parentheses we put Individual. This tells the Python interpreter that this can be a new class referred to as Pupil that inherits attributes and strategies from a mum or dad class referred to as Individual. To distinguish this class a bit, there’s a further attribute referred to as grade. This attribute represents the grade the coed is attending.

The identical factor occurs for the Professor class:

class Professor(Individual):
  def __init__(self, identify, surname, teachings):
    tremendous().__init__(identify,surname)
    self.__teachings = teachings

  def getTeachings(self):
    return self.__teachings

  def setTeachings(self, newTeachings):
    self.__teachings = newTeachings

There’s a brand new aspect we haven’t seen earlier than. On line 3 of the snippet above, there’s an odd perform referred to as tremendous().__init__(identify,surname).

The tremendous() perform in Python is used to present the kid entry to members of a mum or dad class. On this case, we’re calling the __init__ methodology of the category Individual.

Polymorphism

The instance launched above reveals a strong thought. Objects can inherit behaviors and knowledge from different objects of their hierarchy. The Pupil and Professor lessons have been each subclasses of the Individual class. The concept of polymorphism, because the phrase says, is to permit objects to have many shapes. Polymorphism is a sample utilized in OOP languages during which lessons have completely different functionalities whereas sharing the identical interface.

Talking of the instance above, if we are saying {that a} Individual object can have many shapes, we imply that it may be a Pupil, a Professor or no matter class we create as a subclass of Individual.

Let’s see another fascinating issues about polymorphism:

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

  def __repr__(self):
    return f"{self.__class__.__name__}(model={self.model}, coloration={self.coloration})"

class Automotive(Car):
  cross

tractor = Car("John Deere", "inexperienced")
red_ferrari = Automotive("Ferrari", "pink")

print(tractor)
print(red_ferrari)

So, let’s take a look. We outline a category Car. Then, we create one other class referred to as Automotive as a subclass of Car. Nothing new right here. To check this code, we create two completely different objects and retailer them in two separate variables referred to as tractor and red_ferrari. Be aware right here that the category Automotive doesn’t have something inside. It’s simply outlined as a unique class, however until now it has had no completely different habits from its mum or dad. Don’t hassle about what’s contained in the __repr__ methodology for now, as we’ll come again to it later.

Are you able to guess the output of this code snippet? Nicely, the output is the next:

Car(model=John Deere, coloration=inexperienced)
Automotive(model=Ferrari, coloration=pink)

Be aware the magic occurring right here. The __repr__ methodology is outlined contained in the Car class. Any occasion of Automotive will undertake it, since Automotive is a subclass of Car. However Automotive doesn’t outline a customized implementation of __repr__. It’s the identical as its mum or dad.

So the query right here is why the habits is completely different. Why does the print present two various things?

The reason being that, at runtime, the Python interpreter acknowledges that the category of red_ferrari is Automotive. self.__class__.__name__ will give the identify of the category of an object, which on this case is the self object. However keep in mind, we've two completely different objects right here, created from two completely different lessons.

If we wish to verify whether or not an object is an occasion of a sure class, we might use the next features:

print(isinstance(tractor, Car)) 
print(isinstance(tractor, Automotive)) 

On the primary line, we’re asking the next query: is tractor an occasion of the category Car?

On the second line, we’re as an alternative asking: is tractor an occasion of the category Automotive?

Technique Overloading

In Python, like in another OOP language, we are able to name the identical methodology in several methods — for instance, with a unique variety of parameters. That is perhaps helpful once we wish to design a default habits however don’t wish to forestall the person from customizing it.

Let’s see an instance:

class Overloading:
  def sayHello(self, i=1):
    for occasions in vary(i):
      print("Good to satisfy you!")

a = Overloading()
print("Working a.sayHello():")
a.sayHello()
print("Working a.sayHello(5):")
a.sayHello(5)

Right here, we outline a way referred to as sayHello. This methodology has just one argument, which is i. By default, i has a worth of 1. Within the code above, once we name a.sayHello for the primary time with out passing any argument, i will assume its default worth. The second time, we as an alternative cross 5 as a parameter. This implies i=5.

What's the anticipated habits then? That is the anticipated output:

> python snippet.py
Working a.sayHello():
Good to satisfy you!
Working a.sayHello(5):
Good to satisfy you!
Good to satisfy you!
Good to satisfy you!
Good to satisfy you!
Good to satisfy you!

The primary name to a.sayHello() will print the message "Good to satisfy you!" solely as soon as. The second name to a.sayHello() will print "Good to satisfy you!" 5 occasions.

Technique Overriding

Technique overriding occurs when we've a way with the identical identify outlined each within the mum or dad and within the baby class. On this case, we are saying that the kid is doing methodology overriding.

Principally, it may be demonstrated as proven under. The next diagram reveals a toddler class overriding a way.

Diagram showing a child class overriding a method

The sayHello() methodology in Pupil is overriding the sayHello() methodology of the mum or dad class.

To point out this concept in observe, we are able to modify a bit the snippet we launched at first of this text:

class Individual:
  def __init__(self, identify, surname):
    self.identify = identify
    self.surname = surname

  def sayHello(self):
    return ("Hey, my identify is {} and I'm an individual".format(self.identify))

class Pupil(Individual):
  def __init__(self, identify, surname, grade):
    tremendous().__init__(identify,surname)
    self.grade = grade

  def sayHello(self):
    return ("Hey, my identify is {} and I'm a pupil".format(self.identify))

a = Individual("john", "doe")
b = Pupil("joseph", "doe", "eighth")
print(a.sayHello())
print(b.sayHello())

On this instance, we've the strategy sayHello(), which is outlined in each lessons. The Pupil implementation of sayHello() is completely different, although, as a result of the coed says good day in one other manner. This strategy is versatile, as a result of the mum or dad is exposing not solely an interface but in addition a type of the default habits of sayHello, whereas nonetheless permitting the youngsters to switch it in keeping with their wants.

If we run the code above, that is the output we get:

> python snippet.py
Hey, my identify is john and I'm an individual
Hey, my identify is joseph and I'm a pupil

Conclusion

By now, the fundamentals of OOP in Python ought to be fairly clear. On this article, we noticed the right way to create lessons and the right way to instantiate them. We addressed the right way to create attributes and strategies with completely different visibility standards. We additionally found basic properties of OOP languages like inheritance and polymorphism, and most significantly the right way to use them in Python.

Related posts
More

Mastering the JavaScript change Assertion — Dutfe

More

Getting Began with HTML Tables — Dutfe

More

404: Not discovered – Dutfe

More

404: Not discovered – Dutfe

Sign up for our Newsletter and
stay informed

Leave a Reply

Your email address will not be published. Required fields are marked *