Classes and Objects in Python

Classes and Objects are fundamental parts of Object Oriented Programming (OOP). Python is an OOP language and almost everything (including strings, numbers, lists) are seen as objects. In OOP, an object has also "fuctions" and they are called "methods". The object is an instance of a class: the class is a template that describes all the properties and methods while the object is a specific entity which has the class structure but filled with data.

The keyword class is used for the creation of a class. Once the class is created, an object can be instantiated from the class as shown below. The class needs to have an __init__ method, called constructor, which is executed once the object is created from the class so all the variables of the class can be set to specific values. The variable self is used as a reference of the object created in order to access specific variables and methods of the object (like in the case below "name" and "link"), other variable names can be used instead of self but this is the convention.

#Class Website
class Website:
  def __init__(self, name, link):   # Initialize variables name and link
    self.name = name
    self.link = link
	
#Create the object from the class Website
web=Website("ValianTek World","www.valiantekworld.com")

#Access the values
print(web.name)
print(web.link)

As previously mentioned, we can also include methods in the class and this is done in the same way we create functions: with the keyword def but we also include the reference variable self which needs to be the first parameter: this is not passed by the user given that it is simply a reference used for the object created.

#Class Website
class Website:
	def __init__(self, name, link):   # Initialize variables name and link
		self.name = name
		self.link = link

	def print_name(self):    # Method that prints the website name
		print("The name of the website is",self.name)

	def print_info(self,info):    # Method that prints name or link
		if (info=="name"):
			print("The name of the website is",self.name)
		else:
			print("The link of the website is",self.link)			
		
#Create the object from the class Website		
web=Website("ValianTek World","www.valiantekworld.com")

#Call first method
web.print_name()    # This method has no arguments

#Call second method
web.print_info("name")   # By using argument "name", it prints the same of the first method
web.print_info("link")   # By using argument "link", it prints the same of the first method

It is possible to modify the the variables of an object by simply assigning a new value to them or by creating a method with that specific purpose. It is also possible to delete specific variables, with del, which then are not anymore part of the object, as shown below

class Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		
	def get_side(self):      # Print side of the square
		print("The side is",self.side)
		
	def set_side(self,new_value):   # Assign a new value to the side
		self.side=new_value
		
s=Square(4)
s.get_side()   # Print side, it prints 4
s.set_side(5)  # Set size to 5
s.get_side()   # It prints 5
s.side=8       # Directly assign value 8
s.get_side()   # It prints 8
del s.side     # Deletes side variable
s.get_side()   # This throws an error because variable does not exists anymore
del s          # This also deletes the object s

The assignment of an object to a new variable is simply copying the reference and in this way both the variables are linked to the same object.

class Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		
s1=Square(4)      # Initial value
s2=s1
s2.side=8		  # s2 has now side 8
print(s1.side)    # They are the same object, so s1 is also side 8

As mentioned before the constructor __init__ is called everytime the object is created and, in the same way, it is possible to use a destructor __del__ everytime the object is deleted. Some operations that are typically done when an object is created is to delete all the variables within the object to free space, then this can be joined by custom operations that depend on the program created. It is important to mention that Python has a Garbage Collector which automatically deletes variables/objects that cannot be used anymore, so the destructor is not really essential although it can be useful.

class Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		print("Object Created!")

	def __del__(self):  #Deleting variable
		del self.side
		print("Object Deleted!")
		
s=Square(4)   # Prints "Object Created!"
del s         # Prints "Object Deleted!"

A class can also include the method __str__ which is used to create a string representation of the specific object that is calling it. In order to call it, it is simply required to print the object.

class Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		print("Object Created!")
		
s1=Square(4)
print(s1)     # It prints <__main__.Square object at 0x000001C7A8A238B0>

class New_Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		print("Object Created!")
		
	def __str__(self):    # The method needs to return the string
		return "The square side is "+str(self.side)
		
s2=New_Square(5)
print(s2)        # It prints "The square side is 5"

It is also possible to change the meaning of particular operations when dealing with classes. This is called Operator Overloading, for example we can define what does it mean to use the operator "+" within two objects. This is done by creating the method __add__ (there are other methods for other operations such as __mul__ for multiplication and so on).

class Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		
s1=Square(2)
s2=Square(3)
s3=s1+s2     # This throws an error because it is not clear what this operation should do

class New_Square:
	def __init__(self,side):  #Square class with side variable
		self.side=side
		
	def __add__(self,other_square):    			# The method add takes into account the current object and the other object
		new_value=self.side+other_square.side   # For example we can define __add__ as the sum of the sides of the two objects
		return New_Square(new_value)            # Return a new square object with the new value

s1=New_Square(2)
s2=New_Square(3)
s3=s1+s2         # No error now
print(s3.side)   # It prints 5  (i.e. 2+3)

This gives an overview on how to create classes and objects and what operations can be done. Use the console below and create some classes and objects and familiarize with these concepts.