0% found this document useful (0 votes)
16 views42 pages

Complete Python Notes

This document provides thorough Python programming notes, covering fundamentals, data structures, object-oriented programming, file handling, modules, and advanced topics like web development and data analysis. Perfect for beginners and professionals aiming to master Python. Great for both learning and quick reference.

Uploaded by

Khushi Pal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
16 views42 pages

Complete Python Notes

This document provides thorough Python programming notes, covering fundamentals, data structures, object-oriented programming, file handling, modules, and advanced topics like web development and data analysis. Perfect for beginners and professionals aiming to master Python. Great for both learning and quick reference.

Uploaded by

Khushi Pal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 42

PYTHON PROGRAMMING

UNIT-1

INTRODUCTION AND FEATURES OF PYTHON


Python is a programming language that combines the
features of C and Java. It offers elegant style of developing
programs like C. When the programmers want to go for
object orientation, Python offers classes and objects like
Java. Python was developed by Guido Van Rossum in the
year 1991 at the Center for Mathematics and Computer
Science managed by the Dutch Government. Van Rossum
was working on a project to develop system utilities in C
where he had to interact with the Bourne shell available
in UNIX. He felt the necessity of developing a language
that would fill the gap between C and the shell. This has
led to the creation of Python. Van Rossum picked the
name Python for the new language from the TV show,
Monty Python’s Flying Circus. Python’s first working
version was ready by early 1990 and Van Rossum released
it for the public on February 20, 1991.
Features of Python
There are various reasons why Python is gaining good
popularity in the programming community. The
following are some of the important features of Python:
(1) Simple: Python is a simple programming language.
When we read a Python program, we feel like reading
English sentences. It means more clarity and less stress
on understanding the syntax of the language. Hence,

- 1
developing and understanding programs will become
easy.
(2) Easy to learn: Python uses very few keywords. Its
programs use very simple structure. So, developing
programs in Python become easy. Also, Python resembles
C language. Most of the language constructs in C are also
available in Python. Hence, migrating from C to Python is
easy for programmers.
(3) Open source: There is no need to pay for Python
software. Python can be freely downloaded from
www.python.org website. Its source code can be read,
modified and can be used in programs as desired by the
programmers.
(4) High level language: Programming languages are
of two types: low level and high level. A low-level
language uses machine code instructions to develop
programs. These instructions directly interact with the
CPU. Machine language and assembly language are called
low level languages. High level languages use English
words to develop programs. These are easy to learn and
use. Like COBOL, PHP or Java, Python also uses English
words in its programs and hence it is called high level
programming language.
(5) Dynamically typed: In Python, we need not declare
anything. An assignment statement binds a name to an
object, and the object can be of any type. If a name is
assigned to an object of one type, it may later be assigned
to an object of a different type. This is the meaning of the
saying that Python is a dynamically typed language.
Languages like C and Java are statically typed. In these
- 2
languages, the variable names and datatypes should be
mentioned properly. Attempting to assign an object of the
wrong type to a variable name triggers error or exception.
(6) Platform independent: When a Python program
is compiled using a Python compiler, it generates byte
code. Python’s byte code represents a fixed set of
instructions that run on all operating systems and
hardware. Using a Python Virtual Machine (PVM),
anybody can run these byte code instructions on any
computer system. Hence, Python programs are not
dependent on any specific operating system. We can use
Python on almost all operating systems like UNIX, Linux,
Windows, Macintosh, Solaris, OS/2, Amiga, AROS,
AS/400, etc. This makes Python an ideal programming
language for any network or Internet.
(7) Portable: When a program yields the same result on
any computer in the world, then it is called a portable
program. Python programs will give the same result since
they are platform independent. Once a Python program
is written, it can run on any computer system using PVM.
However, Python also contains some system dependent
modules (or code), which are specific to operating system.
Programmers should be careful about such code while
developing the software if they want it to be completely
portable.
(8) Procedure and object oriented: Python is a
procedure oriented as well as an object-oriented
programming language. In procedure-oriented
programming languages (e.g. C and Pascal), the
programs are built using functions and procedures. But

- 3
in object-oriented languages (e.g. C++ and Java), the
programs use classes and objects.
Flavors of Python
Flavors of Python refer to the different types of Python
compilers. These flavors are useful to integrate various
programming languages into Python. The following are
some of them:
(1) CPython: This is the standard Python compiler
implemented in C language. In this, any Python program
is internally converted into byte code using C language
functions. This byte code is run on the interpreter
available in Python Virtual Machine (PVM) created in C
language. The advantage is that it is possible to execute C
and C++ functions and programs in CPython.
(2) Jython: This is earlier known as JPython. This is the
implementation of Python programming language which
is designed to run on Java platform. Jython compiler first
compiles the Python program into Java byte code. This
byte code is executed by Java Virtual Machine (JVM) to
produce the output. Jython contains libraries which are
useful for both Python and Java programmers.
(3) IronPython: This is another implementation of
Python language for .NET framework. This is written in
C# (C Sharp) language. The Python program when
compiled gives an intermediate language (IL) which runs
on Common Language Runtime (CLR) to produce the
output. This flavor of Python gives flexibility of using both
the .NET and Python libraries.

- 4
(4) PyPy: This is Python implementation using Python
language. Actually, PyPy is written in a language called
RPython which was created in Python language. RPython
is suitable for creating language interpreters. PyPy
programs run very fast since there is a JIT (Just in Time)
compiler added to the PVM. PyPy can be downloaded by
visiting the page: http://pypy.org/download.html. Since
the original Python uses only an interpreter in the Python
Virtual Machine (PVM), the Python programs run slowly.
To improve the speed of execution, a compiler called JIT
(Just in Time) is introduced into the PVM of PyPy. Hence,
PyPy programs run faster than those of Python.
(5) RubyPython: This is a bridge between the Ruby and
Python interpreters. It encloses a Python interpreter
inside Ruby applications.
(6) StacklessPython: Small tasks which should run
individually are called tasklets. Tasklets run
independently on CPU and can communicate with others
via channels. A channel is a manager that takes care of
scheduling the tasklets, controlling them and suspending
them. A thread is a process which runs hundreds of such
tasklets. We can create threads and tasklets in
StacklessPython which is reimplementation of original
Python language.
(7) Pythonxy: This is pronounced as Python xy and
written as Python(X,Y). This is the Python
implementation that we get after adding scientific and
engineering related packages.
(8) AnacondaPython: When Python is redeveloped for
handling large-scale data processing, predictive analytics
- 5
and scientific computing, it is called Anaconda Python.
This implementation mainly focuses on large scale of
data.
Python Virtual Machine (PVM)
We know that computers understand only machine code
that comprises 1s and 0s. Since computer understands
only machine code, it is imperative that we should
convert any program into machine code before it is
submitted to the computer for execution. For this
purpose, we should take the help of a compiler. A
compiler normally converts the program source code into
machine code. A Python compiler does the same task but
in a slightly different manner. It converts the program
source code into another code, called byte code. Each
Python program statement is converted into a group of
byte code instructions. Then what is byte code? Byte code
represents the fixed set of instructions created by Python
developers representing all types of operations. The size
of each byte code instruction is 1 byte (or 8 bits) and
hence these are called byte code instructions. Python
organization says that there may be newer instructions
added to the existing byte code instructions from time to
time. The Python Virtual Machine The role of Python
Virtual Machine (PVM) is to convert the byte code
instructions into machine code so that the computer can
execute those machine code instructions and display the
final output. To carry out this conversion, PVM is
equipped with an interpreter. The interpreter converts
the byte code into machine code and sends that machine
code to the computer processor for execution. Since

- 6
interpreter is playing the main role, often the Python
Virtual Machine is also called an interpreter.

Memory Management in Python


In C or C++, the programmer should allocate and
deallocate (or free) memory dynamically, during runtime.
For example, to allocate memory, the programmer may
use malloc () function and to deallocate the memory, he
may use the free () function. But in Python, memory
allocation and deallocation are done during runtime
automatically. The programmer need not allocate
memory while creating objects or deallocate memory
when deleting the objects. Python’s PVM will take care of
such issues. Everything is considered as an object in
Python. For example, strings are objects. Lists are objects.
Functions are objects. Even modules are also objects. For
every object, memory should be allocated. Memory
manager inside the PVM allocates memory required for
objects created in a Python program. All these objects are
stored on a separate memory called heap. Heap is the
memory which is allocated during runtime. The size of
the heap memory depends on the Random-Access
Memory (RAM) of our computer and it can increase or
decrease its size depending on the requirement of the
program. We know that the actual memory (RAM) for
any program is allocated by the underlying Operating
system. On the top of the Operating system, a raw
memory allocator oversees whether enough memory is
available to it for storing objects. On the top of the raw
- 7
memory allocator, there are several object-specific
allocators operate on the same heap. These memory
allocators will implement different types of memory
management policies depending on the type of the
objects. For example, an integer number should be stored
in memory in one way and a string should be stored in a
different way. Similarly, when we deal with tuples and
dictionaries, they should be stored differently.
Garbage Collection in Python
A module represents Python code that performs a
specific task. Garbage collector is a module in Python that
is useful to delete objects from memory which are not
used in the program. The module that represents the
garbage collector is named as gc. Garbage collector in the
simplest way to maintain a count for each object
regarding how many times that object is referenced (or
used). When an object is referenced twice, its reference
count will be 2. When an object has some count, it is being
used in the program and hence garbage collector will not
remove it from memory. When an object is found with a
reference count 0, garbage collector will understand that
the object is not used by the program and hence it can be
deleted from memory. Hence, the memory allocated for
that object is deallocated or freed. Garbage collector can
detect reference cycles. A reference cycle is a cycle of
references pointing to the first object from last object. For
example, take three objects A, B and C. The object A
refers to the object B whereas the object B holds a
reference to the object C. Now if the object C refers to the
first object A, it will form a reference cycle. Even if the

- 8
objects A, B and C are no longer used in the Python
program, still these objects contain 1 reference to each
one. Since the reference count for each object is 1, the
garbage collector will not remove these objects from
memory. These objects stay in memory even after the
program execution completes. To get around this,
garbage collector uses an algorithm (logic) for detecting
reference cycles and removing objects in the cycle.
Garbage collector classifies the objects into three
generations. The newly created objects are considered as
generation 0 objects. First time, when the garbage
collector examines the objects in memory and does not
remove an object from memory due to the reason that the
object is used by the program, then that object is placed
into next generation, say generation 1. When the garbage
collector intends to delete the objects for the second time
and the object also survives for the second time, then it is
placed into generation 2. Thus, older objects belong to
generation 2. Garbage collector tries to delete younger
objects which are not referenced in the program rather
than the old objects. Garbage collector runs
automatically. Python schedules garbage collector
depending upon a number called threshold. This number
represents the frequency of how many times the garbage
collector removed (or collected) the objects.

Comparisons between C and Python


No. C PYTHON
1. C is procedure-oriented Python is object-
programming language. oriented oriented

- 9
It does not contain the language. It contains
features like classes, features like classes,
objects, inheritance, objects, inheritance,
polymorphism, etc. polymorphism, etc.

2. C programs execute Python programs are


faster slower compared to C.
PyPy flavor or Python
programs run a bit faster
but still slower than C.

3. It is compulsory to Type declaration is not


declare the datatypes of required in Python
variables, arrays etc. in
C.
4. C language type Python type discipline is
discipline is static and dynamic and strong.
weak.

5. Pointers concept is Python does not use


available in C. pointers.

6. C does not have Python handles


exception handling exceptions and hence
facility and hence C Python programs are
programs are weak robust.

7. C has do… while, while Python has while and for


and for loops. loops

8. C has switch statement. Python does not have


switch statement

- 10
9. The variable in for loop The variable in the for-
does not increment loop increments
automatically.

10. The programmer should Memory allocation and


allocate and deallocate deallocation is done
memory using malloc (), automatically by PVM.
calloc (), realloc () or
free () functions
11. C does not contain a Automatic garbage
garbage collector. collector is available in
Python.

12. C supports single and Python supports only


multi-dimensional single dimensional
arrays arrays. To work with
multi-dimensional
arrays, we should use
third party applications
like numpy
13. The array index should Array index can be
be positive integer. positive or negative
integer number.
Negative index
represents locations
from the end of the
array.
14. Checking the location Python performs
outside the allocation of checking outside an
an array is not array for all iterations
supported in C. while looping.

- 11
15. Indentation of Indentation is required
statements is not to represent a block of
necessary in C. statements.

16. A semicolon is used to New line indicates end of


terminate the the statements and
statements in C and semicolon is used as an
comma is used to expression separator.
separate expressions.

17. C supports in-line Python does not support


assignments. in-line assignments.

Comparisons between Java and Python


No. JAVA PYTHON
1. Java is object-oriented Python blends the
programming language. functional programming
Functional with object-oriented
programming features programming features.
are introduced into Java Lambdas are already
8.0 through lambda available in Python.
expressions.

2. Java programs are Python programs are


verbose. It means they concise and compact. A
contain a greater big program can be
number of lines. written using very a
smaller number of lines.

3. It is compulsory to Type declaration is not


declare the datatypes of required in Python.

- 12
variables, arrays etc. in
Java.

4. Java language type Python type discipline is


discipline is static and dynamic and strong.
weak.

5. Java has do… while, Python has while and for


while, for and for each loops.
loop.

6. Java has switch Python does not have


statement. switch statement.

7. The variable in for loop The variable in the for


does not increment loop increments
automatically. But in for automatically.
each loop, it will
increment
automatically.

8. Memory allocation and Memory allocation and


deal location is done deal location is done
automatically by JVM automatically by PVM
(Java Virtual Machine). (Python Virtual
Machine).

9. Java supports single and Python supports only


multi-dimensional single dimensional
arrays. arrays. To work with
multi-dimensional
arrays, we should use

- 13
third party applications
like numpy.

10. The array index should Array index can be


be a positive integer. positive or negative
integer number.
Negative index
represents locations
from the end of the
array.

11. Checking the location Python performs


outside the allocation of checking outside an
an array is not supported array for all iterations
in Java. while looping.

12. Indentation of Indentation is required


statements is not to represent a block of
necessary in Java. statements.

13. A semicolon is used to New line indicates end


terminate the of the statements and
statements and comma semicolon is used as an
is used to separate expression separator.
expressions.

14. In Java, the collection Python collection


objects like Stack, objects like lists and
LinkedList or Vector dictionaries can store
store only objects but objects of any type,
not primitive datatypes including numbers and
like integer numbers. lists.

- 14
Datatypes in Python
A datatype represents the type of data stored into a
variable or memory. The datatypes which are already
available in Python language are called Built-in
datatypes. The datatypes which can be created by the
programmers are called User-defined datatypes.
Built-in datatypes
1. The None Type
In Python, the ‘None’ datatype represents an object that
does not contain any value. In languages like Java, it is
called ‘null’ object. But in Python, it is called ‘None’
object. In a Python program, maximum of only one
‘None’ object is provided. One of the uses of ‘None’ is that
it is used inside a function as a default value of the
arguments. When calling the function, if no value is
passed, then the default value will be taken as ‘None’. If
some value is passed to the function, then that value is
used by the function. In Boolean expressions, ‘None’
datatype represents ‘False’.
2. Numeric Types
The numeric types represent numbers. There are three
sub types: 1.int, 2. float, 3. complex
3. Sequences in Python
Generally, a sequence represents a group of elements or
items. For example, a group of integer numbers will form

- 15
a sequence. There are six types of sequences in Python: 1.
str 2. bytes 3. bytearray 4. list 5. tuple 6. range
4. Sets
A set is an unordered collection of elements much like a
set in Mathematics. The order of elements is not
maintained in the sets. It means the elements may not
appear in the same order as they are entered into the set.
Moreover, a set does not accept duplicate elements. There
are two sub types in sets: 1. set datatype 2. frozenset
datatype
5. Mapping Types
A map represents a group of elements in the form of key
value pairs so that when the key is given, we can retrieve
the value associated with it. The dict datatype is an
example for a map. The ‘dict’ represents a ‘dictionary’ that
contains pairs of elements such that the first element
represents the key and the next one becomes its value.
The key and its value should be separated by a colon (:)
and every pair should be separated by a comma. All the
elements should be enclosed inside curly brackets {}.

Identifiers and Reserved words


An identifier is a name that is given to a variable or
function or class etc. Identifiers can include letters,
numbers, and the underscore character (_). They should
always start with a nonnumeric character. Special
symbols such as? #, $,%, and @ are not allowed in
identifiers. Some examples for identifiers are salary,
name11, gross_income, etc. We should also remember
- 16
that Python is a case sensitive programming language. It
means capital letters and small letters are identified
separately by Python.
Reserved words are the words that are already reserved
for some particular purpose in the Python language. The
names of these reserved words should not be used as
identifiers. The following are the reserved words available
in Python: and, del, from, nonlocal, try , as, elif, global,
not, while, assert, else, if, or, with, break, except, import,
pass, yield, class, exec, in, print, False, continue, finally,
is, raise, True, def, for, lambda, return.

Naming Conventions in Python


Python developers made some suggestions to the
programmers regarding how to write names in the
programs. The rules related to writing names of packages,
modules, classes, variables, etc. are called naming
conventions. The following naming conventions should
be followed:
1. Packages: Package names should be written in all
lower-case letters. When multiple words are used for a
name, we should separate them using an underscore (_).
2. Modules: Modules names should be written in all
lower-case letters. When multiple words are used for a
name, we should separate them using an underscore (_).
3. Classes: Each word of a class name should start with
a capital letter. This rule is applicable for the classes
created by us. Python’s built-in class names use all

- 17
lowercase words. When a class represents exception, then
its name should end with a word ‘Error’.
4. Global variables or Module-level variables:
Global variables names should be all lower-case letters.
When multiple words are used for a name, we should
separate them using an underscore (_).
5. Instance variables: Instance variables names should
be all lower-case letters. When multiple words are used
for a name, we should separate them using an underscore
(_). Non-public instance variable name should begin with
an underscore.
6. Functions: Function names should be all lower-case
letters. When multiple words are used for a name, we
should separate them using an underscore (_).
7. Methods: Method names should be all lower-case
letters. When multiple words are used for a name, we
should separate them using an underscore (_).
8. Method arguments: In case of instance methods,
their first argument name should be ‘self’. In case of class
methods, their first argument name should be ‘cls’.
9. Constants: Constants names should be written in all
capital letters. If a constant has several words, then each
word should be separated by an underscore (_).
10. Non accessible entities: Some variables, functions
and methods are not accessible outside and they should
be used as they are in the program. Such entities names
are written with two double quotes before and two double
quotes after. For example, __init__(self) is a function
used in a class to initialize variables.
- 18
Membership Operators
The membership operators are useful to test for
membership in a sequence such as strings, lists, tuples or
dictionaries. For example, if an element is found in the
sequence or not can be asserted using these operators.
There are two membership operators as shown here:
► in
► not in
The in Operator: - This operator returns True if an
element is found in the specified sequence. If the element
is not found in the sequence, then it returns False.
The not in Operator: - This works in reverse manner
for ‘in’ operator. This operator returns True if an element
is not found in the sequence. If the element is found, then
it returns False. Let’s take a group of strings in a list. We
want to display the members of the list using a for loop
where the ‘in’ operator is used. The list of names is given
below:
names = ["Rani", "Yamini", "Sushmita", "Veena"]
Here the list name is ‘names’. It contains a group of
names. Suppose, we want to retrieve all the names from
this list.

Identity Operators
These operators compare the memory locations of two
objects. Hence, it is possible to know whether the two
objects are same or not. The memory location of an object

- 19
can be seen using the id () function. This function returns
an integer number, called the identity number that
internally represents the memory location of the object.
There are two identity operators:
► is
► is not
The is Operator: - The ‘is’ operator is useful to compare
whether two objects are same or not. It will internally
compare the identity number of the objects. If the identity
numbers of the objects are same, it will return True;
otherwise, it returns False.
The is not Operator: - This is not operator returns
True, if the identity numbers of two objects being
compared are not same. If they are same, then it will
return False. The ‘is’ and ‘is not’ operators do not
compare the values of the objects. They compare the
identity numbers or memory locations of the objects. If
we want to compare the value of the objects, we should
use equality operator (==).

    

- 20
PYTHON PROGRAMMING
UNIT-2
➢ ARRAYS IN PYTHON
An array is an object that stores a group of elements (or values) of
same datatype. The main advantage of any array is to store and
process a group of elements easily. There are two points we should
remember in case of arrays in Python.
► Arrays can store only one type of data. It means, we can store
only integer type elements or only float type elements into an
array. But we cannot store one integer, one float and one-
character type element into the same array.
► Arrays can increase or decrease their size dynamically. It means,
we need not declare the size of the array. When the elements are
added, it will increase its size and when the elements are
removed, it will automatically decrease its size in memory.
Advantages of Arrays:
The following are some advantages of arrays:
► Arrays are similar to lists. The main difference is that arrays can
store only one type of elements; whereas, lists can store different
types of elements. When dealing with a huge number of
elements, arrays use less memory than lists and they offer faster
execution than lists.
► The size of the array is not fixed in Python. Hence, we need not
specify how many elements we are going to store into an array in
the beginning.
► Arrays can grow or shrink in memory dynamically (during
runtime).
► Arrays are useful to handle a collection of elements like a group
of numbers or characters.
► Methods that are useful to process the elements of any array are
available in ‘array’ module.
Creating an Array:
We have already discussed that arrays can hold data of same
type. The type should be specified by using a type code at the time
of creating the array object as: arrayname = array (type code,
[elements])
The type code ‘i’, represents integer type array where we can store
integer numbers. If the type code is ‘f’ then it represents float type
array where we can store numbers with decimal point. The
important type codes are given bellow.
TYPE CODE C TYPE
‘b’ Signed integer
‘B’ Unsigned integer
‘i’ Signed integer
‘I’ Unsigned integer
‘L’ Unsigned integer
‘f’ Floating point
‘d’ Floating point
‘u’ Unicode character

➢ FUNCTIONS
function is similar to a program that consists of a group of
statements that are intended to perform a specific task. The main
purpose of a function is to perform a specific task or work. Thus,
when there are several tasks to be performed, the programmer will
write several functions. There are several ‘built-in’ functions in
Python to perform various tasks. For example, to display output,
Python has print () function. Similarly, to calculate square root
value, there is sqrt () function and to calculate power value, there is
power () function. Similar to these functions, a programmer can
also create his own functions which are called ‘user-defined’
functions. The following are the advantages of functions:
► Functions are important in programming because they are used
to process data, make calculations or perform any task which is
required in the software development.
► Once a function is written, it can be reused as and when
required. So, functions are also called reusable code. Because of
this reusability, the programmer can avoid code redundancy. It
means it is possible to avoid writing the same code again and again.
► Functions provide modularity for programming. A module
represents a part of the program. Usually, a programmer divides
the main task into smaller sub tasks called modules. To represent
each module, the programmer will develop a separate function.
Then these functions are called from a main program to accomplish
the complete task. Modular programming makes programming
easy.
► Code maintenance will become easy because of functions. When
a new feature has to be added to the existing software, a new
function can be written and integrated into the software. Similarly,
when a particular feature is no more needed by the user, the
corresponding function can be deleted or put into comments.
► When there is an error in the software, the corresponding
function can be modified without disturbing the other functions in
the software. Thus, code debugging will become easy.
► The use of functions in a program will reduce the length of the
program.
Difference between a Function and a Method
We discussed that a function contains a group of statements and
performs a specific task. A function can be written individually in a
Python program. A function is called using its name. When a
function is written inside a class, it becomes a ‘method’. A method
is called using one of the following ways:
objectname.methodname()
Classname.methodname()
So, please remember that a function and a method are same except
their placement and the way they are called. In python, we can
create our own function. Creating a function means defining a
function or writing a function. Once a function is defined, it can be
used by calling the function.

Positional Arguments
These are the arguments passed to a function in correct positional
order. Here, the number of arguments and their positions in the
function definition should match exactly with the number and
position of the argument in the function call. For example, take a
function definition with two arguments as: def attach (s1, s2)
This function expects two strings that too in that order only. Let’s
assume that this function attaches the two strings as s1+s2. So,
while calling this function, we are supposed to pass only two strings
as: attach (‘New’, ‘York’) The preceding statement displays the
following output: NewYork Suppose, we passed ‘York’ first and
then ‘New’, then the result will be: ‘YorkNew’. Also, if we try to pass
more than or less than 2 strings, there will be an error.
Keyword Arguments
Keyword arguments are arguments that identify the parameters by
their names. For example, the definition of a function that displays
grocery item and its price can be written as: def grocery (item,
price): At the time of calling this function, we have to pass two
values and we can mention which value is for what. For example,
grocery (item='Sugar', price=50.75)
Here, we are mentioning a keyword ‘item’ and its value and then
another keyword ‘price’ and its value. Please observe these
keywords are nothing but the parameter names which receive these
values. We can change the order of the arguments as: grocery
(price=88.00, item='Oil’) In this way, even though we change
the order of the arguments, there will not be any problem as the
parameter names will guide where to store that value.
Default Arguments
We can mention some default value for the function parameters in
the definition. Let’s take the definition of grocery () function as:
def grocery (item, price=40.00):
Here, the first argument is ‘item’ whose default value is not
mentioned. But the second argument is ‘price’ and its default value
is mentioned to be 40.00. At the time of calling this function, if we
do not pass ‘price’ value, then the default value of 40.00 is taken. If
we mention the ‘price’ value, then that mentioned value is utilized.
So, a default argument is an argument that assumes a default value
if a value is not provided in the function call for that argument.
Variable Length Arguments:
Sometimes, the programmer does not know how many values a
function may receive. In that case, the programmer cannot decide
how many arguments to be given in the function definition. For
example, if the programmer is writing a function to add two
numbers, he can write: add (a, b) But, the user who is using this
function may want to use this function to find sum of three
numbers. In that case, there is a chance that the user may provide
3 arguments to this function as: add (10, 15, 20) Then the add ()
function will fail and error will be displayed. If the programmer
wants to develop a function that can accept ‘n’ arguments, that is
also possible in Python. For this purpose, a variable length
argument is used in the function definition. A variable length
argument is an argument that can accept any number of values. The
variable length argument is written with a ‘ * ’ symbol before it in
the function definition as: def add(farg, *args): Here, ‘farg’ is
the formal argument and ‘*args’ represents variable length
argument. We can pass 1 or more values to this ‘*args’ and it will
store them all in a tuple. A tuple is like a list where a group of
elements can be stored.

Anonymous Functions or Lambdas


A function without a name is called ‘anonymous function’. So far,
the functions we wrote were defined using the keyword ‘def’. But
anonymous functions are not defined using ‘def’. They are defined
using the keyword lambdaand hence they are also called ‘Lambda
functions. Let’s take a normal function that returns square of a
given value.
def square(x):
return x*x
The same function can be written as anonymous function as:
lambda x: x*x
Observe the keyword ‘lambda’. This represents that an anonymous
function is being created. After that, we have written an argument
of the function, i.e. ‘x’. Then colon (:) represents the beginning of
the function that contains an expression x * x. Please observe that
we did not use any name for the function here. So, the format of
lambda functions is:
lambda argument_list: expression
Normally, if a function returns some value, we assign that value to
a variable as:
y = square(5) But, lambda functions return a function and hence
they should be assigned to a function as:
f = lambda x: x*x Here, ‘f’ is the function name to which the
lambda expression is assigned. Now, if we call the function f() as:
value = f(5) Now, ‘value’ contains the square value of 5, i.e. 25.

➢ Function Decorators
A decorator is a function that accepts a function as parameter and
returns a function. A decorator takes the result of a function,
modifies the result and returns it. Thus, decorators are useful to
perform some additional processing required by a function.
Decorators concept is a bit confusing but not difficult to
understand. The following steps are generally involved in creation
of decorators:
1. We should define a decorator function with another function
name as parameter. As an example, let’s define a decorator function
decor() with ‘fun’ as parameter.
def decor(fun):
2. We should define a function inside the decorator function. This
function actually modifies or decorates the value of the function
passed to the decorator function. As an example, let’s write inner()
function in the decor() function. Our assumption is that this inner()
function increases the value returned by the function by 2.
def decor(fun):
def inner():
value = fun() #access value returned by fun()
return value+2 #increase the value by 2
return inner #return the inner function
In the previous code, observe the body of the inner() function. We
have accessed the ‘value’ returned by the function ‘fun’, and added
2 to it and then returned it.
3. Return the inner function that has processed or decorated the
value. In our example, in the last statement, we were returning
inner() function using return statement. With this, the decorator
is completed.

➢ List
A list is similar to an array that consists of a group of elements or
items. Just like an array, a list can store elements. But there is one
major difference between an array and a list. An array can store
only one type of elements whereas a list can store different types of
elements. Hence lists are more versatile and useful than an array.
Perhaps lists are the most used datatype in Python programs. In
our daily life, we do not have elements of the same type. For
example, we take marks of a student in 5 subjects: 50, 55, 62, 74,
66 These are all belonging to the same type, i.e. integer type.
Hence, we can represent such elements as an array. But we need
other information about the student, like his roll number, name,
gender along with his marks. So, the information looks like this:
10, Venu gopal, M, 50, 55, 62, 74, 66
Here, we have different types of data. Roll number (10) is an
integer. Name (‘Venu gopal’) is a string. Gender (‘M’) is a character
and the marks (50, 55, 62, 74, 66) are again integers. In daily life,
generally we have this type of information that is to be stored and
processed. This type of information cannot be stored in an array
because an array can store only one type of elements. In this case,
we need to go for list datatype. A list can store different types of
elements. To store the student’s information discussed so far, we
can create a list as:
student = [10, 'Venu gopal', 'M', 50, 55, 62, 74, 66] Please
observe that the elements of the ‘student’ list are stored in square
braces []. We can create an empty list without any elements by
simply writing empty square braces as:
e_lst = [] #this an empty list
Thus, we can create a list by embedding the elements inside a pair
of square braces []. The elements in the list should be separated by
a comma (,). To view the elements of a list as a whole, we can simply
pass the list name to the print() function as: print(student) The list
appears as given below: [10, 'Venu gopal', 'M', 50, 55, 62, 74,
66]
Indexing and slicing operations are commonly done on lists.
Indexing represents accessing elements by their position numbers
in the list. The position numbers start from 0 onwards and are
written inside square braces as: student[0], student[1], etc... It
means, student[0] represents 0th element, student[1] represents
1st element and so forth. For example, to print the student’s name,
we can write: print(student[1]) The name of student appears as
given below: Venu gopal
Slicing represents extracting a piece of the list by mentioning
starting and ending position numbers. The general format of
slicing is: [start: stop: stepsize]. By default, ‘start’ will be 0, ‘stop’
will be the last element and ‘stepsize’ will be 1. For example,
student[0:3:1] represents a piece of the list containing 0th to 2nd
elements. print(student[0:3:1]) The elements are given below:
[10, 'Venu gopal', 'M'] We can also write the above statement
as: print(student[:3:]) The same elements appears as shown
following: [10, 'Venu gopal', 'M'] Here, since we did not mention
the starting element position, it will start at 0 and stepsize will be
taken as 1. Suppose, we do not mention anything in slicing, then
the total list will be extracted as: print(student[::])
It displays the output as: [10, 'Venu gopal', 'M', 50, 55, 62, 74,
66] Apart from indexing and slicing, the 5 basic operations:
finding length, concatenation, repetition, membership and
iteration operations can be performed on lists and other sequences
like strings, tuples or dictionaries.

Methods to Process Lists the List methods and their


Description
sum()=Returns sum of all elements in the list.
index()=Returns the first occurrence of x in the list
append() = Appends x at the end of the list
insert() = Inserts x in to the list in the position specified by i
copy() =Copies all the list elements into a new list and returns it
extend()= Appends list1 to list
count() =Returns number of occurrences of x in the list
remove() = Removes x from the list
pop()=Removes the ending element from the list
sort()=Sorts the elements of the list into ascending order
reverse()=Reverses the sequence of elements in the list
clear()=Deletes all elements from the list

➢ Operations on Dictionaries
To access the elements of a dictionary, we should not use indexing
or slicing. For example, dict[0] or dict[1:3] etc. expressions will give
error. To access the value associated with a key, we can mention
the key name inside the square braces, as: dict[‘Name’]. This will
return the value associated with ‘Name’. This is nothing but
‘Chandra’. If we want to know how many key-value pairs are there
in a dictionary, we can use the len() function, as shown in the
following statements:
dict = {'Name': 'Chandra', 'Id': 200, 'Salary':
9080.50}
n = len(dict)
print('No. of key-value pairs =', n)
The above code will display: No. of key-value pairs = 3. Please
remember each key-value pair is counted as one element. We can
modify the existing value of a key by assigning a new value, as
shown in the following statement:
dict['Salary'] = 10500.00
Here, the ‘Salary’ value is modified as ‘10500.00’. The previous
value of ‘Salary’, i.e. 9080.50 is replaced by the new value, i.e.
10500.00. We can also insert a new key-value pair into an existing
dictionary. This is done by mentioning the key and assigning a
value to it, as shown in the following statement: dict['Dept'] =
'Finance'
Here, we are giving a new key ‘Dept’ and its value ‘Finance’. This
pair is stored into the dictionary ‘dict’. Now, if we display the
dictionary using print(dict), it will display:
{'Name': 'Chandra', 'Dept': 'Finance', 'Id': 200, 'Salary':
10500.0}
Observe the new pair ‘Dept’: ’Finance’ is added to the dictionary.
Also, observe that this pair is not added at the end of existing pairs.
It may be added at any place in the dictionary. Suppose, we want
to delete a key-value pair from the dictionary, we can use del
statement as: del dict['Id']
This will delete the key ‘Id’ and its corresponding value from the
dictionary. Now, the dictionary looks like this:
{'Name': 'Chandra', 'Dept': 'Finance', 'Salary': 10500.0}
To test whether a ‘key’ is available in a dictionary or not, we can use
‘in’ and ‘not in’ operators. These operators return either True or
False. Consider the following statement: 'Dept' in dict #check
if ‘Dept is a key in dict
The preceding statement will give: True

➢ Converting Lists into Dictionary


When we have two lists, it is possible to convert them into a
dictionary. For example, we have two lists containing names of
countries and names of their capital cities.
countries = ["USA", "India", "Germany", "France"]
cities = ['Washington', 'New Delhi', 'Berlin', 'Paris']
We want to create a dictionary out of these two lists by taking the
elements of ‘countries’ list as keys and of ‘cities’ list as values. The
dictionary should look something like this:
d = {"USA": 'Washington', "India": 'New Delhi',
"Germany": 'Berlin', "France": 'Paris'}
There are two steps involved to convert the lists into a dictionary.
The first step is to create a ‘zip’ class object by passing the two lists
to zip () function as: z = zip(countries, cities) The zip() function
is useful to convert the sequences into a zip class object. There may
be 1 or more sequences that can be passed to zip () function. Of
course, we passed only 2 lists to zip() function in the above
statement. The resultant zip object is ‘z’. The second step is to
convert the zip object into a dictionary by using dict() function. d
= dict(z)
Here, the 0th element of z is taken as ‘key’ and 1st element is
converted into its ‘value’. Similarly, 2nd element becomes ‘key’ and
3rd one becomes its ‘value’, etc. They are stored into the dictionary
‘d’. If we display ‘d’, we can see the following dictionary:
{'India': 'New Delhi', 'USA': 'Washington', 'Germany':
'Berlin', 'France': 'Paris'}

    
PYTHON PROGRAMMING
UNIT-3

CLASS
A class is created with the keyword class and then writing the
Classname. After the Classname, ‘object’ is written inside the
Classname. This ‘object’ represents the base class name from where
all classes in Python are derived. Even our own classes are also
derived from ‘object’ class. Hence, we should mention ‘object’ in the
parentheses. Please note that writing ‘object’ is not compulsory
since it is implied.
The docstring is a string which is written using triple double quotes
or triple single quotes that gives the complete description about the
class and its usage. The docstring is used to create documentation
file and hence it is optional. ‘attributes’ are nothing but variables
that contains data. __init__(self) is a special method to initialize
the variables. method1() and method2(), etc. are methods that are
intended to process variables.
If we take ‘Student’ class, we can write code in the class that
specifies the attributes and actions performed by any student. For
example, a student has attributes like name, age, marks, etc. These
attributes should be written inside the Student class as variables.
Similarly, a student can perform actions like talking, writing,
reading, etc. These actions should be represented by methods in the
Student class. So, the class Student contains these attributes and
actions, as shown here:
class Student: #another way is: class Student(object):
#the below block defines attributes
def __init__(self): self.name = ‘Vishnu’
self.age = 20
self.marks = 900
#the below block defines a method
def talk(self):
print(‘Hi, I am ‘, self.name)
print(‘My age is’, self.age)
print(‘My marks are’, self.marks)

Observe that the keyword class is used to declare a class. After this,
we should write the class name. So, ‘Student’ is our class name.
Generally, a class name should start with a capital letter, hence ‘S’
is capital in ‘Student’. In the class, we write attributes and methods.
Since in Python, we cannot declare variables, we have written the
variables inside a special method, i.e. __init__(). This method is
useful to initialize the variables. Hence, the name ‘init’. The method
name has two underscores before and after. This indicates that this
method is internally defined, and we cannot call this method
explicitly. Observe the parameter ‘self’ written after the method
name in the parentheses. ‘self’ is a variable that refers to current
class instance. When we create an instance for the Student class, a
separate memory block is allocated on the heap and that memory
location is by default stored in ‘self’. The instance contains the
variables ‘name’, ‘age’, ‘marks’ which are called instance variables.
To refer to instance variables, we can use the dot operator notation
along with self as: ‘self.name’, ‘self.age’ and ‘self.marks’.

CONSTRUCTOR
A constructor is a special method that is used to initialize the
instance variables of a class. In the constructor, we create the
instance variables and initialize them with some starting values.
The first parameter of the constructor will be ‘self’ variable that
contains the memory address of the instance. For example,
def __init__(self):
self.name = ‘Vishnu’
self.marks = 900

Here, the constructor has only one parameter, i.e. ‘self’. Using
‘self.name’ and ‘self.marks’, we can access the instance variables of
the class. A constructor is called at the time of creating an instance.
So, the above constructor will be called when we create an instance
as: s1 = Student()
Here, ‘s1’ is the name of the instance. Observe the empty
parentheses after the class name ‘Student’. These empty
parentheses represent that we are not passing any values to the
constructor. Suppose, we want to pass some values to the
constructor, then we have to pass them in the parentheses after the
class name. Let’s take another example. We can write a constructor
with some parameters in addition to ‘self’ as:
def __init__(self, n = ‘’, m=0):
self.name = n
self.marks = m
Here, the formal arguments are ‘n’ and ‘m’ whose default values are
given as ‘’ (None) and 0 (zero). Hence, if we do not pass any values
to constructor at the time of creating an instance, the default values
of these formal arguments are stored into name and marks
variables. For example, s1 = Student() Since we are not passing
any values to the instance, None and zero are stored into name and
marks. Suppose, we create an instance as: s1 =
Student(‘Lakshmi Roy’, 880)
In this case, we are passing two actual arguments: ‘Lakshmi Roy’
and 880 to the student instance. Hence these values are sent to the
arguments ‘n’ and ‘m’ and from there stored into name and marks
variables.
Types of Methods
By this time, we got some knowledge about the methods written in
a class. The purpose of a method is to process the variables
provided in the class or in the method. We already know that the
variables declared in the class are called class variables (or static
variables) and the variables declared in the constructor are called
instance variables. We can classify the methods in the following 3
types:

1. Instance methods
2. Class methods
3. Static methods

1. Instance Methods: - Instance methods are the methods which


act upon the instance variables of the class. Instance methods are
bound to instances (or objects) and hence called as:
instancename.method(). Since instance variables are available in
the instance, instance methods need to know the memory address
of the instance. This is provided through ‘self’ variable by default as
first parameter for the instance method. While calling the instance
methods, we need not pass any value to the ‘self’ variable.
2. Class Methods: - These methods act on class level. Class
methods are the methods which act on the class variables or static
variables. These methods are written using @classmethod
decorator above them. By default, the first parameter for class
methods is ‘cls’ which refers to the class itself. For example, ‘cls.var’
is the format to refer to the class variable. These methods are
generally called using the classname.method(). The processing
which is commonly needed by all the instances of the class is
handled by the class methods.
3. Static Methods: - We need static methods when the
processing is at the class level but we need not involve the class or
instances. Static methods are used when some processing is related
to the class but does not need the class or its instances to perform
any work. For example, setting environmental variables, counting
the number of instances of the class or changing an attribute in
another class, etc. are the tasks related to a class. Such tasks are
handled by static methods. Also, static methods can be used to
accept some values, process them and return the result. In this case
the involvement of neither the class nor the objects is needed. Static
methods are written with a decorator @staticmethod above them.
Static methods are called in the form of classname.method().

INHERITANCE
If you have created any class and then if you create any other class
based on the previous class than it is called inheritance. if we have
created Student class from the Teacher class. Here, the original
class, i.e. Teacher class is called base class or super class and the
newly created class, i.e. the Student class is called the sub class or
derived class. Deriving new classes from the existing classes such
that the new classes inherit all the members of the existing classes,
is called inheritance. The syntax for inheritance is:
class Subclass(Baseclass):
The next question is why the base class members are automatically
available to sub class? When an object to Student class is created,
it contains a copy of Teacher class within it. This means there is a
relation between the Teacher class and Student class objects. This
is the reason Teacher class members are available to Student class.
Note that we do not create Teacher class object, but still a copy of it
is available to Student class object. In inheritance, we always create
only the sub class object. Generally, we do not create super class
object. The reason is clear. Since all the members of the super class
are available to sub class, when we create an object, we can access
the members of both the super and sub classes. But if we create an
object to super class, we can access only the super class members
and not the sub class members.
Overriding Super Class Constructors and Methods: - When
the programmer writes a constructor in the sub class, the super
class constructor is not available to the sub class. In this case, only
the sub class constructor is accessible from the sub class object.
That means the sub class constructor is replacing the super class
constructor. This is called constructor overriding. Similarly, in the
sub class, if we write a method with exactly same name as that of
super class method, it will override the super class method.
The super () Method: - super() is a built-in method which is
useful to call the super class constructor or methods from the sub
class. Any constructor written in the super class is not available to
the sub class if the sub class has a constructor. Then how can we
initialize the super class instance variables and use them in the sub
class? This is done by calling the super class constructor using the
super() method from inside the sub class constructor. super() is a
built-in method in Python that contains the history of super class
methods. Hence, we can use super() to refer to super class
constructor and methods from a sub class.
Method Resolution Order (MRO): In the multiple inheritance
scenario, any specified attribute or method is searched first in the
current class. If not found, the search continues into parent classes
in depth-first, left to right fashion without searching the same class
twice. Searching in this way is called Method Resolution Order
(MRO). There are three principles followed by MRO.
1. The first principle is to search for the sub class before going for
its base classes. Thus, if class B is inherited from A, it will search B
first and then goes to A.
2. The second principle is that when a class is inherited from several
classes, it searches in the order from left to right in the base classes.
For example, if class C is inherited from A and B as class C(A,B),
then first it will search in A and then in B.
3. The third principle is that it will not visit any class more than
once. That means a class in the inheritance hierarchy is traversed
only once exactly. Understanding MRO gives us clear idea
regarding which classes are executed and in which sequence. We
can easily estimate the output when several base classes are
involved. To know the MRO, we can use mro() method as:
Classname.mro() This returns the sequence of execution of the
classes, starting from the class with which the method is called.

POLYMORPHISM
Polymorphism is a word that came from two Greek words, poly
means many and morphos means forms. If something exhibits
various forms, it is called polymorphism. Let’s take a simple
example in our daily life. Assume that we have wheat flour. Using
this wheat flour, we can make burgers, roties, or loaves of bread. It
means same wheat flour is taking different edible forms and hence
we can say wheat flour is exhibiting polymorphism.
In programming, a variable, object or a method will also exhibit the
same nature as that of the wheat flour. A variable may store
different types of data, an object may exhibit different behaviors in
different contexts or a method may perform various tasks in
Python. This type of behavior is called polymorphism. So, how can
we define polymorphism? If a variable, object or method exhibits
different behavior in different contexts, it is called polymorphism.
Python has built-in polymorphism. The following topics are
examples for polymorphism in Python:
► Duck typing philosophy of Python
► Operator overloading
► Method overloading
► Method overriding
1. Duck Typing Philosophy of Python: - We know that in
Python, the data type of the variables is not explicitly declared. This
does not mean that Python variables do not have a type. Every
variable or object in Python has a type and the type is implicitly
assigned depending on the purpose for which the variable is used.
Python variables are names or tags that point to memory locations
where data is stored. They are not worried about which data we are
going to store. So, if ‘x’ is a variable, we can make it refer to an
integer or a string.
If the method is defined on the object, then it can be called. Thus,
when we passed Duck object to call_talk(), it has called the talk()
method of Duck type (i.e. Duck class). When we passed Human
object to call_talk(), it has called talk() method of Human type.
2. Operator Overloading: - We know that an operator is a
symbol that performs some action. For example, ‘+’ is an operator
that performs addition operation when used on numbers. When an
operator can perform different actions, it is said to exhibit
polymorphism.
The ‘+’ operator is first adding two integer numbers. Then the same
operator is concatenating two strings. Finally, the same operator is
combining two lists of elements and making a single list. In this
way, if any operator performs additional actions other than what it
is meant for, it is called operator overloading.
3. Method Overloading: - If a method is written such that it can
perform more than one task, it is called method overloading. We
see method overloading in the languages like Java. For example, we
call a method as: sum(10, 15) sum(10, 15, 20) In the first call,
we are passing two arguments and in the second call, we are
passing three arguments. It means, the sum() method is
performing two distinct operations: finding sum of two numbers
or sum of three numbers. This is called method overloading. In
Java, to achieve this, we write two sum() methods with different
number of parameters as: sum(int a, int b) {} sum(int a, int b, int
c) {} Since same name is given for these two methods, the user feels
that the same method is performing the two operations. This is
how the method overloading is done in Java. Method overloading
is not available in Python. Writing more than one method with the
same name is not possible in Python. So, we can achieve method
overloading by writing same method with several parameters. The
method performs the operation depending on the number of
arguments passed in the method call.
4. Method Overriding: - We already discussed constructor
overriding and method overriding under inheritance section. When
there is a method in the super class, writing the same method in the
sub class so that it replaces the super class method is called ‘method
overriding’. The programmer overrides the super class methods
when he does not want to use them in sub class. Instead, he wants
a new functionality to the same method in the sub class.

    

You might also like