Python Constructor

In Python, a constructor is a special method that is called when an object of a class is created. The constructor method is used to initialize the instance variables of a class.

The constructor method is always named __init__ (with two underscores before and after the word init), and it takes the self parameter as the first argument, which refers to the object being created.

Here is an example of a simple class with a constructor:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

In this example, the Person class has two instance variables name and age. The constructor takes two arguments name and age, and initializes the instance variables with the values passed as arguments.

To create an object of the Person class, you can call the constructor as follows:

person1 = Person("Alice", 30)
person2 = Person("Bob", 25)

In this example, person1 and person2 are objects of the Person class, and they have their own copies of the name and age instance variables.

Counting the number of objects of a class:

In Python, you can count the number of objects of a class by using a class variable to keep track of the count. A class variable is a variable that is shared by all instances of a class.

Here is an example of a class with a class variable to count the number of objects:

class MyClass:
    count = 0

    def __init__(self):
        MyClass.count += 1

    def __del__(self):
        MyClass.count -= 1

In this example, the MyClass class has a class variable count initialized to zero. The constructor increments the count variable each time an object of the class is created, and the __del__ method decrements the count variable each time an object is deleted.

To access the count variable, you can use the class name like this:

print(MyClass.count)

This will print the current count of objects of the MyClass class.

Here is an example of how to create objects of the MyClass class and count them:

In this example, obj1, obj2, and obj3 are objects of the MyClass class. After creating them, the count is 3. After deleting obj1 and obj2, the count is reduced to 1.

Python Non-Parameterized Constructor:

In Python, a non-parameterized constructor is a constructor that takes no arguments. It is also known as a default constructor because it initializes the instance variables of a class with default values.

To define a non-parameterized constructor in Python, you can define a method called __init__ (with two underscores before and after the word init) that takes only the self parameter.

Here is an example of a class with a non-parameterized constructor:

class MyClass:
    def __init__(self):
        self.name = "John"
        self.age = 25

In this example, the MyClass class has a non-parameterized constructor that initializes the name instance variable to "John" and the age instance variable to 25.

To create an object of the MyClass class, you can simply call the constructor with no arguments:

obj = MyClass()

In this example, obj is an object of the MyClass class, and it has its own copies of the name and age instance variables initialized with the default values.

You can also override the default values of the instance variables by assigning new values to them after creating the object:

obj.name = "Alice"
obj.age = 30

In this example, the name instance variable of obj is set to "Alice" and the age instance variable is set to 30.

Python Parameterized Constructor:

In Python, a parameterized constructor is a constructor that takes one or more arguments to initialize the instance variables of a class. It allows you to create objects of a class with different initial values for the instance variables.

To define a parameterized constructor in Python, you can define a method called __init__ (with two underscores before and after the word init) that takes one or more parameters in addition to the self parameter.

Here is an example of a class with a parameterized constructor:

class MyClass:
    def __init__(self, name, age):
        self.name = name
        self.age = age

In this example, the MyClass class has a parameterized constructor that takes two parameters name and age, and initializes the name and age instance variables with the values passed as arguments.

To create an object of the MyClass class with a specific name and age, you can call the constructor with the values as arguments:

obj1 = MyClass("John", 25)
obj2 = MyClass("Alice", 30)

In this example, obj1 and obj2 are objects of the MyClass class, and they have their own copies of the name and age instance variables initialized with the values passed as arguments.

You can also change the values of the instance variables after creating the object:

obj1.name = "Bob"
obj1.age = 35

In this example, the name instance variable of obj1 is set to "Bob" and the age instance variable is set to 35.

Python Default Constructor:

In Python, a default constructor is a constructor that is automatically created if you don’t define any constructor explicitly. It takes no arguments and initializes the instance variables of a class with default values.

Here is an example of a class with a default constructor:

class MyClass:
    def __init__(self):
        self.name = "John"
        self.age = 25

In this example, the MyClass class has a default constructor that initializes the name instance variable to "John" and the age instance variable to 25.

To create an object of the MyClass class, you can simply call the constructor with no arguments:

obj = MyClass()

In this example, obj is an object of the MyClass class, and it has its own copies of the name and age instance variables initialized with the default values.

You can also override the default values of the instance variables by assigning new values to them after creating the object:

obj.name = "Alice"
obj.age = 30

In this example, the name instance variable of obj is set to "Alice" and the age instance variable is set to 30.

If you define any constructor explicitly, the default constructor will not be created automatically. In that case, you need to define a constructor for the class yourself.

More than One Constructor in Single class:

In Python, you can define more than one constructor in a single class by using method overloading. Method overloading allows you to define methods with the same name but different signatures (i.e., different parameters) in a class.

Here is an example of a class with two constructors:

class MyClass:
    def __init__(self):
        self.name = "John"
        self.age = 25
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

In this example, the MyClass class has two constructors: a default constructor that takes no arguments and initializes the name and age instance variables with default values, and a parameterized constructor that takes two arguments name and age, and initializes the name and age instance variables with the values passed as arguments.

To create an object of the MyClass class using the default constructor, you can simply call the constructor with no arguments:

obj1 = MyClass()

In this example, obj1 is an object of the MyClass class, and it has its own copies of the name and age instance variables initialized with the default values.

To create an object of the MyClass class using the parameterized constructor, you can call the constructor with the values as arguments:

obj2 = MyClass("Alice", 30)

In this example, obj2 is an object of the MyClass class, and it has its own copies of the name and age instance variables initialized with the values passed as arguments.

When you define more than one constructor in a class, the constructor with the most specific signature (i.e., the one that matches the arguments passed) is called. In the example above, if you call the constructor with two arguments, the parameterized constructor is called. If you call the constructor with no arguments, the default constructor is called.

Python built-in class functions:

In Python, there are several built-in class functions that you can use to define and manipulate classes. Here are some of the most commonly used ones:

  1. __init__(self[, args...]): The constructor function that initializes the instance variables of a class with the values passed as arguments.
  2. __str__(self): The function that returns a string representation of an object. This function is called when you use the print() function or the str() function on an object.
  3. __repr__(self): The function that returns a string representation of an object that can be used to recreate the object. This function is called when you use the repr() function on an object.
  4. __len__(self): The function that returns the length of an object. This function is called when you use the len() function on an object.
  5. __del__(self): The destructor function that is called when an object is deleted or goes out of scope.
  6. __setattr__(self, name, value): The function that sets the value of an instance variable.
  7. __getattr__(self, name): The function that gets the value of an instance variable.
  8. __getitem__(self, index): The function that gets the value of an item in a sequence or mapping object.
  9. __setitem__(self, index, value): The function that sets the value of an item in a sequence or mapping object.
  10. __call__(self[, args...]): The function that makes an object callable like a function.

These are just a few of the many built-in class functions in Python. Each function has its own specific purpose and can be used to customize the behavior of a class in various ways.

Built-in class attributes:

In Python, there are several built-in class attributes that you can use to access information about a class or its objects. Here are some of the most commonly used ones:

  1. __name__: The name of the class.
  2. __module__: The name of the module in which the class is defined.
  3. __doc__: The docstring of the class.
  4. __dict__: A dictionary containing the namespace of the class.
  5. __bases__: A tuple containing the base classes of the class.
  6. __class__: The class of an instance.

These built-in class attributes can be accessed using the dot notation. For example, to access the name of a class, you can use ClassName.__name__. Similarly, to access the module in which a class is defined, you can use ClassName.__module__.

Here is an example:

class MyClass:
    """This is a docstring for MyClass"""
    
    def __init__(self):
        self.name = "John"
        self.age = 25

print(MyClass.__name__)
# Output: MyClass

print(MyClass.__module__)
# Output: __main__

print(MyClass.__doc__)
# Output: This is a docstring for MyClass

print(MyClass.__dict__)
# Output: {'__module__': '__main__', '__doc__': 'This is a docstring for MyClass', '__init__': <function MyClass.__init__ at 0x7f945f65bf80>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>}

print(MyClass.__bases__)
# Output: <class 'object'>

obj = MyClass()
print(obj.__class__)
# Output: <class '__main__.MyClass'>

As you can see in the example, each built-in class attribute provides useful information about the class or its objects, and can be used to introspect the class and its behavior.