Unit 3
Unit 3
UNIT – III
Python Modules
In this article, you will learn to create and import custom modules in Python. Also, you will
find different techniques to import and use custom and built-in modules in Python.
What are modules in Python?
Modules refer to a file containing Python statements and definitions.
A file containing Python code, for example: example.py, is called a module, and its module
name would be example.
We use modules to break down large programs into small manageable and organized files.
Furthermore, modules provide reusability of code.
We can define our most used functions in a module and import it, instead of copying their
definitions into different programs.
Let us create a module. Type the following and save it as example.py.
result = a + b
return result
Here, we have defined a function add() inside a module named example. The function takes
in two numbers and returns their sum.
This does not import the names of the functions defined in example directly in the current
symbol table. It only imports the module name example there.
Using the module name we can access the function using the dot . operator. For example:
>>> example.add(4,5.5)
9.5
Python has tons of standard modules. You can check out the full list of Python standard
modules and their use cases. These files are in the Lib directory inside the location where you
installed Python.
Standard modules can be imported the same way as we import our user-defined modules.
There are various ways to import modules. They are listed below..
import math
print("The value of pi is", math.pi)
import math as m
print("The value of pi is", m.pi)
We have renamed the math module as m. This can save us typing time in some cases.
Note that the name math is not recognized in our scope. Hence, math.pi is invalid,
and m.pi is the correct implementation.
Here, we have imported all the definitions from the math module. This includes all names
visible in our scope except those beginning with an underscore(private definitions).
Importing everything with the asterisk (*) symbol is not a good programming practice. This
can lead to duplicate definitions for an identifier. It also hampers the readability of our code.
We can add and modify this list to add our own path.
6
Reloading a module
The Python interpreter imports a module only once during a session. This makes things more
efficient. Here is an example to show how this works.
Suppose we have the following code in a module named my_module.
We can see that our code got executed only once. This goes to say that our module was
imported only once.
Now if our module changed during the course of the program, we would have to reload
it.One way to do this is to restart the interpreter. But this does not help much.
Python provides a more efficient way of doing this. We can use the reload() function inside
the imp module to reload a module. We can do it in the following ways:
>>> dir(example)
['__builtins__',
'__cached__',
'__doc__',
'__file__',
'__initializing__',
'__loader__',
'__name__',
'__package__',
'add']
Here, we can see a sorted list of names (along with add). All other names that begin with an
underscore are default Python attributes associated with the module (not user-defined).
For example, the __name__ attribute contains the name of the module.
All the names defined in our current namespace can be found out using the dir() function
without any arguments.
>>> a = 1
>>> b = "hello"
>>> import math
>>> dir()
6
Python provides a getopt module that helps you parse command-line options and arguments.
$ python test.py arg1 arg2 arg3
The Python sys module provides access to any command-line arguments via the sys.argv.
This serves two purposes −
Example
import sys
NOTE − As mentioned above, first argument is always script name and it is also being
counted in number of arguments.
Python provided a getopt module that helps you parse command-line options and
arguments. This module provides two functions and an exception to enable command line
argument parsing.
getopt.getopt method
This method parses command line options and parameter list. Following is simple syntax for
this method −
getopt.getopt(args, options, [long_options])
Exception getopt.GetoptError
This is raised when an unrecognized option is found in the argument list or when an option
requiring an argument is given none.
The argument to the exception is a string indicating the cause of the error. The
attributes msg and opt give the error message and related option.
Example
Consider we want to pass two file names through command line and we also want to give an
option to check the usage of the script. Usage of the script is as follows −
6
def main(argv):
inputfile = ''
outputfile = ''
try:
opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
except getopt.GetoptError:
print 'test.py -i <inputfile> -o <outputfile>'
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print 'test.py -i <inputfile> -o <outputfile>'
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile = arg
elif opt in ("-o", "--ofile"):
outputfile = arg
print 'Input file is "', inputfile
print 'Output file is "', outputfile
if __name__ == "__main__":
main(sys.argv[1:])
$ test.py -i BMP -o
usage: test.py -i <inputfile> -o <outputfile>
$ test.py -i inputfile
Input file is " inputfile
Output file is "
The Python Standard Library is a collection of script modules accessible to a Python program
to simplify the programming process and removing the need to rewrite commonly used
commands. They can be used by 'calling/importing' them at the beginning of a script.
It is important to become familiar with the Python Standard Library as so many problems can
be solved quickly if you are familiar with the things that these libraries can do.
A list of the Standard Library modules, the following are among the most important:
Time
The datetime module provides us with the objects which we can use to store information
about date and time: are not associated with a
sys - sys:
The sys module contains system-specific functionality. The sys module has a
version_info tuple that gives us information about the version.
math
Random
6
re
An object is simply a collection of data (variables) and methods (functions) that act on those
data. Similarly, a class is a blueprint for that object.
We can think of a class as a sketch (prototype) of a house. It contains all the details about the
floors, doors, windows, etc. Based on these descriptions we build the house. House is the
object.
As many houses can be made from a house's blueprint, we can create many objects from a
class. An object is also called an instance of a class and the process of creating this object is
called instantiation.
6
Like function definitions begin with the def keyword in Python, class definitions begin with
a class keyword.
The first string inside the class is called docstring and has a brief description of the class.
Although not mandatory, this is highly recommended.
class MyNewClass:
'''This is a docstring. I have created a new class'''
pass
A class creates a new local namespace where all its attributes are defined. Attributes may be
data or functions.
There are also special attributes in it that begins with double underscores __. For
example, __doc__ gives us the docstring of that class.
As soon as we define a class, a new class object is created with the same name. This class
object allows us to access the different attributes as well as to instantiate new objects of that
class.
class Person:
"This is a person class"
age = 10
def greet(self):
print('Hello')
# Output: 10
print(Person.age)
6
Output
10
<function Person.greet at 0x7fc78c6e8160>
This is a person class
We saw that the class object could be used to access different attributes.
It can also be used to create new object instances (instantiation) of that class. The procedure
to create an object is similar to a function call.
This will create a new object instance named harry. We can access the attributes of objects
using the object name prefix.
Attributes may be data or method. Methods of an object are corresponding functions of that
class.
class Person:
"This is a person class"
age = 10
6
def greet(self):
print('Hello')
Output
You may have noticed the self parameter in function definition inside the class but we called
the method simply as harry.greet() without any arguments. It still worked.
This is because, whenever an object calls its method, the object itself is passed as the first
argument. So, harry.greet() translates into Person.greet(harry).
In general, calling a method with a list of n arguments is equivalent to calling the
corresponding function with an argument list that is created by inserting the method's object
before the first argument.
For these reasons, the first argument of the function in class must be the object itself. This is
conventionally called self. It can be named otherwise but we highly recommend to follow the
convention.
Now you must be familiar with class object, instance object, function object, method object
and their differences.
6
Constructors in Python
Class functions that begin with double underscore __ are called special functions as they
have special meaning.
Of one particular interest is the __init__() function. This special function gets called
whenever a new object of that class is instantiated.
This type of function is also called constructors in Object Oriented Programming (OOP). We
normally use it to initialize all the variables.
class ComplexNumber:
def __init__(self, r=0, i=0):
self.real = r
self.imag = i
def get_data(self):
print(f'{self.real}+{self.imag}j')
Output
2+3j
(5, 0, 10)
Traceback (most recent call last):
File "<string>", line 27, in <module>
print(num1.attr)
AttributeError: 'ComplexNumber' object has no attribute 'attr'
In the above example, we defined a new class to represent complex numbers. It has two
functions, __init__() to initialize the variables (defaults to zero) and get_data() to display the
number properly.
An interesting thing to note in the above step is that attributes of an object can be created on
the fly. We created a new attribute attr for object num2 and read it as well. But this does not
create that attribute for object num1.
Any attribute of an object can be deleted anytime, using the del statement. Try the following
on the Python shell to see the output.
We can even delete the object itself, using the del statement.
6
>>> c1 = ComplexNumber(1,3)
>>> del c1
>>> c1
Traceback (most recent call last):
...
NameError: name 'c1' is not defined
Python Inheritance
Inheritance enables us to define a class that takes all the functionality from a parent class and
allows us to add more. In this tutorial, you will learn to use inheritance in Python.
Inheritance in Python
It refers to defining a new class with little or no modification to an existing class. The new
class is called derived (or child) class and the one from which it inherits is called the base
(or parent) class.
class BaseClass:
class DerivedClass(BaseClass):
Derived class inherits features from the base class where new features can be added to it. This
results in re-usability of code.
class Polygon:
def __init__(self, no_of_sides):
self.n = no_of_sides
self.sides = [0 for i in range(no_of_sides)]
def inputSides(self):
self.sides = [float(input("Enter side "+str(i+1)+" : ")) for i in range(self.n)]
def dispSides(self):
for i in range(self.n):
print("Side",i+1,"is",self.sides[i])
This class has data attributes to store the number of sides n and magnitude of each side as a
list called sides.
The inputSides() method takes in the magnitude of each side and dispSides() displays these
side lengths.
A triangle is a polygon with 3 sides. So, we can create a class called Triangle which inherits
from Polygon. This makes all the attributes of Polygon class available to the Triangle class.
We don't need to define them again (code reusability). Triangle can be defined as follows.
class Triangle(Polygon):
def __init__(self):
Polygon.__init__(self,3)
def findArea(self):
a, b, c = self.sides
# calculate the semi-perimeter
s = (a + b + c) / 2
area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('The area of the triangle is %0.2f' %area)
However, class Triangle has a new method findArea() to find and print the area of the
triangle. Here is a sample run.
>>> t = Triangle()
>>> t.inputSides()
Enter side 1 : 3
Enter side 2 : 5
6
Enter side 3 : 4
>>> t.dispSides()
Side 1 is 3.0
Side 2 is 5.0
Side 3 is 4.0
>>> t.findArea()
The area of the triangle is 6.00
We can see that even though we did not define methods like inputSides() or dispSides() for
class Triangle separately, we were able to use them.
If an attribute is not found in the class itself, the search continues to the base class. This
repeats recursively, if the base class is itself derived from other classes.
In the above example, notice that __init__() method was defined in both classes, Triangle as
well Polygon. When this happens, the method in the derived class overrides that in the base
class. This is to say, __init__() in Triangle gets preference over the __init__ in Polygon.
Generally when overriding a base method, we tend to extend the definition rather than simply
replace it. The same is being done by calling the method in base class from the one in derived
class (calling Polygon.__init__() from __init__() in Triangle).
A better option would be to use the built-in function super(). So, super().__init__(3) is
equivalent to Polygon.__init__(self,3) and is preferred. To learn more about
the super() function in Python, visit Python super() function.
Two built-in functions isinstance() and issubclass() are used to check inheritances.
The function isinstance() returns True if the object is an instance of the class or other classes
derived from it. Each and every class in Python inherits from the base class object.
6
>>> isinstance(t,Triangle)
True
>>> isinstance(t,Polygon)
True
>>> isinstance(t,int)
False
>>> isinstance(t,object)
True
>>> issubclass(Polygon,Triangle)
False
>>> issubclass(Triangle,Polygon)
True
>>> issubclass(bool,int)
True
In this tutorial, you'll learn about multiple inheritance in Python and how to use it in your
program. You'll also learn about multi-level inheritance and the method resolution order.
A class can be derived from more than one base class in Python, similar to C++. This is
called multiple inheritance.
In multiple inheritance, the features of all the base classes are inherited into the derived class.
The syntax for multiple inheritance is similar to single inheritance.
Example
6
class Base1:
pass
class Base2:
pass
Here, the MultiDerived class is derived from Base1 and Base2 classes.
The MultiDerived class inherits from both Base1 and Base2 classes.
We can also inherit from a derived class. This is called multilevel inheritance. It can be of
any depth in Python.
6
In multilevel inheritance, features of the base class and the derived class are inherited into the
new derived class.
class Base:
pass
class Derived1(Base):
pass
class Derived2(Derived1):
pass
Here, the Derived1 class is derived from the Base class, and the Derived2 class is derived
from the Derived1 class.
Every class in Python is derived from the object class. It is the most base type in Python.
So technically, all other classes, either built-in or user-defined, are derived classes and all
objects are instances of the object class.
# Output: True
print(issubclass(list,object))
# Output: True
print(isinstance(5.5,object))
# Output: True
print(isinstance("Hello",object))
In the multiple inheritance scenario, any specified attribute is searched first in the current
class. If not found, the search continues into parent classes in depth-first, left-right fashion
without searching the same class twice.
MRO of a class can be viewed as the __mro__ attribute or the mro() method. The former
returns a tuple while the latter returns a list.
>>> MultiDerived.__mro__
(<class '__main__.MultiDerived'>,
<class '__main__.Base1'>,
<class '__main__.Base2'>,
<class 'object'>)
>>> MultiDerived.mro()
6
[<class '__main__.MultiDerived'>,
<class '__main__.Base1'>,
<class '__main__.Base2'>,
<class 'object'>]
Here is a little more complex multiple inheritance example and its visualization along with
the MRO.
# Demonstration of MRO
class X:
pass
class Y:
pass
class Z:
pass
6
# Output:
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class '__main__.Z'>,
# <class 'object'>]
print(M.mro())
Output
To know the actual algorithm on how MRO is calculated, visit Discussion on MRO.
You can change the meaning of an operator in Python depending upon the operands used. In
this tutorial, you will learn how to use operator overloading in Python Object Oriented
Programming.
Python operators work for built-in classes. But the same operator behaves differently with
different types. For example, the + operator will perform arithmetic addition on two
numbers, merge two lists, or concatenate two strings.
6
This feature in Python that allows the same operator to have different meaning according to
the context is called operator overloading.
So what happens when we use them with objects of a user-defined class? Let us consider the
following class, which tries to simulate a point in 2-D coordinate system.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)
Output
Here, we can see that a TypeError was raised, since Python didn't know how to add
two Point objects together.
However, we can achieve this task in Python through operator overloading. But first, let's get
a notion about special functions.
Class functions that begin with double underscore __ are called special functions in Python.
6
These functions are not the typical functions that we define for a class.
The __init__() function we defined above is one of them. It gets called every time we create
a new object of that class.
There are numerous other special functions in Python. Visit Python Special Functions to learn
more about them.
Using special functions, we can make our class compatible with built-in functions.
>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>
Suppose we want the print() function to print the coordinates of the Point object instead of
what we got. We can define a __str__() method in our class that controls how the object gets
printed. Let's look at how we can achieve this:
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
p1 = Point(2, 3)
print(p1)
Output
6
(2, 3)
That's better. Turns out, that this same method is invoked when we use the built-in
function str() or format().
>>> str(p1)
'(2,3)'
>>> format(p1)
'(2,3)'
So, when you use str(p1) or format(p1), Python internally calls the p1.__str__() method.
Hence the name, special functions.
Now let's go back to operator overloading.
To overload the + operator, we will need to implement __add__() function in the class. With
great power comes great responsibility. We can do whatever we like, inside this function. But
it is more sensible to return a Point object of the coordinate sum.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x, self.y)
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x, self.y)
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)
Output
(3,5)
What actually happens is that, when you use p1 + p2, Python calls p1.__add__(p2) which in
turn is Point.__add__(p1,p2). After this, the addition operation is carried out the way we
specified.
Similarly, we can overload other operators as well. The special function that we need to
implement is tabulated below.
Addition p1 + p2 p1.__add__(p2)
Subtraction p1 - p2 p1.__sub__(p2)
6
Multiplication p1 * p2 p1.__mul__(p2)
Power p1 ** p2 p1.__pow__(p2)
Division p1 / p2 p1.__truediv__(p2)
Bitwise OR p1 | p2 p1.__or__(p2)
Python does not limit operator overloading to arithmetic operators only. We can overload
comparison operators as well.
Suppose we wanted to implement the less than symbol < symbol in our Point class.
6
Let us compare the magnitude of these points from the origin and return the result for this
purpose. It can be implemented as follows.
def __str__(self):
return "({0},{1})".format(self.x, self.y)
p1 = Point(1,1)
p2 = Point(-2,-3)
p3 = Point(1,-1)
Output
True
False
False
Similarly, the special functions that we need to implement, to overload other comparison
operators are tabulated below.
Equal to p1 == p2 p1.__eq__(p2)
Python setattr()
In this tutorial, we will learn about the Python setattr() function with the help of examples.
class Student:
marks = 88
name = 'Sheeran'
person = Student()
print(person.name)
print(person.marks)
# Output: Adam
6
# 78
setattr() Syntax
setattr() Parameters
class Person:
name = 'Adam'
p = Person()
print('Before modification:', p.name)
Output
If the attribute is not found, setattr() creates a new attribute an assigns value to it. However,
this is only possible if the object implements the __dict__() method.
You can check all the attributes of an object by using the dir() function.
class Person:
name = 'Adam'
p = Person()
6
Output
Python getattr()
In this tutorial, we will learn about the Python getattr() method with the help of examples.
The getattr() method returns the value of the named attribute of an object. If not found, it
returns the default value provided to the function.
Example
class Student:
marks = 88
name = 'Sheeran'
person = Student()
print(name)
print(marks)
6
# Output: Sheeran
# 88
getattr() Syntax
object.name
getattr() Parameters
class Person:
age = 23
name = "Adam"
person = Person()
print('The age is:', getattr(person, "age"))
Output
class Person:
age = 23
name = "Adam"
person = Person()
Output
The named attribute sex is not present in the class Person. So, when calling getattr() method
with a default value Male, it returns Male.
But, if we don't provide any default value, when the named attribute sex is not found, it raises
an AttributeError saying the object has no sex attribute.
Python property()
property() Parameters
property() returns the property attribute from the given getter, setter, and deleter.
If no arguments are given, property() returns a base property attribute that doesn't
contain any getter, setter or deleter.
If doc isn't provided, property() takes the docstring of the getter function.
class Person:
def __init__(self, name):
self._name = name
def get_name(self):
print('Getting name')
return self._name
def del_name(self):
print('Deleting name')
del self._name
p = Person('Adam')
print(p.name)
p.name = 'John'
del p.name
Output
6
Getting name
The name is: Adam
Setting name to John
Deleting name
Here, _name is used as the private variable for storing the name of Person.
We also set:
Instead of using property(), you can use the Python decorator @property to assign the getter,
setter, and deleter.
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
print('Getting name')
return self._name
@name.setter
def name(self, value):
print('Setting name to ' + value)
self._name = value
@name.deleter
def name(self):
print('Deleting name')
6
del self._name
p = Person('Adam')
print('The name is:', p.name)
p.name = 'John'
del p.name
Output
Getting name
The name is: Adam
Setting name to John
Deleting name
This is done by using @name.setter for the setter method and @name.deleter for the deleter
method.
Notice, we've used the same method name() with different definitions for defining the getter,
setter, and deleter.
Now, whenever we use p.name, it internally calls the appropriate getter, setter, and deleter as
shown by the printed output present inside the method.
In this tutorial, we are going to discuss the name mangling process in Python and how we can
use the name mangling process in Python with different methods.
Name Mangling
A process in which any given identifier with one trailing underscore and two leading
underscores is textually replaced with the __ClassName__Identifier is known as Name
mangling. In __ClassName__Identifier name, ClassName is the name of current class where
identifier is present.
Illustration:
6
Basically, above given definition of name mangling means that any identifier in the form
such as __Jtp (Either at least two leading underscores or at most one underscore trailing the
name) will be replaced by __ClassName__Jtp (the name of the current class will replace
ClassName) with the leading underscore (s) striped in ClassName.
Example:
Output:
JavaTpoint
Explanation:
We have defined a testing class with a name identifier in the class in the above program.
Inside the testing class, we have defined two default functions and one with the PrintName().
In the PrintName() function, we have given the print command to print the name. Then, we
initialized a t1 variable with the testing class. In last, we have used PrintName() to print the
name we used in the Testing class while initializing it.
Note: If we try to access the functions and variables of the Testing class outside the
class, it will throw an error. Any changes made to the variable given inside the Testing
Class can be done inside the class only.
Example: 2
1. class Testing:
6
Output:
JavaTpoint
Traceback (most recent call last):
File "C:\Users\Manish\Downloads\code.py", line 12, in
print(t1.__name) # will throw an error in the output
AttributeError: 'Testing' object has no attribute '__name'
Implementation of the name mangling process in Python is the same as we have discussed
above. We will use different methods in our Python program to implement the name
mangling process and accessing variables in it.
We will use a program for each method to understand its implementation in Python.
We can use the dir() method to perform the name mangling process, and it will be done to a
class given in the code. The Python interpreter will do the process of name mangling to the
class. We can use the dir() method by passing the defined class object in it, and the dir()
method will return all the valid attributes belonging to the given class object.
Look at the following exemplar program to understand this dir() method of name mangling:
Example:
6
Output:
Explanation:
As we look at the output, we can see that the dir() method we used on the initialized variable,
i.e., t1, returned all the valid attributes of the class testing and printed them. We can also see
that the name of the identifier, i.e., __name, is changed to _Testing__name by the interpreter.
We can access the name mangled variables even outside the class and print the in output (Not
like accessing the class variable that will return an error). To access the name mangled
variables outside the class, we simply have to add _ClassName with the variable, and we can
also print the value in the output.
Look at the following program where we have accessed name mangled variables outside the
testing class.
Example:
8. print("The name mangled that we are accessing outside the class: ", t1._Testing__nam
e)
Output:
The name mangled that we are accessing outside the class: JavaTpoint
Explanation:
We have been able to access the __name variable outside as it was a name mangled variable,
and it returned the name value in the output.
As we are using the name mangling process in our program, we are limited because of little
support for a valid use case of members from a private class. The limited support for the
private class member's valid use case is to avoid name clashes of various names with names
defined inside the subclasses. As long as the name mangling process will occur as per the
definition of a Python class, the mangling process will be done by the interpreter. And, it is
very helpful for the subclasses in the program to let them override methods without even
breaking calls of the interclass method.
Example:
Output:
Conclusion
First, we have learned about the introduction of the Name mangling process in this tutorial.
We also learned that how we can use the dir() method for name mangling in Python. Then,
we accessed the name mangled variables outside the class in which they are present. In last,
we also learn about that how we can use the name mangling process with method overriding
in given subclasses in the program.
In Object-Oriented Programming, we have (drum roll please) objects. These objects consist
of properties and behavior. Furthermore, properties of the object are defined by the attributes
and the behavior is defined using methods. These methods are defined inside a class. These
methods are the reusable piece of code that can be invoked/called at any point in the program.
Python offers various types of these methods. These are crucial to becoming an efficient
Instance Method
Class Method
Static Method
Instance Methods
The purpose of instance methods is to set or get details about instances (objects), and that is
why they’re known as instance methods. They are the most common type of methods used in
a Python class.
6
They have one default parameter- self, which points to an instance of the class. Although you
don’t have to pass that every time. You can change the name of this parameter but it is better
Any method you create inside a class is an instance method unless you specially specify
class My_class:
def instance_method(self):
return "This is an instance method."
In order to call an instance method, you’ve to create an object/instance of the class. With the
help of this object, you can access any method of the class.
obj = My_class()
obj.instance_method()
When the instance method is called, Python replaces the self argument with the instance
object, obj. That is why we should add one default parameter while defining the instance
methods. Notice that when instance_method() is called, you don’t have to pass self. Python
Along with the default parameter self, you can add other parameters of your choice as well:
class My_class:
We have an additional parameter “a” here. Now let’s create the object of the class and call
obj = My_class()
obj.instance_method(10)
Again you can see we have not passed ‘self’ as an argument, Python does that for us. But
have to mention other arguments, in this case, it is just one. So we have passed 10 as the
value of “a”.
You can use “self” inside an instance method for accessing the other attributes and methods
class My_class:
def instance_method(self):
return f"This is the instance method and it can access the variables a = {self.a} and\
b = {self.b} with the help of self."
Note that the __init__() method is a special type of method known as a constructor. This
method is called when an object is created from the class and it allows the class to initialize
obj = My_class(2,4)
obj.instance_method()
With the help of the “self” keyword- self.a and self.b, we have accessed the variables present
Along with the objects of a class, an instance method can access the class itself with the help
class My_class():
def instance_method(self):
print("Hello! from %s" % self.__class__.__name__)
6
obj = My_class()
obj.instance_method()
The self.__class__.__name__ attribute returns the name of the class to which class
instance(self) is related.
2. Class Methods
The purpose of the class methods is to set or get the details (status) of the class. That is why
they are known as class methods. They can’t access or modify specific instance data. They
are bound to the class instead of their objects. Two important things about class methods:
In order to define a class method, you have to specify that it is a class method with the
help of the @classmethod decorator
Class methods also take one default parameter- cls, which points to the class. Again,
this not mandatory to name the default parameter “cls”. But it is always better to go
with the conventions
class My_class:
@classmethod
def class_method(cls):
return "This is a class method."
As simple as that!
As I said earlier, with the help of the instance of the class, you can access any method. So
we’ll create the instance of this My_class as well and try calling this class_method():
obj = My_class()
6
obj.class_method()
This works too! We can access the class methods with the help of a class instance/object. But
we can access the class methods directly without creating an instance or object of the class.
My_class.class_method()
Without creating an instance of the class, you can call the class method with
– Class_name.Method_name().
But this is not possible with instance methods where we have to create an instance of the
class in order to call instance methods. Let’s see what happens when we try to call the
My_class.instance_method()
We got an error stating missing one positional argument – “self”. And it is obvious because
instance methods accept an instance of the class as the default parameter. And you are not
providing any instance as an argument. Though this can be bypassing the object name as the
argument:
My_class.instance_method(obj)
6
3. Static Methods
Static methods cannot access the class data. In other words, they do not need to access the
class data. They are self-sufficient and can work on their own. Since they are not attached to
any class attribute, they cannot get or set the instance state or class state.
In order to define a static method, we can use the @staticmethod decorator (in a similar way
we used @classmethod decorator). Unlike instance methods and class methods, we do not
need to pass any special or default parameters. Let’s look at the implementation:
class My_class:
@staticmethod
def static_method():
return "This is a static method."
And done!
Notice that we do not have any default parameter in this case. Now how do we call static
methods? Again, we can call them using object/instance of the class as:
obj = My_class()
obj.static_method()
And we can call static methods directly, without creating an object/instance of the class:
My_class.static_method()
6
You can notice the output is the same using both ways of calling static methods.
o An instance method knows its instance (and from that, it’s class)
o A class method knows its class
o A static method doesn’t know its class or instance
The instance methods are the most commonly used methods. Even then there is difficulty in
knowing when you can use class methods or static methods. The following explanation will
Class Method – The most common use of the class methods is for creating factory methods.
Factory methods are those methods that return a class object (like a constructor) for different
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
Here as you can see, the class method is modifying the status of the class. If we have the year
of birth of any dog instead of the age, then with the help of this method we can modify the
Dog1 = Dog('Bruno', 1)
Dog1.name , Dog1.age
Here we have constructed an object of the class. This takes two parameters name and age. On
printing the attributes of the class we get Bruno and 1 as output, which was the values we
provided.
Here, we have constructed another object of the class Dog using the class
method Year(). The Year() method takes Person class as the first parameter cls and returns
the constructor by calling cls(name, date.today().year – year), which is equivalent
to Dog(name, date.today().year – year).
As you can see in printing the attributes name and age we got the name that we provided and
the age converted from the year of birth using the class method.
Static Method – They are used for creating utility functions. For accomplishing routine
programming tasks we use utility functions. A simple example could be:
class Calculator:
@staticmethod
def add(x, y):
return x + y
You can see that the use-case of this static method is very clear, adding the two numbers
given as parameters. Whenever you have to add two numbers, you can call this method
class Specialstring:
def __len__(self):
return 21
# Driver's code
if __name__ == "__main__":
string = Specialstring()
print(len(string))
Output:
21
In this case, we call method len() gives the return value from __len__ method.
Here __len__ method defines the property of the class Specialstring
The object’s type itself is not significant in this we do not declare the argument in method
prototypes. This means that compilers can not do type-checking. Therefore, what really
matters is if the object has particular attributes at run time. Duck typing is hence
implemented by dynamic languages. But now some of the static languages like Haskell also
supports it. But, Java/C# doesn’t have this ability yet.
Example: Now, lets look demonstrates how an object be used in any other circumstances
until it is not supported.
# duck typing
class Bird:
def fly(self):
print("fly with wings")
class Airplane:
def fly(self):
print("fly with fuel")
class Fish:
def swim(self):
print("fish swim in sea")
Output:
fly with wings
fly with fuel
Traceback (most recent call last):
File "/home/854855e5570b9ce4a9e984209b6a1c21.py", line 20, in
obj.fly()
AttributeError: 'Fish' object has no attribute 'fly'
In this example, we can see a class supports some method we can modify it or give them
new functionality. Duck-typing emphasis what the object can really do, rather than what the
object is.
Everything in Python is an object and we define objects through classes. When we define an
object, we actually create an instance of a class. Thus, class is the most fundamental piece in
Python.
Classes have:
6
Methods (i.e. procedural attributes): Define how to interact with the instances of a
class
We can create our own classes using data and procedural attributes. It is our playground so we
In addition to the user-defined functions, it is possible to use built-in Python function within
user-defined classes. This is what special (or magic) methods are for.
Special methods allow for using the built-in Python functions to enrich user-defined classes.
Consider the print function which is one of the most commonly used Python function. If you
use it to print an instance of your class, it will print out something like the following:
<__main__.Book object at 0x7f9ed5b1d590>
It displays the name of the class (Book) and the memory location of the object which is not a
proper use of the print function. We can customize its behavior by implementing the __str__
In this article, we will go over 4 special methods that you will be likely to use in your classes.
1. __init__
The __init__ special method is automatically executed when an instance of class is created. It
is also called class constructor. The parameters of the __init__ represent the data attributes of a
class.
self.writer = writer
self.pages = pages
The self refers to the instance itself. The Book class has 3 data attributes that need to be
2. __str__
We use the __str__ special method to implement the built-in print function within our class.
Now the print function will return the title of the name. It accesses the name of the book
through the name attribute. You can customize it in any way you’d like.
print(b)
The title of the book is Moby Dick
3. __len__
The len function returns the length of an object. For strings, it returns the number of
We can customize its behavior by implementing the __len__ special method in our class
If the __len__ is not implemented in the class definition, you will get an error if you try to use
it on an object of your class. It does not have a default behavior like the print function.
def __len__(self):
return int(self.pages)len(b)
378
Please note that each time you add a new function to your class, you need to recreate the
4. __eq__
The __eq__ special method allows for comparing two instances of a class. If it is defined in
our class, we can check if an instance is equal to another instance. The equality condition is
In our case, we can declare two books being equal if the names and writers of the book are the
The “==” operator will return True if both names and writes are the same for two instances.