Learning Management Platform for Written Tutorial Series.

Python 3 Classes - A beginners guide

Python 3 Classes - A beginners guide

Python Classes

In this lesson, we will explore the concept of object oriented programming. Object oriented programming maps the real world entities using classes. Classes form the blueprints from which we create objects. For example, we are developing an application that will store data that is related to animals, then we can create a class called Animal and create our animal objects from it.

Topics to be covered

We will cover the following topics in this lesson.

  • What is a class?
  • Class declaration syntax
  • Python __init__ method
  • Python __del__ method
  • Python class parameters
  • Python class self keyword
  • Python class access modifiers
  • Python class properties
  • Python class methods
  • Python static methods
  • Python Class Methods Vs Static Methods

What is a class?

A class is a collection of related functions grouped together that mirror a real-world entity. Let's look at the code below then explain the concept of classes further.

class Animal:
    def eat(self):
        print('eating')


    def sleep(self):
        print('sleeping')


dog = Animal()

dog.eat()
dog.sleep()

Our class above maps a real-world entity called animal that is capable of eating and sleeping. In a way, Animal forms the blue print for all animals that eat and sleep. Because it is a blueprint, we can create cats and dogs from it.

Class declaration syntax

Let's now look at the syntax for creating classes in python

class Myclass:

	def class_method(self):
		print('class method')
		
		
my_class = Myclass()

my_class.class_method()

HERE,

  • class Myclass: they keyword class is used to define the a class in python. MyClass is the name of the class that we have defined. The full colon : at ends the class declaration. Notice how the class name starts with an upper class name and how we used another upper case letter to separate the words in the class name. This is not mandatory but highly recommended.
  • def class_method(self): defines a method called class_method that accepts a mandatory parameter of self. The keyword self refers to the class itself and this parameter can be used to access class methods and variables internally. However, you don't have to pass in this method when calling the class method.
  • my_class = Myclass() defines an object instance called my_class of the class MyClass.
  • my_class.class_method() calls the class_method() that we defined in our class. Notice how we did not pass in the parameter self. Python does that automatically for us.

Executing the above code produces the following results.

hello class

Python __init__ method

In this section, we will look at class constructors and what they do. A constructor that is method that is automatically called when an instance of the class is created. Let us look at a practical example.

class MyClass: 
	def __init__(self): 
		print('hello constructor')


	def class_method(self): 
		print('class method') 


my_class = MyClass() 

HERE,

  • class MyClass: defines a class called MyClass
  • def __init__(self): defines a method called __init__. It is a special method that will be called automatically when we create an instance of MyClass.
  • def class_method(self): defines a class method.
  • my_class = MyClass() creates an instance the class MyClass and the constructor method __init__ is called automatically.

Executing the above code produces the following results.

hello constructor

Python __del__ method

Python another method that is similar to the constructor but it does the opposite. It is called the destructor method. It is automatically called when the class object is destroyed.

class MyClass: 
	def __init__(self): 
		print('hello constructor')


	def class_method(self): 
		print('class method') 


	def __del__(self):
		print('shiva the destroyer')


my_class = MyClass() 
my_class.class_method() 

HERE,

  • def __del__(self): defines the destructor method using the special method name __del__

Executing the above code produces the following results.

hello constructor
class method
shiva the destroyer

The code above prints three lines two of which are done automatically. Python manages memory automatically. When you define a variable, it is stored in memory and as long as some code is using it, then python will preserve it. When no code is referencing the variable anymore, python automatically removes it from memory. This is called automatic garbage collection. When this process happens, the __del__ method is automatically called. This method is useful for activities such as closing database connections or cleaning up when the class is no longer needed.

Python class parameters

We have been dealing with methods that do not accept any parameters apart from the mandatory self parameter. In this section, we will look at how we can pass parameters. Let's create a simple class called Arithmetic that will perform basic arithmetic operations.

class Arithmetic:
    def add(self,x,y):
        print(x + y)


    def product(self,x,y):
        print(x * y)


    def divide(self,x,y):
        print(x / y)


arithmetic = Arithmetic()
arithmetic.add(2,3)
arithmetic.product(2,3)

HERE,

  • class Arithmetic: defines a class called Arithmetic
  • def add(self,x,y): defines a method called add that accepts two parameters x and y. Note: the self parameter is mandatory when defining the method and it should be the first parameter. If you swap them then you will get an error message.

Python class access modifiers

If you have knowledge of other programming languages like Java or C#, then you must be familiar with the concept of access modifiers like private, protected and public. Access modifiers restrict access to variables and methods.

Let's look at a C# example to fully understand the concept of access modifiers

class Person{
    private string religion = ""; //Can only be accessed in Person class
    protected string name = ""; //Can only be accessed in Person and all subclasses of Person
    public string country = ""; //Can be accessed in Person and sub classes and instances of both 
}

class Employee : Person{
    //name and country are accessible here
}

Employee employee = new Employee(); //only country is accessible in employee variable

HERE,

  • class Person{...} defines a new class called Person.
  • private string religion = ""; defines a string variable religion that is private. This means religion is only accessible in the Person class. All sub classes and instances will not have access to religion because C# has hidden it.
  • protected string name = ""; defines a string variable called name that is protected. This means it can only be accessed in the super and sub classes. Instances have not access to it.
  • public string country = ""; defines a string variable country that has public access. Super and sub classes and all instances can access it.

That is the concept of access modifiers, we will talk more about terminologies used in this section in the next lesson.

Now, let's look at python philosophy for dealing with access modifiers. The philosopher can be summarized as follows

A word is enough for the wise

Python does not restrict access to variables or methods that are private or protected. What python recommends is to mark items as private using a double underscore __private and protected items with a single underscore _protected.

So for a wise programmer, access to variables or methods with double underscores __ is avoided. For variables and methods with a single underscore _, access to it is restricted only to sub classes and not instances.

For python programmers who violate these conventions then verily verily we say unto them

you've made your bed, now lie in it

What this means is if you use a library that has private members and you access them directly, don't complain in the future if the private variables are renamed or removed and this breaks your code. You were warned.

Now that we have covered the philosophical aspect of it, let's look at a practical example.

class Person:
    _name = ''
    __religion = ''
    country = ''

    def __init__(self, name,religion):
        self._name = name
        self.__religion = religion


    def iam(self):
        print(f'I am {self._name}. My religion is {self.__religion}')


    def get_name(self):
        return self._name
        
        
    def set_religion(self,value):
        self.__religion = value


    def get_religion(self):
        return self.__religion


person = Person('Robert Ingersoll','Agnostic')

print(f'I am {person.get_name()}')
print(f'My religion is {person.get_religion()}')

HERE,

  • class Person: defines a class called Person
  • _name = '' defines a protected attribute _name. We know it is protected because it starts with an underscore _.
  • __religion = '' defines a private attribute religion which should only be accessed in the super class. We know it is private because the variable name starts with double underscores __
  • def __init__(self, name,religion): defines the class constructor that accepts the arguments of _name and __religion parameters
  • def iam(self): defines a method that describes the person using the values of our two (2) variables.
  • def get_name(self): defines a method that should be used to access the value of the name attribute. This is the proper way of doing things. This way, we define a public contract that the code using the class can call and it will always work even if the internal variable _name were to be renamed to something else
  • def get_religion(self): defines a public method that returns the value of the __religion variable.
  • person = Person('Robert Ingersoll','Agnostic') creates an instance of the Person class.
  • print(f'I am {person.get_name()}') prints the value of the name variable.
  • print(f'My religion is {person.get_religion()}')

Executing the above code produces the following results.

I am Robert Ingersoll
My religion is Agnostic

The following code shows how you can access both weak protected and strong private private attributes.

print(f'My name is {person._name}')
print(f'My religion is {person._Person__religion}')

HERE,

  • print(f'My name is {person._name}') access to a protected method is the same as a normal attribute
  • print(f'My religion is {person._Person__religion}') access to a private method has a special syntax which includes the class name that starts with an underscore. This should be called on the instance variable like so person._Person__religion.

Trying to access religion using the following syntax produces raises an exception.

print(f'My religion is {person.__religion}')

The above code produces the following exception

Traceback (most recent call last):
  File "/Users/lion/Desktop/PyTest/p.py", line 29, in <module>
    print(f'My religion is {person.__religion}')
AttributeError: 'Person' object has no attribute '__religion'

Python class properties

In the above example, we looked at a Person and created set and get methods for it. We will work with the same example and create properties for the private variables of the class like so.

class Person:
    __name = ''
    __religion = ''

    def __init__(self, name,religion):
        self.__name = name
        self.__religion = religion


    @property
    def name(self):
        return self.__name


    @name.setter
    def name(self,value):
        self.__name = value


    def __set_religion(self,religion):
        self.__religion = religion


    def __get_religion(self):
        return self.__religion

    
    def __del_religion(self):
        print('Doing house cleaning before deleting religion property')
        del self.__religion

    docstring_religion = 'Religion property allows you to set, get, and delete the value of __religion variable'
    religion = property(__get_religion, __set_religion, __del_religion,docstring_religion) 


person = Person('Robert Ingersoll','Agnostic')

person.name = 'Thomas Paine'
person.religion = 'Deism'

print(Person.religion.__doc__)
print(f'My religion is {person.religion}, I go by the name of {person.name}')
del person.religion

HERE,

  • class Person: defines a class called Person
  • __name = ''; __religion = '' defines two private variables __name and __religion.
  • def __init__(self, name,religion): defines a class constructor that can be used to initialize the values of name and religion.
  • @property; def name(self): defines a function called name that is decorated with the @property decorator. The function returns the value of the variable name.
  • @name.setter; def name(self,value): defines a function called name that is decorated with the setter function. This decoration is used to set new values for the property `name.
  • def __set_religion(self,religion): defines a private function called __set_religion that we will use to set the value of the variable __religion.
  • def __get_religion(self): defines a private function called __get_religion that will be used to get the value of the variable __religion.
  • def __del_religion(self): defines the function that will be executed when the variable __religion is deleted.
  • docstring_religion = '...' defines a string variable that describes the property religion
  • religion = property(__get_religion, __set_religion, __del_religion,docstring_religion) defines a property called religion using the built-in function property that three functions __get_religion, __set_religion, __del_religion for get,set and del methods for our property and the last parameter docstring_religion is a string that describes the property.
  • person = Person('Robert Ingersoll','Agnostic') defines an instance of person and sets the arguments 'Robert Ingersoll','Agnostic' as initialization values for our properties.
  • person.name = 'Thomas Paine' overrides the value of the name property with Thomas Paine
  • person.religion = 'Deism' overrides the value of the religion property with Deism
  • print(Person.religion.__doc__) calls the magic method __doc__ on the religion property which is in the Person class. Note: the magic method __doc__ is called directly on the Person class and not the instance of Person.
  • print(f'My religion is {person.religion}, I go by the name of {person.name}') used a formatted string to print the values of person.religion and person.name properties.

Executing the above code produces the following results.

Religion property allows you to set, get, and delete the value of __religion variable
My religion is Deism, I go by the name of Thomas Paine
Doing house cleaning before deleting religion property

Python class methods

Let's now look at class methods. A class method is a method within a class that exists independent of the class and returns the class object. The class method has access to the class and can modify the state of the class.

Let's work with a practical example. Suppose we have a class for math that accepts two parameters x and y and then sums during initialization like so

class Math:
    __sum = 0

    def __init__(self,x,y):
        self.__sum = x + y


    @property
    def sum(self):
        return self.__sum


math = Math(1,2)

print(f'The sum of math is {math.sum}')

HERE,

  • The above example defines a class Math with a private variable __sum that is initialized to the sum of parameters x and y assigning the result to __sum which is accessible via the property sum.

Executing the above code produces the following results.

The sum of math is 3

What if we want to get the product of x and y at the time that we create an instance of Math class without getting rid of the summation constructor, we can use a class method for that like so.

class Math:
    __sum = 0
    __product = 0

    def __init__(self,x,y):
        self.__sum = x + y


    @property
    def sum(self):
        return self.__sum


    @classmethod
    def multiplication(cls,x,y):
        cls.__product = x * y
        return cls(x,y)


    @property
    def product(self):
        return self.__product


math = Math(1,2)
print(f'The sum of math is {math.sum}')

p_math = Math.multiplication(3,4)
print(f'The sum of math is {p_math.sum}')
print(f'The product of math is {p_math.product}')

HERE,

  • @classmethod; def multiplication(cls,x,y): defines a class method using the decorator @classmethod named multiplication that accepts cls as the first parameter which is reference to the class itself and x,y as regular parameters.
  • cls.__product = x * y assigns to the __product variable of our class the product of x and y.
  • return cls(x,y) returns an instance of the class passing in the parameters x and y.
  • math = Math(1,2) creates an instance of the class Math passing in 1 and 2 as arguments.
  • p_math = Math.multiplication(3,4) creates an instance of the Math class using the class method multiplication

Executing the above code produces the following results.

The sum of math is 3
The sum of math is 7
The product of math is 12

Python static methods

Static methods are used to create utility functions and they can be called directly on the class without creating an instance of the class. Let's look at a practical example. Add the following code to the above class

    @staticmethod
    def square(x):
        return x * x

HERE,

  • @staticmethod; def square(x): defines a static method using the @staticmethod called square that returns the square of the number. Note: we only passed in one parameter x and we skipped the parameter that references the class.

and you can call the static method like so

print(f'The square of 35 is {Math.square(35)}')

HERE,

  • Math.square(35) calls the square method on the class Math directly without creating an instance of it.

Executing the above code produces the following result

The square of 35 is 1225

Python Class Methods Vs Static Methods

In this section, we will look at similarities and differences between class methods and static methods.

Similarities

The following are some of the similarities between class and static methods

  • They can both be called directly on the parent class without creating an instance of it first.
  • They are both defined using regular function that use decorators to turn them into either class or static method.

If you know more similarities, then use the comments section below to share.

Differences

The following are some of the differences between class and static methods

  • Class methods are aware of the class while static methods are not aware of the class at all.
  • Class methods modify the state of the class while static methods do not modify the state of the class
  • Class methods usually return the class instance itself while static methods don't.

Summary

Classes allow us to create blueprints of real-world entities. For example, we can model a real animal by creating a class Animal. Things like number of legs, and color are mapped to class attributes. Things like walking and eating are mapped to methods. Variables created from classes are called objects or instances of the class. Classes promote code reusability and diversity. An animal class can be used to create cat and dog objects etc.

What next?

If you enjoyed this lesson then show us your appreciation by creating a free accounts on our site. As always we appreciate your comments down below.


...