Classes

Classes

In Python, classes are a fundamental concept used for object-oriented programming (OOP). Classes are a special data type which provide a way to structure and organize code by grouping data attributes and methods (functions) that operate on that data into a single unit called an “object”.

Let us take a very basic example of a class. 

Output:

<class ‘__main__.Person’>

Here, we are defining a Person class using the class keyword. We have also defined two attributes(firstname and lastname) inside the class. So, this class groups the firstname and lastname data attributes into a single unit which can be later used to create an object. On printing the value of Person, we only get to see that it is a class named Person. We cannot see the attributes present inside the class.

If we try to print the data type of this class, we get the output as ‘type’.

Output:

<class ‘type’>

So, in order to access the attributes, we have to use attribute references. Let us now see how to use attribute references.

Output:

Charles

Babbage

AttributeError: type object ‘Person’ has no attribute ‘age’

From this example, we can say that we can use a dot(.) followed by the reference of the attribute to access the attribute present in a class. Here, Person.age throws an error as there is no ‘age’ attribute in the Person class. 

Person.firstname and Person.lastname are known as attribute references. These attribute values can be modified by assigning new values to them.

Output:

Darwin

Here, we are modifying the lastname attribute by assigning a new value to it. In the output, we can see that the value of the lastname attribute has changed. 

Let us now see how to create an object using a class. Previously, we have seen that the type of a class is a type. This is because creating a new class creates a new type of object, allowing new instances of that type to be made. We can create an object from a class by instantiation. We can instantiate a class just like what we do to call a function as follows:

Here, we can see that we are creating an instance of a class by using Person(). It returns an object of type Person to the variable person1. On printing person1, we can see that it is a Person object stored at some memory location. On checking the type, it denotes that it is of type Person. We can also access the firstname and lastname attributes of the created object as shown above.

Earlier, we had seen that we can modify the attributes of a class by using attribute references. But that can create undesired effects in the created objects. That’s why we should avoid that approach. Rather, we should create objects out of a class and modify attributes of created objects to avoid polluting the main class. This can be done as follows:

Here, we are creating two instances of the Person class to generate two separate objects(person1 and person2). Then, we are modifying the lastname attribute of the person1 object. This does not modify the lastname attribute of the Person object which we can see at the last line.

Until now, we were creating objects by calling the class object(instantiation) with no parameters. 

person1 = Person()

The object created in this way has the attributes values as defined in the class. This means that all object instances created from the same class will have the same attribute values. But in reality, we may need some attributes unique to each class. In that case, we have to proceed with a slightly different approach. For this, we need a special method called __init__(). We need to define our attributes inside the __init__()method.

Here, we can see that the __init__()method is defined inside the class which takes two parameters. The first parameter self points to the current class instance and the second parameter brand is a value to be passed to the class during instantiation. Inside the __init__() method, self.brand is creating a new attribute for the class to which the user-defined value of brand is assigned. Thus, the Car class has two attributes, category and brand. Here, category is an attribute or variable present in the class which will be shared by all instance objects created from this class. Whereas, brand is an attribute or value passed during instantiation which will be unique for all instances. Due to this, category is known as a class variable and brand is known as an instance variable.

While creating an instance, we can see that we are passing the string BMW which is received by the __init__() method and assigned to the brand variable.

In the above example, we can observe the difference between class variable and instance variable. Here, category is a class variable and therefore it is shared by both instance objects. Whereas brand is an instance variable and therefore it is unique for both instances.

We can also have methods(or functions) inside classes which can be called using attribute references. A function residing inside a class is known as a method. For example:

Output:

It is a four-wheeler BMW

Here, we have created a carDetails method inside the class which prints the car details(category and brand). In this class, both __init__ and carDetails are methods. The only difference is that __init__ is a special method which if present gets called automatically during instantiation. But the carDetails method needs to be called in order to get the desired output. We are calling it using the statement car1.carDetails() where we are accessing the method using attribute reference. It has a parameter self which points to the current object instance. So, we need to access the category and brand attribute values by using self.category and self.brand respectively.

Note that we can use any variable like obj, myobj, thisobj etc. instead of self.