Understanding and using Python classes | by Valentina Alto | Towards Data Science

Python is an interpreted, object-oriented, high-level programming language with dynamic semantics. The latter is the formal definition given by the official website python.org. Let’s break it and try to understand it:
interpreted: differently from compiled programming languages (where the source code has to be converted into machine-readable code), interpreted languages are not directly executed by the target machine. Instead, they are read and executed by some other computer program called interpreter;
object-oriented: it means that python, like any other Object-Oriented Programming (OOP) languages, is organized around objects. Everything in python (lists, dictionaries, classes and so forth) is an object;
high-level: it means that the syntax of the code is easier to interpret by humans. Namely, if you have to display something on the screen, the built-in function is called print;
dynamic semantics: dynamics objects are instances of values contained into constructs in the code, and they exist at run-time level. Furthermore, we can assign to one object multiple values, since it will update itself, differently from a static semantic language. Namely, if we set a=2 and then a=’hello’, the string value will substitute the integer one as soon as the line is executed.
In this article, I want to dive deeper into the concept of classes. Classes are a particular type of object. More specifically, they are object-constructors, which are able to build both data representation and the procedure we can use to interact with that object (hence methods, functions and so forth).
To create a class in Python, we need to give that class a name and some attributes. So let’s start with the following example:
class Actor:    def __init__(self, name, surname, age, years_on_stage):        self.name=name        self.surname=surname        self.age=age        self.years_on_stage=years_on_stage
So we created a class called Actor, which defines some features (name, surname, age, years on stage). There are two elements to focus on:
__init__(): it is a special method used to initialize data attributes. We can look at it as an initializer.
self: it is a standard notation which is used to point the parameters.
Now, we can use our class and create an object of class Actor:
mario=Actor(    'Mario',    'Rossi',    40,    13)
Now, we can access all the attribute of mario (which we defined in __init__()):
mario.name"mario"mario.age40
Now, imagine we want to know specific information about mario which is not stored among its attributes. More specifically, we want to know the year of debut, but we are only provided with the years on stage. So what we would like to have is a function which subtracts from the current date the years on stage, so that it returns the year of debut.
We can do so directly into our class Actor:
class Actor:    def __init__(self, name, surname, age, years_on_stage):        self.name=name        self.surname=surname        self.age=age        self.years_on_stage=years_on_stage    def year_of_debut(self, current_year):        self.current_year=current_year        year_of_debut=self.current_year-self.years_on_stage        return year_of_debut
Now let’s test it on our object mario:
mario.year_of_debut(2019)2006
The last thing I’m going to talk about is a very interesting and useful property of python classes, called class inheritance. The idea is that, if you have to create a class (called child class) which is a subset of the one you’ve already created (called parent class), you can easily import its attributes to the child class.
Let’s see how to do that with the following example. Let’s say you want to create a child class called Comedian, which will have some attributes in common with the parent class Actor:
class Comedian(Actor):    def __init__(self, n_shows, field, shows_schedule, name, surname, age, years_on_stage):        self.n_shows=n_shows        self.field=field        self.shows_schedule=shows_schedule        super().__init__(name,surname,age,years_on_stage)
As you can see, instead of specifying self.attribute=attribute for name, surname, age and years_on_stage, we directly inherited them by the parent class through the function super(). Now, we can create an object of our child class and access its attributes exactly as in the parent class example:
a_comedian=Comedian(           21,          'politics',          'late night',           'amelia',           'smith',           '33',           '10')a_comedian.name'amelia'a_comedian.field'politics'
The advantages of Python classes are noticeable. Particularly, they make Python language extremely customizable: not only you can create personalized functions (besides those which are built-in), but also can you create object-generators which are able to perfectly satisfy your needs.