In object-oriented programming (OOP), a class is like a blueprint or template for creating objects. Objects are instances of classes. When we say "instantiating a class," we mean creating an object from that class.

We have already covered how to create a single instance of class:

#class declaration
class MyClass(object):
    
    #constructor
    def __init__(self, name): # constructor
        self.name = name   # assign local variable in object
    
    #functions of the class
    def print_my_name(self):
       print("My name is: " + self.name)

#create a class instance
my_class_instance = MyClass("Lucy")
print (my_class_instance)
#execute some of the functions
my_class_instance.print_my_name()

In the example above, " my_class_instance " is the object, referred to as the instance of the class.

The great benefit of classes is that we can instantiate multiple objects from a class, keeping the code of the class modular and adaptable to multiple conditions.

Let's create multiple instances of a class using the last example:

#class declaration
class MyClass(object):
    
    #constructor
    def __init__(self, name): # constructor
        self.name = name   # assign local variable in object
    
    #functions of the class
    def print_my_name(self):
       print("My name is: " + self.name)

#create a class instance
my_class_instance_1 = MyClass("Lucy")
my_class_instance_2 = MyClass("Peter")
my_class_instance_3 = MyClass("Alex")


print (my_class_instance_1)
print (my_class_instance_2)
print (my_class_instance_3)

In the example above, we are manually creating 3 instances of a class, each one with different arguments for the name of the object. The constructor of the class is allowing us to pass different information to each instance.

We can also do this within a loop:

import random

#class declaration
class MyClass(object):
    
    #constructor
    def __init__(self, my_color): # constructor
        self.my_color = my_color   # assign local variable in object
    
    #functions of the class
    def print_my_color(self):
       print("My color is: " + str(self.my_color) ) #converting the integer to string

#Lets create a loop and create instances of the class within it
for i in range(0,20):
    #random color (0-255)
    rand_color = random.randrange(0,255) #random color
    #create a class instance
    my_class_instance = MyClass(rand_color)
    
    my_class_instance.print_my_color()

Notice that in the example above, we do the class instantiation within a for loop. This allows us to create 20 instances of the class, therefore 20 objects. Each object is using a different value obtained from the random function.

As we create objects within a for-loop structure, it might be a good idea to store them in a list in order to reference them later:

import random

#Create an empty list 
myList = []

#class declaration
class MyClass(object):
    
    #constructor
    def __init__(self, my_color): # constructor
        self.my_color = my_color   # assign local variable in object
    
    #functions of the class
    def print_my_color(self):
       print("My color is: " + str(self.my_color) ) #converting the integer to string


for i in range(0,20):
    #random color (0-255)
    rand_color = random.randrange(0,255) #random color
    #create a class instance
    my_class_instance = MyClass(rand_color)
    
    myList.append(my_class_instance)
    
#Execute the functions for all elements inside the list
for x in myList:
    x.print_my_color()

Notice that in the example above, we store all the instantiated objects in a list using append.

Later, we can do a very simple loop throughout the elements in the list and call their print function.