0% found this document useful (0 votes)
28 views277 pages

Python - Material Ashok IT

The document provides an introduction to Python, including its history, features, applications, and limitations. It covers Python's setup, programming fundamentals such as reserved words, identifiers, and data types, along with details on IDEs and installation instructions. Additionally, it outlines various Python versions and flavors, emphasizing Python's role as a versatile programming language suitable for beginners.

Uploaded by

palamakularamesh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views277 pages

Python - Material Ashok IT

The document provides an introduction to Python, including its history, features, applications, and limitations. It covers Python's setup, programming fundamentals such as reserved words, identifiers, and data types, along with details on IDEs and installation instructions. Additionally, it outlines various Python versions and flavors, emphasizing Python's role as a versatile programming language suitable for beginners.

Uploaded by

palamakularamesh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 277

Python

Course Material
Unit-1 : Python Introduction

1. Introduction to Python
2. History of Python
3. Applications of Python
4. Features of Python
5. Limitations of Python
6. Flavors of Python
7. Versions of Python
8. Python Setup
FUNDAMENTALS OF PYTHON
Introduction to Python:

 Python is a general-purpose high-level programming language.


 Python was developed by Guido Van Rossam in 1989 while working at National
Research Institute at Netherlands.
 But officially Python was made available to public in 1991. The official Date of
Birth for Python is: Feb 20th 1991.
 Python is recommended as first programming language for beginners.

Printing of “Hello World!”:

In Java:

In Python:

History of Python:

 The name Python was selected from the TV Show: "The Complete Monty
Python's Circus", which was broadcasted in BBC from 1969 to 1974.
 Guido developed Python language by taking almost all programming features
from different languages
1. Functional Programming Features from C
2. Object Oriented Programming Features from C++
3. Scripting Language Features from Perl and Shell Script.
4. Modular Programming Features from Modula-3
Note: Most of syntax in Python Derived from C and ABC languages.

Applications of Python:

1. For developing Desktop Applications


2. For developing web Applications
3. For developing database Applications
4. For Network Programming
5. For developing games
6. For Data Analysis Applications
7. For Machine Learning
8. For developing Artificial Intelligence Applications
9. Telecom Applications
10. For IOT
11. Data Science Applications
12. Artificial Intelligence Applications

Features of Python:

1. Simple and Easy Programming Language to Learn:

Python is a simple programming language. When we read Python program, we


can feel like reading English statements. The syntaxes are very simple and only 30+
keywords are available. When compared with other languages, we can write programs
with very a smaller number of lines. Hence more readability and simplicity. We can
reduce development and cost of the project.

2. Freeware and Open-source Programming Language:

We can use Python software without any license and it is freeware. Source code
is open, so that we can we can customize based on our requirement.

3. High-Level Programming Language:

Python is high level programming language and hence it is programmer friendly


language. Being a programmer, we are not required to concentrate low level activities
like memory management and security etc.

4. Portability:

Python programs are portable. I.e., we can migrate from one platform to another
platform very easily. Python programs will provide same results on any platform.

5. Platform Independent Programming Language:


Once we write a Python program, it can run on any platform without rewriting
once again. Internally PVM is responsible to convert into machine understandable form.

6. Secure and Reusable:

Python is supporting the features of procedure-oriented languages (like: C, C++)


and also of Object-Oriented languages (like: Java). Hence the Python can achieve
security and re-usability of the code.

7. Dynamically Typed Programming Language:

In Python we are not required to declare type for variables. Whenever we are
assigning the value, based on value, type will be allocated automatically. Hence Python
is considered as dynamically typed language. This feature will provide more flexibility to
the programmer.

8. Interpreted Programming Language:

We are not required to compile Python programs explicitly. Internally Python


interpreter will take care that compilation. If compilation fails interpreter raised syntax
errors. Once compilation success then PVM (Python Virtual Machine) is responsible to
execute.

9. Scripting Language:

Python is scripting language, because we can able to develop the scripts to test
the functionality in application in automation testing.

10. Extended to other Programming Languages:

We can use other language programs in Python. The main advantages of this
approach are:
1. We can use already existing legacy non-Python code
2. We can improve performance of the application

11. Extensive Library:

Python has a rich inbuilt library. Being a programmer, we can use this library
directly and we are not responsible to implement the functionality.

Limitations of Python:

1. Not suitable for mobile application development.


2. Not up to mark in performance wise, because it is interpreter dependent
language.
Flavors of Python:

1. CPython:

It is the standard flavor of Python. It can be used to work with C language


Applications.

2. Jython or JPython:

It is for Java Applications. It can run on JVM

3. IronPython:

It is for C#.Net platform

4. PyPy:

The main advantage of PyPy is performance will be improved because JIT compiler
is available inside PVM.

5. RubyPython

For Ruby Platforms

6. AnacondaPython

It is specially designed for handling large volume of data processing.

Versions of Python:

 Python 1.0V introduced in Jan 1994


 Python 2.0V introduced in October 2000
 Python 3.0V introduced in December 2008
 Python 3.1V introduced in Jun 2009
 Python 3.2V introduced in Feb 2011
 Python 3.3V introduced in Sep 2012
 Python 3.4V introduced in Mar 2014
 Python 3.5V introduced in Sep 2015
 Python 3.6V introduced in Dec 2016
 Python 3.7V introduced in Jun 2018
 Python 3.8V introduced in Oct 2019
 Python 3.9V introduced in Oct 2020
 Python 3.10V introduced in Oct 2021
 Python 3.11V introduced in Oct 2022
 Python 3.12V introduced in Oct 2023
 Current Version of Python: 3.12.4, introduced in Jun 2024
Python Software Download:

To download the python, use the below link path:

Download Python | Python.org

Click on “Download Python 3…..”


Python Software Install:

To install the Python software, click on the above downloaded file:

 Select “Add python.exe to PATH”


 And click on “Install Now”
Check Python Software in Computer:

 Open Command Prompt in Computer


 And type a command “python –version”

Integrated Development Environment (IDE)

An integrated development environment (IDE) is a software application that helps


programmers develop software code efficiently. It increases developer productivity
by combining capabilities such as software editing, building, testing, and packaging
in an easy-to-use application.

There are many IDEs are available to develop complex applications using Python.
Usually with only Python software, we can’t develop and build complex applications
because, the Python is interpreter dependent language.

The popular IDEs for Python Development are:


Visual Studio Code (VS Code)
PyCharm
Atom
Spyder
PyDev
PyScripter etc.

PyCharm Download and Installation:

To download PyCharm into our computer, use the below link:

Download PyCharm: The Python IDE for data science and web
development by JetBrains

 Select PyCharm Community Edition

 Click on “Download” button


 Run the downloaded file to install PyCharm.
 Click on “Yes”.
 Click on “Next”.
 Click on “Next”.

 Select an option “Add ‘bin’ folder to PATH”


 Select “Create Desktop Shortcut”.
 Click on “Next”.
 Click on “Install”.
 Click on “Finish”.

Create a Project/Folder in PyCharm:

 Click on “File Menu”.


 Click on “File”.
 Click on “New Project”.
 Enter the name of the project.
 Click on “Create”.

Add a sub folder to Python Project:

 Select the created project.


 Right click of mouse.
 Click on “New”.
 Click on “Directory”.
 Enter the name for the directory.

Create a Python file in the Directory:

 Select the sub folder.


 Right click of muse.
 Click on “New”.
 Click on “Python” file
 Enter the name without any extension.
Unit-2: Python Programming Fundamentals
1. Reserved Words
2. Identifiers
3. Datatypes
4. Type Conversion
5. IO Operations
Python Programming Fundamentals

Keywords

In Python, there are some words which reserved to represent some meaning or
functionality are called as “Reserved Words” or “Keywords”.

There total 35 keywords/reserved words are available in Python:

 'False', 'None', 'True',


 'and', 'or', 'not', 'is',
 'if', 'elif', 'else',
 'while', 'for', 'break', 'continue', 'return', 'in', 'yield'
 'try', 'except', 'finally', 'raise', 'assert',
'import', 'from', 'as', 'class', 'def', 'pass', 'global', 'nonlocal', 'lambda', 'del', 'with'
 'async', 'await',

Q: Write a program in Python to display all the keywords.

Identifiers

To name any entity in program is called as an “Identifier”. Entity in program like:


variable, function, class, object, method etc.

Rules for Identifier:

 Allowed characters to define identifiers are:


o Alphabets (either lower case or upper case)
o Digits (0 to 9)
o Underscore symbol (_)

 Identifier should not start with digit.

 Identifiers are case sensitive.

 No reserved word is an identifier.


 There is no length limit for Python identifiers. But not recommended to use
lengthy identifiers.

Note:

 If identifier starts with _ symbol then it indicates that it is private.


 If identifier starts with __ (two underscore symbols) indicating that strongly
private identifier.
 If the identifier starts and ends with two underscore symbols then the identifier is
language defined special name, which is also known as magic methods.

Ex: __add__

Datatypes

Data Type represent the type of data present inside a variable. In Python we are
not required to specify the type explicitly. Based on value provided, the type will be
assigned automatically. Hence Python is Dynamically Typed Language.

Python contains the following inbuilt data types


 Int
 Float
 Complex
 Bool
 Str
 Bytes
 Bytearray
 Range
 List
 Tuple
 Set
 Frozenset
 Dict
 None

To get the properties of the data, there are three pre-defined methods are available in
python. Those are:

type():

It is a pre-defined method, which is used to find the type of the specified data/value.
Syntax:
type(data/value)
id():

It is a pre-defined method, which is used to get the address of the specified data/value.
Syntax:
id(data/value)

print():

It is a pre-defined method, which is used to print anything/any data.


Syntax:
print(data)

Integer Datatype:

There are four ways to represent integer data in python:

1) Decimal form
2) Binary form
3) Octal form
4) Hexadecimal form

Decimal form (base-10 number system):

 It is default number system in python, means any value can be printed or


accessed by the PVM (Python Virtual Machine) in decimal form.
 The decimal data in python can be represented with allowed digits are from 0 to
9.

Ex: a = 1223

Binary form (base-2 number system):

 Binary number is base-2 number system, means which can be represented with
allowed digits are: 0 and 1.
 And the binary number system in python can always prefixed with ‘0b’ or ‘0B’.
Ex: 0b11001, 0B11000101
Octal form (base-8 number system):

 Octal number system is base-8 number system which can be allowed to


represent with allowed digits are: 0 to 7.
 And the octal number can always be prefixed with ‘0o’ or ‘0O’ in Python.

Ex: 0o1723, 0O11227

Hexadecimal form (base-16 number system):

 Hexadecimal l number system is base-16 number system which can be allowed


to represent with allowed digits are: 0 to 9 and alphabets: a to f or A to F.
 Also called as “alpha numeric data”.
 And the octal number can always be prefixed with ‘0o’ or ‘0O’ in Python.

Ex: 0x1723, 0XAA1122F

Note:

 In Python2 we have long data type to represent very large integral values.
 But in Python3 there is no long type explicitly and we can represent long values
also by using int type only.
 Being a programmer, we can specify literal values in decimal, binary, octal and
hexadecimal forms. But PVM will always provide values only in decimal form.

Base Conversions:

1. bin():

It is a pre-defined/inbuilt method in python, which is used to convert any integer


value into binary value.
Syntax:
bin(any value)

Note: Other than the integer value like: floating-point, boolean, complex etc. not
allowed for the conversion into binary.

2. oct():

It is a pre-defined/inbuilt method in python, which is used to convert any integer


value into octal value.

Syntax:
oct(any value)

Note: Other than the integer value like: floating-point, boolean, complex etc. not
allowed for the conversion into octal.

3. hex():
It is a pre-defined/inbuilt method in python, which is used to convert any integer
value into hexadecimal value.

Syntax:
hex(any value)

Note: Other than the integer value like: floating-point, boolean, complex etc. not
allowed for the conversion into hexadecimal.

Floating-point Datatypes:

 We can use float data type to represent floating point values (decimal values).
 We can also represent floating point values by using exponential form (scientific
notation).

Note:

Floating-point data is allowed to define with only decimal values only.

Complex Datatype:
A complex number is of the form:
Real +/- imaginary
Ex: a + bj

Here: a = real data and b = imaginary data

 In the real part if we use int value then we can specify that either by decimal,
octal, binary or hexadecimal form. But imaginary part should be specified only by
using decimal form.

Boolean datatype:

 We can use this data type to represent boolean values.


 The only allowed values for this data type are:
True and False
 Internally Python represents True as 1 and False as 0.

String Datatype:

 String datatype in python defined with the class name: str.


 A String is a sequence of characters enclosed within single quotes or double
quotes.
Ex: ‘python’, “abcdef”
 To define the multi-line string, triple quotes (‘’’ or “””) are used. We can also use
triple quotes to use single quote or double quote in our String.
Ex:
''' This is " character'''
'This i " Character '
We can embed one string in another string
'''This "Python class very helpful" for java students'''

String Slicing:

 [ ] operator is called slice operator, which can be used to retrieve parts of String.
 In Python Strings follows zero based index.
 The index can be either + ve or -ve.
 +ve index means forward direction from Left to Right.
 -ve index means backward direction from Right to Left.

Note:
 All the above datatypes: int, float, complex, bool and str are primitive type of the
datatypes.
 And all primitive datatypes are “Immutable type”.
 Immutable type means, once we can define the data cannot be modified. If the
re-definition of the value to the variable is take place, the new address will be
created.

Bytes Datatype:

 bytes data type represents a group of byte numbers just like an array.
 The only allowed values for byte data type are 0 to 256. By mistake if we are
trying to provide any other values then we will get value error.
 Once we create bytes data type value, we cannot change its values, otherwise
we will get TypeError.

Bytearray Datatype:

 bytearray is exactly same as bytes data type except that its elements can be
modified.
List Datatype:

If we want to represent a group of values as a single entity where insertion order


required to preserve and duplicates are allowed then we should go for list data type.
 Insertion order is preserved.
 Heterogeneous objects are allowed.
 Duplicates are allowed.
 Growable in nature.
 values should be enclosed within square brackets.

Tuple Datatype:

 Tuple data type is exactly same as list data type except that it is immutable., we
cannot change values.
 Tuple elements can be represented within parenthesis.
Range Datatype:

 range Data Type represents a sequence of numbers.


 The elements present in range Data type are not modifiable. i.e., range Data type
is immutable.
 We cannot modify the values of range data type.

Set Datatype:

If we want to represent a group of values without duplicates where order is not


important
then we should go for set Data Type.

 Insertion order is not preserved.


 Duplicates are not allowed.
 Heterogeneous objects are allowed.
 Index concept is not applicable.
 It is mutable collection.
 Growable in nature.
Frozenset Datatype:

 It is exactly same as set except that it is immutable. Hence, we cannot use add
or remove functions.

Dict Datatype:

 If we want to represent a group of values as key-value pairs then we should go


for dict data type.
 Duplicate keys are not allowed but values can be duplicated. If we are trying to
insert an entry with duplicate key then old value will be replaced with new value.
 dict is mutable and the order won’t be preserved.
Type Conversion

 Type Conversion is also called as “Type Casting” or “Coercion”.


 Type casting is used to convert the data from one form to another form of the
data.
 There are list of inbuilt methods are available in python for the type conversion:
o int()
o float()
o complex()
o bool()
o str()

Any Data to Integer Conversion:

int():
 It is a pre-defined method/inbuilt method used to convert any data to integer
(decimal).

Syntax:
int(any value)

Rules for Integer conversion:

 int() method is allowed to convert any base value of integer to decimal.


o Like: binary to decimal conversion
o Octal number to decimal conversion
o Hexadecimal to decimal conversion.
 Int() method is allowed to convert float value to decimal value.
o Float with decimal literals to decimal by rounding the digits.
o Exponential value also allowed to convert into decimal.
 Boolean value also allowed to convert into decimal using int() method.
o True can be converted into ‘1’
o False can be converted into ‘0’
 String with decimals only possible to convert into integer using int() method.
Ex: int(‘123’) = 123
 String with alphabets, floats etc. are not possible for integer conversion using
int() method.
 Complex values cannot be possible to convert into integer using int() method.
Any Data to Floating-point data:

float():

float() is inbuilt method used to convert any data to floating-point value.

Syntax:
float(Any Value)

Rules for floating-point conversion:

 Any integer (with any base) allowed to convert into float.


o Binary to float
o Octal to float
o Hexadecimal to float
o Decimal to float
 String with decimals and with floats are allowed to convert into float.
Ex: float(‘123.123’) = 123.123
Float(‘123’) = 123.0

 Boolean values are considered to convert into float data.


 String with alphabets or with any other characters are not possible to convert into
float.
 Complex data is not allowed to convert into float.

Any Data to Complex data Conversion:

complex():

A pre-defined method which can be allowed to convert any data to complex data.

Syntax:
complex(Any value)

Rules for complex Conversion:

 Any integer data (with any base) can be allowed to convert into complex.
 The float value can be allowed to convert into complex data using complex().
 Boolean value also allowed for the complex conversion.
 String with complex, integer, float are allowed for the complex data conversion.
Any Data to Boolean Conversion:

bool()

bool() is a pre-defined/inbuilt method which is used to convert any data into boolean
data.

Syntax:
bool(Any Value)

Note:
 Any non-zero value is the “True” by bool() method.
 Any zero value is the “False” by bool() method.
 String with empty quotes is equals to ‘0’ by bool() method.
Any Data to String Conversion:

str():

str() is the method which is used to convert any data to string data.

Syntax:
str(Any data)
IO Operations
IO Operations is represented as “Input and Output Operations”. To perform IO
operations in python, there are two inbuilt/pre-defined methods:

1) input()
2) print()

Input Operations:

input():

 input() is an inbuilt method, which is used to read a value which is entered from
keyboard during the time of running of the program.
 input() method can read a string value by default.
 To read other type of the data/value, we required to perform the type conversion
to input() method with the required type.

Ex: to read a decimal/integer value:


Int(input())

Output Operations:

print():

 print() is an inbuilt method used to write/print anything/any data on the screen.


Syntax:
print(Any Value)

 print() method is reserved with new line after printing of any data in all the time.
Interview Questions:

1) WAP to display list of keywords in Python.


2) What are identifiers in Python? What are rules for naming identifiers?
3) Why is it important to follow naming conventions for identifiers in Python?
4) What happens if you name a variable with “def” or “class” in Python?
5) WAP in python to take a binary value as an input and print its equivalent decimal,
octal and hexadecimal value.
6) WAP in python to accept an octal value as an input and print its equivalent
decimal, binary and hexadecimal value.
7) WAP in python to accept the string data and print the character at 3 rd place of the
string.
8) What is dynamic typing in Python?
9) WAP in python two swap values of two variables using temporary variable.
10) What is the difference between mutable and immutable datatypes?
11) What are frozen sets and how they are differ from sets?
12) What is type casting? And what is the difference between implicit and explicit
type casting?
13) What is the difference between list and tuple data?
Unit-3 : Operators
1. Arithmetic Operators
2. Assignment Operators
3. Relational Operators
4. Logical Operators
5. Conditional Operator
6. Bitwise Operators
7. Special Operators
Operators
Introduction:

OPERAND:
A data/value/variable on which we can define an operation is called as an
“Operand”.
Ex: 10 + 20
Here: 10 and 20 are operands
We are defining ‘+’ operation on these operands.

OPERATOR:
A symbol which is used to define an operation is called as an “Operator”.
Ex: 10 + 20
Here: + is an operator, which denotes sum/addition operation.

EXPRESSION:
A combination with an operator and operands is called as an “Expression”.
Ex: 10 + 20 is an expression
Operands: 10 and 20 are joined with an operator ‘+’

STATEMENT:
A line of code which may or may not be terminate with semi-colon is called as a
“statement”.

Block of statements:
A block of statement/code can be defined with one or more number of
statements. In python, the block of code can be represented with indentation.
TYPES OF OPERATORS:

According to the definition of an expression, the operators are classified into


three types:
1) Unary Operators:
An operator with single operand is called as “Unary Operator”.
Ex: Unary Minus Operator, Logical Not and Bitwise Complement Operator etc.

2) Binary Operators:
An operator can be defined with two operands is called as “Binary
operator”.
Ex: +, -, *, ** etc.

3) Ternary Operators
An operator can be defined with three operands is called as “Ternary
operator”. Also called as “Conditional operator”.

According to functionality, the operators are classified into several types:


1) Arithmetic Operators
2) Assignment Operator
3) Compound Operators
4) Relational Operators
5) Logical Operators
6) Bitwise Operators
7) Special Operators

1) Arithmetic Operators

The arithmetic operators are:


+ ==> Addition
- ==> Subtraction
* ==> Multiplication
/ ==> Normal Division
// ==> Floor Division
% ==> Modulo Division
** ==> Exponent Operator

Note:
 (/) Operator always performs floating point arithmetic. Hence it will always return
float value.
 But Floor division (//) can perform both floating point and integral arithmetic. If
arguments are int type then result is int type. If at least one argument is float
type, then result is float type.
Note:

For any number x,


x/0 and x%0 always raise "ZeroDivisionError".
10/0
10.0/0

2) Assignment Operator:

Symbol: =
Assignment operator is used to assign anything to the variable/expression. Assignment
operator’s associativity is from right to left.

3) COMPOUND OPERATOR:

+=, -=, *=, /=, //=, %=, **=

Ex: x += 10 or x = x + 10
X -= 10 or x = x – 10
X *= 10 or x = x * 10
X /= 10 or x = x /10
X //= 10 or x = x // 10
X %= 10 or x = x % 10
X **= 3 or x = x ** 3
4) RELATIONAL OPEARTORS:

 Relational Operators are also called as “Comparison Operators”.


 These are used to compare two values and return a result as boolean value
either True or False.
 The relational operators are:
<, >, <=, >=, ==, !=
 Relational operators are binary operators.

Note:
 Chaining of relational operators is possible. In the chaining, if all comparisons
return True then only result is True. If at least one comparison returns False then
the result is False.
Difference between ‘==’ and ‘=’

 If we can use an assignment operator (=) in place of equal operator (==) “Type
Error” is returned.
 If an equal operator is written in place of assignment operator (=) “Name Error” is
returned.

5) LOGICAL OPERATORS:

 To join two or more expressions into single expression using logical operators.
 Logical operators are:
1) Logical And == and
2) Logica Or == or
3) Logical Not == not

Logical and operator:

 Logical and operator is a binary operator.


 We can be allowed to use with all values.
 Logical and operator is working according to the truth table.

Note:

For logical and operation, when we define with other than boolean values:
 If both inputs are defined with non-zero values, the output is the second
operand/input value.
 If the first input is zero and the second input is non-zero, the output is “zero”
without decode the second operand/input value.
 If the first input is non-zero and the second input is zero, the output is “zero”.

Note:

 Any logical operator can understand any non-zero value (positive/negative) as


“True” and zero value as “False”
Logical or operator:

 Logical or operator is a binary operator which always allowed to define with two
possible operands/values.
 It can also be allowed to define with any type of values like: decimal, binary, float
etc.
Note:

For logical or operation, when we define with other than boolean values:
 If both inputs are defined with non-zero values, the output is the first
operand/input value.
 If the first input is zero and the second input is non-zero, the output is “second
operand/input value”.
 If the first input is non-zero and the second input is zero, the output is “first
operand value”.

Logical not Operator:

 Logical not is a unary operator, which need only single operand.


 Logical not also allowed to define with any values.
 For any non-zero value, not operator will return an output as “True”
 For zero inputs, the output is “True”
6) Conditional Operator:

Conditional Operator also called as “Ternary Operator”.

Syntax:
resultant-variable = expression1 if condition else expression2

here:
if and else ==> keywords

conditions ==> with relational operators


with relational and logical operators
ex: a > b, a == b or a < b
Bitwise Operators:

 All Bitwise operations can define on individual bits of the given data.
 Bitwise operations are allowed to define with: boolean data and integer data only.
 bitwise operations are:
bitwise and ==> &
bitwise or ==> |
bitwise xor ==> ^
bitwise complement ==> ~
shift operators
left shift ==> <<
right shift => >>

bitwise and ==> &:

 BINARY OPERATOR

a b a&b
==============
1 1 1
1 0 0
0 1 0
0 0 0

 When both inputs are ‘1’, the output is ‘1’


 When any input is ‘0’, the output is: ‘0’
 When we define the bitwise and on integer data, each input value can convert to
binary and define the bitwise and can perform the operation from right to left on
each individual bits.
bitwise or ==> |:

 Binary operator

a b a|b
==============
0 0 0
0 1 1
1 0 1
1 1 1

 When both inputs are ‘1’, the output is ‘1’


 When any input is ‘1’, the output is: ‘1’
 When both inputs are ‘0’, the output is: ‘0’.
 When we define the bitwise or on integer data, each input value can convert to
binary and define the bitwise or can perform the operation from right to left on
each individual bits.

bitwise xor ==> ^:

 Binary operator

a b a^b
==============
0 0 0
0 1 1
1 0 1
1 1 0
 For same inputs, the output is ‘0’.
 For different inputs the output is ‘1’.
 When we define the bitwise Xor on integer data, each input value can convert to
binary and define the bitwise Xor can perform the operation from right to left on
each individual bits.

BITWISE COMPLEMENT ==> ~:

 Bitwise complement can use to find the 2's complement of number.


 Unary operator
 2's complement ==> inverter
+eve ==> -eve
-eve ==> +eve

print(~0)
print(~7)
print(~-7)

Shift Operators:

1) Left Shift Operator:

 Binary Operator.

Syntax:
Data << n
Here:
n = number of times

 Left shift operation can be defined on the data by converting into binary with
‘n’ number of times.
 Left shift operation defines: shifting of bits from right to left bit by bit and place
‘0’ in LSB place after the shifting of bits.

2) Right Shift Operator:

 Binary Operator.

Syntax:
Data >> n

Here:
n = number of times

 Right shift operation can be defined on the data by converting into binary with
‘n’ number of times.
 Right shift operation defines: shifting of bits from left to right bit by bit and
place ‘0’ in MSB place and discard the LSB after the shifting bit by bit.

SPECIAL OPERATORS:

1) Membership Operators:

in, not in

 These are used to define with collections.


 Used to check whether the specified element is belonging to the given
collection or not.
 Returns: Boolean values
2) Identity Operators:

 Identity Operators are used to check whether two objects are pointing to the
same location or not.
 Returns: Boolean values.

Practice Programs:

1) Write a program to find the maximum among three numbers.


2) Write a program to check whether the number if even or odd using conditional
operator.
3) Write a program to find the area of the perimeter and area of the circle.
4) Write a program to check the type of the triangle.
5) Write a program to find the area and circumference of the rectangle.
6) Write a program to convert the temperature from Fahrenheit to Celsius.
7) Explain the difference between ‘==’ and ‘=’ operators.
8) Explain the difference between ‘/’ and ‘//’.
9) WAP in python to convert the temperature from Celsius to Fahrenheit.
10) WAP in python to check whether the number s even or odd using conditional
operator.
Unit-4: Control Statements
Conditional Statements/Selection Statements
If statement
If-else statement
If-elif-else statement

Loop Statements/Iterative Statements


While loop
For loop

Transfer Statements
Break statement
Continue statement
Pass statement

Patterns
Control Statements
In general, all python programs can be executed in sequential (statement by statement).
Instead of executing the python program in sequential, to execute only the selected part
of the program or to execute the part of the program repeatedly or to stop executing of
the program certainly control statements can be used.

The control statements can be classified into three types:


1) Conditional statements/Selection statements
2) Loop statements/Iteration statements
3) Transfer statements

1. Conditional Statements:

if statement:

Syntax:
if condition:
statements

condition: can be defined with relational operators and with any values.

Working Operation:

If the condition is evaluated as “True”, then the statements in if-block will be get
executed otherwise, the statements in if-block will be not executed.
Program to define if statement with integer value as condition
Program to define if condition with boolean value

Program to define the if condition with string value

If-else Statement:

Syntax:
If condition:
Statement-1
Statement-2
else:
Statement-3
Statement-4

Working Operation:

If “condition” is “True”, then the statements in if-block can be executed. Otherwise, the
statements in else-block can be executed.
If-elif-else statement:

Syntax:
If condition1:
Statements
elif condition2:
statements
elif condition3:
Statements
else:
statements

Working Operation:

If condition1 is “True”, then if-block statements can be executed otherwise the


condition2 is evaluated, if it is “True”, then the statements of elif-block can be executed
otherwise it can be check with condition3 to execute with elif-block statement. If no
more conditions are remaining then it can execute with else block statements
automatically.

2. Loop Statements:

Loop statements are also called as “Iterative statements”. A loop is a sequence


of iterative statements or instructions that are continuously repeated until a certain
condition meets. Loops are used in scenarios where we want to do certain work
numerous times. So instead of writing the same code multiple times, we use a loop.
There are two loop statements supported by the Python:
1) While loop
2) For loop

while loop:

In Python, while is the keyword which we can use to define the while loop
statements. If we want to execute a group of statements iteratively until some condition
false, then we should go for while loop.

Syntax:

initialization
while condition:
loop body statements
update statement

Q: Write a python program to print numbers from 1 to 10 using while loop.

Q: Write a python program to print numbers from 10 to using while loop.


Q: Write a python program to find the sum of individual digits of the given
number.

for loop:

If we want to execute some action for every element present in some sequence (it may
be string or collection) then we can use for loop.

Syntax:

for iteration_variable in sequence:


loop body statement

here:
sequence  strings, list, tuple etc.

range ():

range () is a pre-defined operator in python which is used to generate a range of values.

Syntax:

range(x) ==> generate numbers from 0 to x-1


range (x, y) ==> generate numbers from x to y-1
range (x, y, z) ==> generate numbers from x to y-1 with the difference of ‘z’
for loop can also allowed to define some action on the numbers which can be generated
from the range of values.

Syntax:

for iteration_variable in range (some):

loop body statement

A Program to iterate on string data using for loop

A Program to iterate on list data using for loop

A Program to print numbers from 0 to 10 using for loop.


A Program to print numbers from 1 to 10 using while loop.

A Program to sum of all odd numbers from 100 to 1 using for loop

Infinite Loops:

An infinite loop in Python is a continuous repetition of the conditional loop until


some external factors like insufficient CPU memory, error in the code, etc. occur. An
infinite loop does not have an explicit end.
In the above code, “Python Fullstack in Ashok IT” is printed an infinite number of times.
Now, we can terminate the execution using CTRL + C so that the memory of the CPU
does not get exhausted.

When are Infinite Loops necessary?

In Python, an infinite loop can be useful in various scenarios. One of the prime
uses of an infinite loop can be seen in a client-server architecture model in networking.

As we know a server is central storage that is always awake and ready to handle
client requests. So, a server runs in an infinite loop which makes it always awake and
ready to handle various situations like new requests from the client, new connections
from the client, etc.

Another example of an infinite loop in Python can be visualized in game


development. For example, an infinite while loop is used for the main game frame which
continues to get executed until the user or the game selects some other event. Since
the game developer does not know the exact iterations or the time at which the user will
do something, the game developer uses the infinite loop in Python.

Nested Loops:

Nested loops are described as a loop can be defined within other loop statements.

Syntax:
Outer_Loop:
Statement-1
Statement-2
Inner_Loop:
Statement-3
Statement-4
Transfer Statements:

Transfer statements are used to:


 When to stop/terminating the loop execution immediately.
 When to pause/skip the iteration and to continue with remaining iterations.

There are two types of transfer statements:


1) Break Statement
2) Continue Statement

Break Statement:

 “break” is the keyword which is used to define the break statement.


 When need to stop/terminate execution of the program, break is used.

Syntax:
break
Continue Statement:

 “continue” is the keyword which is used to define the continue statement.


 When need to skip/pause the iteration and continue with the remaining
iterations, continue is used.

Syntax:
continue

Note:
 Python cannot support to use switch statement, do-while and goto like other
languages.

Practice Programs:

1) Write a program in Python to find the type of the triangle.


2) Write a program in Python to accept a single digit number and print its value in
English.
3) Write a program in Python to find the smallest number among four integers.
4) Write a program in Python to check whether the given number is between 1 and 100.
5) Write a program to find the sum of two numbers if first is smaller than second
otherwise print its difference.
6) Write a program in Python to accept 4 integers and check whether the square is
possible with the given four integers or not.
7) Write a program in python to find the reverse of the number.
8) Write a program in python to check whether the given number is palindrome number
or not.
9) Write a program in python to check whether the given number is Armstrong number
or not.
10) Write a Python program to find those numbers which are divisible by 7 and multiples
of 5, between 1500 and 2700 (both included).
11) Write a Python program to convert temperatures to and from Celsius and
Fahrenheit.
12) Write a Python program that accepts a word from the user and reverses it.
13) Write a Python program to count the number of even and odd numbers in a series
of numbers.
14) Write a Python program to get the Fibonacci series between 0 and 50.
15) Write a Python program to check whether an alphabet is a vowel or consonant.

Unit-5: List Data Operations

List Data and Properties


Creation of List
Traversing on List
Is List Mutable?
Math Operations
List Comparison
Membership checks on List
Counting of number of occurrences
Finding of element in a list
Adding of elements to the list
Removing of elements from the list
Ordering of list elements
Aliasing and Cloning of List data
Nested lists
List Comprehensions

List Data Structure


List Data and Properties

 List is a sequential collection data item.


 List can define with [] and all elements in [] must be separated with comma.
Ex: [1,2,3,4,5]
 List is pre-defined/inbuilt datatype because it has an inbuilt class i.e., “list”.
 List is Sequenced because the list data can be get accessed with indexing
(positive indexing/negative indexing).
 List is supposed to accessing the part of the list using slicing.
 List can possible to define with same type of data items which is called as
“Homogeneous List”.
 List can possible to define with different type of data items which is called as
“Heterogeneous list”.
 List is ordered datatype.
 List can possible to define with duplicated elements.

Ways to creation of List:

1) Compile Time Definition:

Syntax:
List-object-name = [list elements with comma separation]

Ex: a = [1,2,3,4,5]

2) Run Time Definition:

eval ():

To define the list in run-time or to define dynamical changed list, eval() method is used.

Syntax:
eval(input())
3) list ()

Syntax:
List-object-name = list (any collection)

 This method can use for the conversion of any collection to list.

4) split ():

Syntax:
List-object-name = str-data-object.split(‘separator’)

This method can use to split the string based on the separator. The separator can be
any character within single quotes or double quotes.
Traversing on the List:

Using while loop:

Syntax:
Initialization

while condition_to_iterate_loop:
block of operation
update

Using for loop:

Syntax:
for loop-variable in list-data:
block of code
Membership Check:

To check the element whether it is the member to the list or not we have two types of
membership operators:
1) in
2) not in

List Comparison:
List comparison is defined with relational operators like: <, >, <=, >=, == , !=

Equality check:

Equal operators can check on list:


1) whether both list data are with same size or not.
2) If both are with same size:
Individual element comparison on each list element by element.
3) If all elements of both lists are same
Equal operators can return “True”.
4) If both are with different sizes:
equal operators can return “False” .

Comparison with other operators:

List comparison with <, >, <=, >= should be element by element on from both lists with
any size of lists.

List is Mutable:
Once we create a List object, we can modify its content. Hence List objects are mutable.

Counting of number of occurrences of element in a list:

count():

 count() method can use to find the total number of occurrences of the specified element
within the list.

Syntax:
List-data.count(list element)

 If the specified element in count() is not the member of the list, count() can return = '0'.
 we cannot count the number of occurrences of the specified within the range.
Finding of first occurrence of the specified element in a list:

index():

index() method use to find the first occurrence of the specified element in the given list.

Syntax:
list_data/list_object.index(element)

When the specified element is not in the given list, index() can return: “value error”.

Adding of elements into a list:

To add elements into the list, there are different methods in python:
1) append()
2) insert()
3) extend()

Adding of an element at the end of the list:

append():

append() is the method used to add the element at the end of the list by default.

Syntax:
List-data-name.append(element)
Note:
Using append(), we can add only one element into the list at a time.

Adding of an element at the specified index/position in a list:

insert():

This method can add an element at the specified index/position in a list.

Syntax:
List-data.insert(index, element)

Note:
If the specified index is from out of the index range of the list data, index() can add the
specified element at the end automatically.

Adding of list of elements into list:

extend():

extend() method can add the group of elements into the given list.
Syntax:
Main-list.extend(list of elements)

Note:
extend() method can add list of elements into the given list at the end by default.

Removal of elements from the list:

To remove elements from the given list, we have:


1) remove()
2) pop()
3) del
4) clear()

1) remove():

remove() is the method can use to remove the specified element from the list.

Syntax:
List-data-name.remove(element)

Note:
If the specified element is not in the list, remove() can return “value error”.
2) pop():

This method can use to:


i) remove the last element from the list by default.

Syntax:
List-data-name.pop()

ii) pop() can also remove the element from the list based on the specified index.

Syntax:
List-data-name.pop(index)
3) del

del is the property/attribute can use to delete the specified element from the list based
on the index.

Syntax:
del list-data-name[index]

del property can also use to delete the total list data permanently from the memory.
Once we deleted using del property, we cannot use or access it again. If we can access
the list variable after the delete using del property we can get “Name Error”.

Note:
Using del property, we can delete any data from the program.

4) clear():

This can use to clear the total list elements from the list.

Syntax:
List-data-name.clear()
Note:

After the clearing/deleting of list using clear(), we can access that list.

Reversing of the list:

reverse():

To reverse the list data we can use reverse() method.

Syntax:
List-data-name.reverse()

Sorting of the list:

1) Forward Sorting:

Arranging of the list in ascending order is called as “forward sorting”.


Syntax:
List-data-name.sort()

2) Reverse Sorting:

Arranging of the list in descending order is called as “reverse sorting”.

Syntax:
List-data-name.sort(reverse = True)

List Aliasing and Cloning:

 The process of giving another reference variable to the existing list is called
aliasing.
 The problem in this approach is by using one reference variable if we are
changing content, then those changes will be reflected to the other reference
variable.
 To overcome this problem we should go for cloning.
 The process of creating exactly duplicate independent object is called cloning.
copy():

It is used to copy the data of one list to another list.

Syntax:
New-list = List-data-name.copy()

Math Operations

1) List Concatenation:

 Joining of two or more lists into one list is called as “List Concatenation”.
 List concatenation can define with symbol: ‘+’.

Syntax:
List-data-name1 + List-data-name2
2) List Repetition:

 List data be repeated with given number of times is called as “List


Repetition”.
 It can denote with symbol: ‘*’

Syntax:
List-data-name * num-times

Nested List:

Defining of a list in another list is called as “nested list”.


Practice Programs:

1) Write a program to declare and print the list.


2) Write a program to add an element to the list at the given position.
3) Write a program to remove the element from the list.
4) Write a program to remove the first occurrence of the list.
5) Write a program to remove all occurrences of a given element from the list.
6) Write a program to remove all elements in a range from the list.
7) Write a program to arrange list elements in ascending and descending order.
8) WAP in python to find the second largest element of the list.
9) WAP in Python to check whether the list palindrome or not.
10) WAP in python to rotate a list by ‘k’ positions.
11) WAP to find the duplicates of the list.
12) WAP to merge the data of two lists.
13) WAP to remove duplicates from a list while maintaining an order.
14) WAP to find the missing number in a list of consecutive numbers.
15) WAP to sort the list data in descending order.
Unit-6: String Operations

String Definition
Multi-line string literal
Accessing of characters of the strings data
Accessing the part of the string data
Traversing on the string data
Math Operations
Finding of string length
Membership check
String Comparison
Removal of spaces from the string
Finding of sub-strings of the string
Counting number of occurrences of the sub-string in a string
String replacement
String to List conversion
Joining of strings into one string
Changing case of the string
Checking starting and ending part of the string
Checking type of characters present in a string
Formatting of the string
Strings
What is string?

 Any sequence of characters within either single quotes or double quotes is


considered as a String.

Ex: ‘python’
“Python”

Note:
 In most of other languages like C, C++, Java a single character with in single
quotes is treated as char data type value. But in Python we are not having char
data type. Hence it is treated as String only.
 Like C, strings in Python cannot end with null character (‘\0’).

Multi-line string literal:

We can define multi-line String literals by using triple single or double quotes.
Ex:
'''Python is High-level,
General-purpose,
Object Oriented
Programming language.'''

"""Python is High-level,
General-purpose,
Object Oriented
Programming language."""

Note:
====
1) adding of double quotes in between double quotes ==> not possible.
2) adding of single quotes in between single quotes ==> not possible
==> to add:
\ start-quotes ........ \ end-quotes
Accessing of characters of the string data:

1) Unsing Index:

Indexing on strings can define in two ways:

Using positive index:

 It can use to access the string characters from left to right.


 Also called as "forward accessing".
 Default start value: 0.
 End with: Number of characters of string – 1.
 Range of positive indexing ==> 0 to number of characters of string – 1.
 if the index value from out of range ==> Index error

Using negative index:

 Negative index can use to access the string characters from right to left.
 Also called as "reverse accessing".
 Default start value: -1.
 Default end value: -total characters of string.
 range of negative indexing ==> -1 to -total number of characters of string

Syntax:
String-data-name [index value]
2) Slicing:

Syntax:
Str-data [start: stop] ==> slicing start at "start" value and end with "stop-1" value

Str-data [start: stop: step] ==> slicing start with "start" value and end with "stop-
1" value with the difference of "step"

Str-data [: stop] ==> by default, slicing can start with first character and end
with "stop-1" value

Str-data [start:] ==> slicing can start with "start" value and end with "last" by
default

Str-data [: :] ==> start with first character and end with last

Str-data [: : step] ==> start with first character and end with last with difference
of step value.
Finding length of the string:

len():

len() method is used to find the length of the string.

Syntax:
len(string-data)
Without len() method:

Traversing on the string data:

To traverse the string data, we can use while loop and for loop.

Math Operations:

1) String Concatenation:

 Joining of two or more strings into one string is called as “string concatenation”.
 String concatenation can represent with ‘+’ operator.
2) String Repetition:

This can use to repeat the string data for number times. And it can represent with string
repetition operator (*).

Syntax:
String-data * number-times

Note:
 String is immutable type, for any operation there will be the new object address
can create.

Membership Check:

 Membership check can define with two operators:


in
not in
are called as “membership operators”.

String Comparison:

 String comparison can define with relational operators.


 Any Relational operators on the string:
1) check with length first.
2) checking with individual characters of both strings with respect to ASCII
value.

Changing case of string data:

We can change case of a string by using the following methods:


upper()

 This is an inbuilt method in python which can use to convert the total given string
into upper case string.

Syntax:
String-data. upper ()

lower()

 This an inbuilt method in python can use to convert the given string into lower
case string.

Syntax:
String-data. lower ()

swapcase()

 This is an inbuilt method in python can use to convert a lower case string to
upper case and upper case string to lower case

Syntax:
String-data. swapcase ()

title()

Title case means that every word of the same string should be start with capital letter.
ex: python programming language
title case ==> Python Programming Language
 title() is an inbuilt method in python can use to convert any case string into title
case.

Syntax:
String-data. title ()

Capitalize ()

Capitalize case means that the entire string (might be with more than one word), that
only the first word should start with capital remaining all the characters in lower case

Ex: Python programming language


 capitalize() is an inbuilt method can use to convert any case string into capitalize
case.

Syntax:
String-data. capitalize ()
Checking start and end part of the string:
1) string.startswith(sub-string):
2) string.endswith(sub-string):

Check type of characters of given string:


Python contains the following methods for this purpose.
1) isalnum(): Returns True if all characters are alphanumeric( a to z , A to Z ,0 to9 )
2) isalpha(): Returns True if all characters are only alphabet symbols(a to z,A to Z)
3) isdigit(): Returns True if all characters are digits only( 0 to 9)
4) islower(): Returns True if all characters are lower case alphabet symbols
5) isupper(): Returns True if all characters are upper case aplhabet symbols
6) istitle(): Returns True if string is in title case
7) isspace(): Returns True if string contains only spaces
Removing spaces from the string:

We can use the following 3 methods:


1) rstrip() ===>To remove spaces at right hand side

Syntax:
String-data.rstrip()

2) lstrip() ===>To remove spaces at left hand side

Syntax:
String-data.lstrip()

3) strip() ==>To remove spaces both sides

Syntax:
String-data.strip()
Finding of sub-strings in a given string

In forward direction:
To find sub-strings in a given string from left to right, there are inbuilt methods in python
are:
1) find()
2) index()

find():

Syntax:
String-data.find(sub-string)

 when the sub-string is at multiple places, find() can return the first occurrence.
 when the sub-string is not the part of the string, find() can return '-1'.
 using find(), we can search about the sub-string from the given range.
 when we defined the sub-string with more than one character, find() returns: the
index of First character of the sub-string only.
index():

Syntax:
String-data.index(sub-string)

 when the sub-string is at multiple places, index() can return the first occurrence.
 when the sub-string is not the part of the string, index() can return 'value error'.
 using find(), we can search about the sub-string from the given range.
 when we defined the sub-string with more than one character, index() returns:
the index of First character of the sub-string only.

In backward direction:

To find sub-strings in a given string from right to left, there are inbuilt methods in python
are:
1) rfind()
2) rindex()

rfind():

Syntax:
String-data-name.rfind(‘sub-string’, start-index, stop-index)

rindex():

Syntax:
String-data-name.rindex(‘sub-string’, start-index, stop-index)
Counting number of occurrences of the sub-string in a string:

count():

We can find the number of occurrences of substring present in the given string by using
count() method.

Syntax:
String-data-name.count(sub-string)

String-data-name.count(sub-string, start-index, stop-index)

Replacing a string with another string:

replace():

Syntax:
String-data-name.replace(old-string,new-string)
String to list conversion:

Split():

Syntax:
String-data-name.split(‘separator’)
List to string conversion:

join():

Syntax:
‘separator’.join(list-data-name)

Practice Programs:

1) Write a program to reverse the string data.


2) Write a program reverse order of words in a given string.
3) Write a program to reverse the internal content of each word of the string.
4) Write a program to print characters at even and odd positions for the given string.
5) Write a program to merge characters of two strings into a single string by taking
characters alternatively.
6) Write a program to sort the characters of the string and first alphabet symbols
followed by numeric values.
7) Write a program for the following requirement:
Input: a4b3c2d1
Output: aaaabbbccd
8) Write a program for the following requirement:
Input: a4k3b2
Output: aeknbd
9) WAP to check whether the string is palindrome or not.
10) WAP to count the number or occurrences of each character in a string.
11) WAP to check whether two strings are anagrams or not.
12) WAP to rotate the string data.
13) WAP to find the permutations of a string.
Unit-7: Tuple Operations

Tuple-Features
Creation of the tuple
Traversing on tuple data
Tuple Math Operations
Tuple comparison
Counting number of occurrences of the specified element of tuple
Finding of the specified element of tuple
Tuple Sorting
Finding of minimum and maximum from collection data
Tuple packing and unpacking
Tuple Operations
Tuple-Features:

 It is a sequential collection datatype.


 Tuple data can define with parenthesis ‘()’.

Syntax:
Tuple-object-name = (item1, item2, item3, …)

 It is a pre-defined/an inbuilt datatype because for the tuple data representation


and other operations/methods there is an inbuilt class named as “tuple”.
 Tuple is an ordered datatype.
 tuple can index supported to access the individual elements of the tuple.

Syntax:
Tuple-object-name[index]

Note:
====
Like strings and list, Tuple can also support both positive index and negative index.
1) positive indexing can use to access the elements of tuple using forward access.
Forward access means accessing of tuple data from left to right.
2) negative indexing can use to access the elements of tuple using reverse access.
Reverse access means accessing of tuple data from right to left.

 Tuple can allow to access the part of the data using slicing.

Syntax:
Tuple-object-name[start : stop : step]

 Tuple can define with homogeneous elements.


 Tuple can define with heterogeneous elements.
 Tuple can be nested with other collections.

Note:
list can also be nested with other collections.

 Tuple can be immutable datatype.


Note:
====
To modify the tuple, we can convert that tuple into list, on this list we can define any
modification. After that the list can convert into tuple again

tuple ==> list ==> define change ==> tuple

list():

list() is an inbuilt method which we can use to convert any collection data to list data.
Ex: tuple data can convert to list using list().

Syntax:
list(any collection data)

tuple():

tuple() is an inbuilt method which can use to convert any collection to tuple data.
Ex: list data can convert to tuple using tuple().

Syntax:
tuple(any collection data)
Creation of Tuple:

1) Compile time definition:

 Compile time definition is nothing but the direct assignment of the tuple data to
tuple object using assignment operator.

Syntax:
Tuple-object-name = (e1, e2, e3, …)

 For the tuple definition, () is optional but comma between elements is mandatory.

Syntax:
Tuple-object-name = e1, e2, e3, …

Note:
For the list representation [] is mandatory.

2) Run time definition:

 The tuple in run time can dynamically change.


 To define the dynamically changed tuple, eval() method can use.

Syntax:
eval(input(“Enter tuple data:”))

3) Using tuple():

 tuple() method can use to convert any collection data to tuple data.

Syntax:
tuple(any collection data like: list, string etc.)
Traversing on Tuple:

Using while loop:

Syntax:
Initialization
While condition:
Block of code
Update

Using for loop:

Syntax:
for iteration-variable in tuple-collection:
block of code

Math Operations:

1) Tuple Concatenation:

 The joining of two or more tuples into one called as "tuple concatenation".
 Symbol for tuple concatenation: ‘+’
Syntax:
Tuple1 + Tuple2 + Tuple3 + ….

2) Tuple Repetition:

 To make repeat the data of tuple for number of times, we can use tuple
repetition.
 Symbol of denote is: ‘*’

Syntax:
Tuple-data-name * n

Here: n is number of times

Tuple comparison:

Tuple is possible with relational operators (<, >, <=, >=, ==, !=)

Comparison with equal operators:

 The equality check on tuple can define with: == and != operators.


 Equal operators on tuple data can check:
o Lengths of both tuples
If lengths of both tuple data is same then, these can compare on both
tuples individually like: element by element.

Comparison with other relational operators:


 These operators can compare on both tuple element by element even both
tuples are with different sizes.

Counting number of occurrences of the element in a tuple:

count():

Syntax:
Tuple-data-name.count(element)

Note:
 count() can return '0' if the specified element is unknown to the tuple data.
 count() method cannot find the element in between the indexes.

Find the element in a tuple:

index():

Syntax:
Tuple-data-name.index(element)
Note:
 index() can also find the element within the specified range.
Syntax:
Tuple-data-name.index(element, start-index, stop-index)

Tuple sorting:

sorted():

sorted() is an inbuilt method in python to arrange the tuple data in ascending order
(forward sorting) and/or descending order (reverse sorting).

Forward Sorting:

Syntax:
sorted(tuple-data)

Reverse Sorting:
Syntax:
sorted(tuple-data, reverse = True)

Finding of minimum and maximum value from collection data:

min():

min() is an inbuilt method which we can use to find the minimum value from the given
collection data.

Syntax:
min(collection data)

max():

max() is an inbuilt method which we can use to find the maximum value from the given
collection data.

Syntax:
max(collection data)
Tuple packing and unpacking:

Tuple packing means packing/creating a tuple from individual data items.

Syntax:
Tuple-object = d1,d2,d3,d4,…

Tuple unpacking means create individual data items from tuple

Syntax:
D1,d2,d3,d4, = tuple-data
Practice Programs:

1) Write a program to take a tuple of numbers from the keyboard and print its sum
and average?
2) Write a program find the length of the tuple data.
3) Write a program to add elements into a tuple.
4) Write a program remove all tuples of length K.
5) WAP to create tuple in different ways.
6) WAP to convert a tuple to list without inbuilt function.
7) WAP to add new element into a tuple data.
8) WAP to find repeated items in a tuple data.
9) Write a Python program to unzip a list of tuples into individual lists.
10) Write a Python program to reverse a tuple without inbuilt functions.
11) Write a Python program to count the elements in a list until an element is a
tuple.
12) Write a Python program to calculate the average value of the numbers in a
given tuple of tuples.
Unit-8: Set Operations
Features of set data
Creation of set data
Traversing on set data
Set Comparison
Adding Elements into set data
Set Aliasing
Cloning of set data
Deleting Elements from set data
Set Math Operations
Set Data Operations

Features of Set Data:

 Set is a collection datatype.


 Symbol of notation for set data is: {}. All the elements in {} must be separated
with comma.
ex: {1,3,5,7,9}
 Set is an inbuilt datatype, because it has an inbuilt class: "set".
 Set is not an ordered datatype.
 Set is not a sequential datatype.
 it is not supposed to use an index

Note: if the index is used with set ==> Type Error

 No slicing is possible with set data.


 Set can be homogeneous.
 Set can be heterogeneous.
 No duplication is allowed on set. (no duplication can preserve by the set).
 Set can nest with only tuples.

Note:
 limitation with list, set, dictionary.
 set never be nested with list
Ex: If a set with list data returns "Type Error".
Creation of Set Data:

1) Compile time Definition of Set Data:

Syntax:
Set-data-object = {d1, d2, d3, d4, d5, …}

2) Run time Definition of Set Data:

To define the set in run time which can dynamically change “eval()” method can use.

Syntax:
eval(input(“Enter the Set data:”))

3) Using set():

set() is an inbuilt method which we can use to create a set data from any collection
(means to convert any collection data to set data, set() method can use).

Syntax:
Set-data-object = set()  for an empty set creation
Set-data-object = set(any collection data)
Traversing on Set Data:

Using for loop:

Syntax:
for loop-variable in set-data:
block of code
Set Comparison:

Set comparison with ‘==’ and ‘!=’:

 These operators can check lengths of the both sets.


 if both lengths are same (equal) then: individual element comparison should take.

Set comparison with ‘<’, ‘>’, ‘<=’ and ‘>=’:

 Set comparison should be based on individual elements of sets only.


Adding of Elements into Set Data:

1) add():

add() is an inbuilt method which can add an element/item (only one at a time) to the
set.

Syntax:
add(element/item)

2) update():

update() is an inbuilt method which can use to add more than one item/element to
the set.
Syntax:
Set-data-object.update(collection data)

Set Aliasing:

Assigning the same set data to two or more set objects using assignment
operator is called as set aliasing. In this case, if any change at any set object can
reflect on other set data automatically.

Set cloning:

To avoid the issue of set aliasing, set cloning can be used.


copy():

Syntax:
New set-data-object = Old-set-data-object.copy()

Remove Elements from Set Data:

1) pop():

It is an inbuilt method which we can use to remove/delete an item/element of any


from the set.

Syntax:
Set-data-object.pop()

Note:
 pop() can delete an element from set randomly.
2) remove():

remove() is an inbuilt method which we can use to remove/delete any specified


element from the given set.

Syntax:
Set-data-object.remove(element)

Note:
 if the specified element is not in the set, then: remove() can return "Key Error".

3) discard():

dicard() is an inbuilt method which we can use to remove the specified element from
the given set data.
Syntax:
Set-data-object.discard(element)

Note:
 if the specified element is not known to the set, then: discard() not return any
error.

4) del:

del is a property which we can use to delete the entire set permanently.

Syntax:

del set-data-object

5) clear():

to clear whole set by making an empty, we can use clear().


Syntax:
Set-data-object.clear()

Set Math Operations:

1) Set Union:

Joining of two sets into one by eliminating common elements from set2.

union():

Syntax:
Set-object1.union(set-object2)

2) Set Intersection:

Set Intersection can create a new set with only common elements from both the
sets.
intersection():

Syntax:
Set-object1.intersection(set-object2)

3) Set Difference:

Set difference can return a set with elements from only the first set.

difference():

Syntax:
Set-object1.difference(set-object2)

4) Set Symmetric Difference:


This can return a new set with elements which are in only first set and only in second
set.

symmetric_difference():

Syntax:
Set-object1.symmetric_difference(set-object2)

Practice Programs:

1) Write a program to eliminate duplicates present in the list?


2) Write a program to print different vowels present in the given word?
3) Write a Python program to add member(s) to a set.
4) Write a Python program to remove item(s) from a given set.
5) Write a Python program to check if a set is a subset of another set.
6) Write a Python program to create a shallow copy of sets.
7) Write a Python program to iterate over sets.
8) Write a Python program to add member(s) to a set.
9) Write a Python program to remove an item from a set if it is present in the set.
10) Write a Python program to check if a set is a subset of another set.
11) Write a Python program to create a shallow copy of sets.
12) Write a Python program to remove all elements from a given set.
13) Write a Python program that uses frozensets.
14) Write a Python program to check if a given value is present in a set or not.
15) Write a Python program to find the third largest number from a given list of
numbers. Use the Python set data type.
Unit-8: Dictionary Operations

What is Dictionary Data?


Features of Dictionary Data
Creation of Dictionary Data
Properties of Dictionary Keys
Accessing values in Dictionary
Updating Dictionary Data
Deleting Dictionary Elements
Traversing on Dictionary Data
Dictionary Data Operations
What is Dictionary Data?

Dictionary in Python is one of the most popular data structures. They are used to store
data in a key-value pair format. The keys are always unique within a dictionary and are
the attribute that helps us locate the data in the memory. The values of the Python
dictionary may or may not be unique. The values within a dictionary can be of any data
type, but the thing to note is that the keys are immutable. Hence, the key can only be
strings, numbers or tuples.

Ex: my_dictionary = {‘a’ : 111, ‘b’ : 222, ‘c’ : 333}

 The keys must be only a single element.


 The keys are case-sensitive, i.e. the same name in either uppercase or
lowercase will be treated differently.

Features of Dictionary Data:

 We can use List, Tuple and Set to represent a group of individual objects as a
single entity.
 If we want to represent a group of objects as key-value pairs then we should go
for Dictionary.
 Dictionary data is an inbuilt datatype because in python there is an inbuilt class
named as “dict”.
 Duplicate keys are not allowed but values can be duplicated.
 To access the values from the dictionary, “keys” can be used.
 Heterogeneous objects are allowed for both key and values.
 insertion order is not preserved.
 Dictionaries are mutable.
 Dictionaries are not support with dynamic indexing and slicing concepts.
Creating a Dictionary Data:

Compile Time Definition:

To create a Python dictionary is as simple as placing the required key and value pairs
within a curly bracket “{}”. A colon separates the key-value pair “:”. When there are
multiple key-value pairs, they are separated by a comma “,”

Syntax:
Dictionary-object = {key1 : value1, key2 : value2, key3 : value3}

Run Time Definition:

To define the dictionary data in run time which can dynamically change “eval()” method
can use.

eval():

Syntax:
eval(input(“Enter the Dictionary Data:”))
Using dict() method:

dict() is an inbuilt method which we can use to create the dictionary data.
Syntax:
dict({key : value1, key2 : value2, key3 : value3})

Properties of Dictionary Keys:

 Duplicate keys are not allowed. When duplicate keys are encountered in Python,
the last assignment is the one that wins.
 Keys are immutable- they can only be numbers, strings or tuples.

Accessing of Values of Dictionary Data:

Using keys:

Syntax:
Dictionary-object[key]
Note:
 If we tried to reference a key that is not present in our Python dictionary, we
would get the “key error”.

Write a program to enter name and percentage marks in a dictionary and display
information on the screen.

Updating Dictionary Data:

We can do multiple things when trying to update a dictionary in Python. Some of them
are:
1. Add a new entry.
2. Modify an existing entry.
3. Adding multiple values to a single key.
4. Adding a nested key.
Deleting Dictionary Data:

del:

 To remove an entire dictionary in Python, we use the “del” keyword.

clear():

To clear the dictionary data, clear() method can be used.

Syntax:
Dictionary-object.clear()
Dictionary Operations:

len():
 len() is an inbuilt method which we can use to find the length of any collection
data.

Syntax:
len(dictionary-object)

Finding length using loop:

Getting individual Values from the Dictionary:

Way_01: Using Dictionary Key:

Syntax:
Dictionary-name[key-name]
Way_02: Using get() Method:

Syntax:
Dictionary-name.get(key-name)

 If the specified key is in the dictionary, associated value can be returned by the
get().
 If the specified key is not in the dictionary, then the get() can return “None”.
 To return some “default value” when the specified key is not in the dictionary, we
can use:

Syntax:
Dictionary-name.get(key-name, default-value)

Getting all keys from the Dictionary:

keys():

keys() is an inbuilt method which can use to get all the keys from the given dictionary.

Syntax:
Dictionary-name.keys()
Getting all values from the Dictionary:

Values():

Values() is an inbuilt method which we can use to get all the values from the dictionary.

Syntax:
Dictionary-name.values()
Getting both keys and values in arbitrary from the dictionary:

Items():

Items() is an inbuilt method which can be used to get all the items (key : value) from the
given dictionary.

Syntax:
Dictionary-name.items()

Aliasing of Dictionary:

Dictionary aliasing can be represented using an assignment operator (=).


Cloning of Dictionary:

Using copy():

Copy() it is an inbuilt method which we can use to create a new dictionary from another
dictionary.

Syntax:
New-dictionary-name = old-dictionary-name.copy()
Comprehensions:

Comprehensions are very easy and compact way to create collection objects like: list,
set, dictionary from any iterable object like: range(), list, tuple etc. based on some
condition.

List Comprehension:

Syntax:
identifier = [condition for lv in collection/range]

Tuple Comprehension:

Tuple Comprehension is not possible in python.


Set Comprehension:

Syntax:
identifier = {condition for lv in collection/range}

Dictionary Comprehension:

Syntax:
identifier = {key : value for condition for lv in collection/range}

Practice Programs:

1) Write a program to enter name and percentage marks in a dictionary and display
information on the screen.
2) Write a program to take dictionary from the keyboard and print the sum of
values?
3) Write a program to find number of occurrences of each letter present in the given
string?
4) Write a program to find number of occurrences of each vowel present in the
given string?
5) Write a program to accept student name and marks from the keyboard and
creates a dictionary. Also display student marks by taking student name as
input?
Unit-10: Functions

What is function?
Function definition
Function call
Types of Functions
Returning multiple values
Types of arguments
Scope of Variables
Recursion
Passing collection to function
Function within the function
Passing a function as an argument to function
Pass by Reference and Pass by Value
Returning of Collection from function
Anonymous function
Function Aliasing
Function Decorators
Function Generators
Functions
What is function?

Functions are modular blocks of code designed to perform specific tasks. They
enhance code efficiency and clarity by reducing code repetition and enabling code
reuse.

Python primarily categorizes functions into two types:


1. Built-in Functions: These are predefined functions in Python that are readily
available for use. Examples include len(), range(), and abs().
2. User-defined Functions: As the name suggests, these are the functions defined
by the users to perform specific tasks.

Advantages:
1) solving the complex or larger programs easily.
2) debugging the application is easy.

Function Definition:

In Python, a function is declared using the keyword def, succeeded by the name of the
function and enclosed parentheses, which may enclose parameters.

Syntax:
def functions-name(parameters/arguments):
Function body
block of statements

 Function-name: This is the identifier for the function. It follows the same naming
conventions as variables in Python. The function name should be descriptive
enough to indicate what the function does.
 Parameters (Optional): These are variables that accept values passed into the
function. Parameters are optional; a function may have none. Inside the function,
parameters behave like local variables.
 Function Body: This block of code performs a specific task. It starts with a colon
(:) and is indented. The function body typically contains at least one statement.
The return statement can be used to send back a result from the function to the
caller. None is returned if no return statement is used.

Creating of Function:
Calling of Function:

A function in Python is called by using its name followed by parentheses. In case


parameters are present, these are included in the parentheses.

Syntax:
Function-name(values for parameters)

Types of Functions:

1) Function without Parameters and no Return type

Syntax:
def function-name():
function-body
2) Function without Parameters and Return type

Syntax:
def function-name():
function-body
return
3) Function with Parameters and no Return type

Syntax:
def function-name(parameters):
function body
4) Function with Parameters and Return type

Syntax:
def function-name(parameters):
function-body
return
RETURNING MULTIPLE VALUES FROM FUNCTION:

Types of Arguments:

1. Positional Arguments:

These are the most common arguments, where the argument's value is based on its
position. For example, in func(a, b), a and b are positional arguments.
2. Keyword Arguments:

The parameter name identifies these and can be supplied in any order, making your
code more readable. For instance, func(a=1, b=2) explicitly states which parameter each
argument corresponds to.

3. Default Arguments:

A parameter with a default value can be omitted in the function call. The function will
then use the default value.
4. Variable Length Arguments:

You may need to determine the number of arguments supplied to your function.
Python allows you to handle this with variable-length arguments, defined with an
asterisk *args and **kwargs.

Docstring:

In Python, documentation strings, or docstrings, are literal strings used to document a


Python module, function, class, or method. They are essential for understanding and
maintaining code, as they provide a convenient way of associating documentation with
Python code.

Syntax:
print(function_name.__doc__)
Types of Variables:

There are two types of variables:


1) Local Variables
2) Global Variables

1) Local Variables:

 Local variables are always allowed to define inside the function.


 The scope of the local variables within the same function.

2) Global Variables:

 The variables from outside the function are called as “Global variables”.
 And we can access in anywhere of the program.
Recursion:

A function that calls itself again and again is known as "recursion". And that function is
called as “recursive function”.
Advanced Functions

Passing Collections to a function as an arguments

Passing a string to function:

Syntax:
def function-name(string-data):
function body

Passing a list to function:

Syntax:
def function-name(list-data):
function-body
Passing a tuple to function:

Syntax:
def function-name(tuple-data):
function-body

Passing set data to function:

Syntax:
def function-name(set-data):
function-body

Passing dictionary data to function:

Syntax:
def function-name(dictionary-data):
function-body
Function within another function:

In Python, functions can be defined inside other functions. These nested functions help
organize code into more manageable pieces, encapsulating functionality or creating
closures and decorators. Also called as “Higher Order Functions”.

Passing a function as an argument to function:

Syntax:
def function-name(function-name):
function-body

Pass By Value and Pass By Reference:

Pass By Reference:

 A reference (or pointer) to the actual data is passed in pass-by-reference.


Modifications to the parameter within the function affect the passed argument.
 Python doesn’t strictly follow this but behaves similarly with mutable objects.
When a mutable object is passed, changes to it inside the function are reflected
outside the function.
Pass By Value:

 Pass by value means the actual value is passed. The function works on a copy,
and changes within the function do not affect the original data.
 With immutable objects (like integers and strings), Python's behavior is akin to
pass-by-value. Changes made to an immutable object in a function do not reflect
in the original object.

Returning of collection data from function:

Returning of string from function:


Returning of list from function:

Anonymous Function:

An anonymous in Python is a function that is defined without a name. Unlike functions


defined using the def keyword, these are defined using the lambda keyword and are
hence called lambda functions. They can have 0 or more arguments but only one return
value. The main purpose of anonymous function is just for instant use (i.e., for one time
usage).

Syntax:
lambda arguments: expression

Note:
By using Lambda Functions, we can write very concise code so that readability of the
program will be improved.

The above example as a usually defined function could be written as:


Note:
 Lambda Function internally returns expression value and we are not required to
write return statement explicitly.

Sometimes we can pass function as argument to another function. In such cases


lambda functions are best choice. We can use lambda functions very commonly with
filter(), map() and reduce() functions, because these functions expect function as
argument.

filter():

We can use filter() function to filter values from the given sequence based on some
condition.

Syntax:
filter(function-name, sequence)

here function argument is responsible to perform conditional check sequence can be list
or tuple or string.

map():

For every element present in the given sequence, apply some functionality and
generate new element with the required modification. For this requirement we should go
for map() function. The function can be applied on each element of sequence and
generates new sequence.

Syntax:
map(function-name, sequence)

We can apply map() function on multiple lists also. But make sure all list should have
same length.
reduce():

reduce() function reduces sequence of elements into a single element by applying the
specified function. reduce() function present in functools module and hence we should
write import statement.

Syntax:
reduce(function-name, sequence)

Function Aliasing:

For the existing function we can give another name, which is nothing but function
aliasing.
Function Decorators:

Decorators in Python are functions that takes another function as an argument and
extends its behavior without explicitly modifying it. It is one of the most powerful features
of Python. It has several usages in the real world like logging, debugging,
authentication, measuring execution time, and many more. The main objective of
decorator functions is we can extend the functionality of existing functions without
modifies that function.

Suppose, you have a set of functions and you only want authenticated users to access
them. Therefore, you need to check whether a user is authenticated or not before
proceeding with the rest of the code in the function. One way to do this is by calling a
separate function inside all the functions and using conditional statements. But this will
require us to change the code for each function. A better solution here would be to use
a Decorator. A Decorator is just a function that takes another function as an argument
and extends its behavior without explicitly modifying it. This means that a decorator
adds new functionality to a function. By the end of this article, you will understand what
does "extending a function without actually modifying it" means.

First-class Object:

In Python, a function is treated as a first-class object. This means that a function has all
the rights as any other variable in the language. That's why, we can assign a function to
a variable, pass it to a function or return it from a function. Just like any other variable.
As everything is an object in Python, the names we define are simply identifiers
referencing these objects. Thus, both foo and also_foo points to the same function
object as shown below in the diagram:

Passing a function to another function:

There are multiple use cases for passing a function as an argument to another function
in Python. For instance, passing a key function to sort lists. Decorators also use this technique as
we will see later.

Returning a function from another function:


Returning a function from a function is another technique used by decorators in Python.

Inner Functions:

We can define a function inside other functions. Such functions are called inner
functions or nested functions. Decorators in Python also use inner functions.

Note:
The inner functions are locally scoped to the parent. They are not available outside of
the parent function. If you try calling the first_child outside of the parent body, you will get a Name
Error.

Inner functions can access variables in the outer scope of the enclosing function. This
pattern is known as a Closure.
Decorators function with arguments:

Now that we have the pre-requisite knowledge for understanding decorators, let's go on
to learn about Python decorators. As discussed before, a decorator in Python is used to
modify the behavior of a function without actually changing it.

Syntax:

Function-name = decorator(function-name)

where function-name is the function being decorated and decorator is the function used to
decorate it.
We have two functions here:

 decorator: This is a decorator function, it accepts another function as an argument


and "decorates it" which means that it modifies it in some way and returns the
modified version.
Inside the decorator function, we are defining another inner function called wrapper.
This is the actual function that does the modification by wrapping the passed
function func.
decorator returns the wrapper function.
 say_hello: This is an ordinary function that we need to decorate. Here, all it does is
print a simple statement.

We passed the say_hello function to the decorator function. In effect, the say_hello now points to
the wrapper function returned by the decorator. However, the wrapper function has a reference to the
original say_hello() as func, and calls that function between the two calls to print().

Syntactic Decorator:

The above decorator pattern got popular in the Python community but it was a little
inelegant. We have to write the function name thrice and the decoration gets a bit
hidden below the function definition. Therefore, Python introduced a new way to use decorators
by providing syntactic sugar with the @ symbol.
Syntax:
@decorator
def function-name(arg1, arg2, arg3, ….):
pass

Syntactic sugar is syntax within a programming language that is designed to make


things easier to read or to express.

Preserving original name and Docstring of the decorated function:

In Python, functions have a name attribute and a docstring to help with debugging and
documentation.

Although technically true, this is not what we wanted. As the say_hello now points to
the wrapper function, it is showing its information instead of the original function. To fix this, we need
to use another decorator called wraps on the wrapper function. The wraps decorator is imported from
the in-built functools modules.

 Authorization in Python frameworks like Flask and Django.


 Logging and debugging code.
 Caching return values of a function.
 Validating JSON (JavaScript Object Notation).

Reusing Decorator:

A decorator is just a regular Python function. Hence, we can reuse it to decorate


multiple functions.

Let's create a file called decorators.py with the following code:


do_twice is a simple decorator that calls the decorated function two times. Now, you can
reuse the do_twice decorator any number of times by importing it.
Here's an example:

We imported any used the do_twice decorator on both the functions and called them.
Therefore, we got two outputs for each function.

Returning values form Decorated Functions:

What happens to the returned value from the decorated function? Let's check out
with an example. Consider the following add function, it prints a statement then returns
the sum of the two numbers, we are decorating it with the previously
created do_twice decorator:
The add function was called twice as expected but we got None in the return value. This
is because the wrapper function does not return any value. To fix this, we need to make
sure the wrapper function returns the return value of the decorated function.

Decorators with Arguments:


You can pass arguments to the decorator itself!
All you need to do is define the decorator inside another function that accepts the
arguments and then use those arguments inside the decorator. You also need to return
the decorator from the enclosing function. Let's see what does this means with code to
better understand it. Previously, we created a decorator called do_twice. Now, we will
extend it to repeat any number of times. Let's call this new decorator repeat.

Chaining Decorators:

Chaining the decorators means that we can apply multiple decorators to a single
function. These are also called nesting decorators.
 The first one takes a function that returns a string and then splits it into a list of
words.
 The second one takes a function that returns a string and converts it into
uppercase.

Fancy Decorators:

You need a basic understanding of classes in Python for this section.


Till now, you have seen how to use decorators on functions. You can also use
decorators with classes, these are known as fancy decorators in Python. There are two
possible ways for doing this:
 Decorating the methods of a class.
 Decorating a complete class.

Decorating the methods of a class:

Python provides the following built-in decorators to use with the methods of a class:
 @classmethod: It is used to create methods that are bound to the class and not
the object of the class. It is shared among all the objects of that class. The class
is passed as the first parameter to a class method. Class methods are often used
as factory methods that can create specific instances of the class.

 @staticmethod: Static methods can't modify object state or class state as they
don't have access to cls or self. They are just a part of the class namespace.

 @property: It is used to create getters and setters for class attributes.

We created a class called Browser. The class contains a getter and setter for
the page attribute created with the @property decorator. It contains a class method
called with_incognito which acts as a factory method to create incognito window
objects. It also contains a static method to get the information for the browser which will
be the same for all objects (windows).
Decorating a complete class:

Writing a class decorator is very similar to writing a function decorator. The only
difference is that the decorator will receive a class and not a function as an argument.
Decorating a class does not decorate its methods.

Syntax:
className = decorator(className)

Classes as Decorators:

We can also use a class as a decorator. Classes are the best option to store the state of
some data, so let's understand how to implement a stateful decorator with a class that
will record the number of calls made for a function.
There are two requirements to make a class as a decorator:
 The __init__ function needs to take a function as an argument.
 The class needs to implement the __call__ method. This is required because the
class will be used as a decorator and a decorator must be a callable object.
Also note that we use functools.update_wrapper instead of functools.wraps in case of a
class as a decorator.
Real world usage of Decorators:

One real-world usage of decorators in Python is to measure the execution time of a


function.
Other Use Cases of Decorators:

 Authorization in Python frameworks like Flask and Django.


 Logging and debugging code.
 Caching return values of a function.
 Validating JSON (JavaScript Object Notation).

Generators in Python:

Generators in Python are used to create iterators and return a traversal object. It helps
in traversing all the items one at a time with the help of the keyword yield.

Python's generator functions are used to create iterators(which can be traversed


like list, tuple) and return a traversal object. It helps to transverse all the items one at a
time present in the iterator.

Generator functions are defined as the normal function, but to identify the difference
between the normal function and generator function is that in the normal function, we
use the return keyword to return the values, and in the generator function, instead of
using the return, we use yield to execute our iterator.

In the above example, gen_fun() is a generator function. This function uses


the yield keyword instead of return, and it will return a value whenever it is called.

Yield Vs Return:

Yield Return
It is used in generator functions. It is used in normal functions.
It is responsible for controlling the flow of the
generator function. After returning the value Return statement returns the value and
from yield, it pauses the execution by saving terminates the function.
the states.
Generative Function Vs Decorative Function:

 In generator functions, there are one or more yield functions, whereas, in Normal
functions, there is only one function
 When the generator function is called, the normal function pauses its execution,
and the call is transferred to the generator function.
 Local variables and their states are remembered between successive calls.
 When the generator function is terminated, StopIteration is called automatically
on further calls.

Generators with loops:

The Generator functions are also used for the loop.

The function seq will run 10 times, and when seq is called using next for the 11th time, it
will show an error StopIteration. But when using for loop, instead of next.

It will not show any error. for loop automatically handle the exception statements.
Creation of Generator Function:

In Python, there are some ways to create a generator function.


1. Using a Yield statement
2. Using Python Generator Expression

Yield Statement:

Yield keyword in Python that is used to return from the function without destroying the
state of a local variable. We have already discussed how to create a generator function
using yield.

Python Generator Expression:

Generator Expression is a short-hand form of a generator function. Python provides an


easy and convenient way to implement a Generator Expression. According to its
definition, they are similar to lambda function as lambda function is an anonymous
function, and generator functions are anonymous. But when it comes to implementation,
they are different, they are implemented similarly to list comprehension does, and the
only difference in implementation is, instead of using square brackets('[]'), it uses
round brackets('()'). The main and important difference between list comprehension
and generator expression is list comprehension returns a list of items, whereas
generator expression returns an iterable object.

Uses of Generators:

1. Easy to Implement:

Generator functions are easy to implement as compared with iterators. In iterators, we


have to implement iter(), __next__() function to make our iterator work.
2. Memory Efficient:

Generator Functions are memory efficient, as they save a lot of memory while using
generators. A normal function will return a sequence of items, but before giving the
result, it creates a sequence in memory and then gives us the result, whereas the
generator function produces one output at a time.

3. Infinite Sequence:

We all are familiar that we can't store infinite sequences in a given memory. This is
where generators come into the picture. As generators can only produce one item at a
time, so they can present an infinite stream of data/sequence.

Practice Programs:

1) Write a function to check whether the given number is even or odd?


2) Write a function to find factorial of given number?
3) Write a Python Function to find factorial of given number with recursion.
4) Write a program to create a lambda function to find square of given number?
5) Lambda function to find sum of 2 given numbers
6) Lambda Function to find biggest of given values.
7) Program to filter only even numbers from the list by using filter() function?
8) Write a Python function to check whether a number falls within a given range.
9) Write a Python function that accepts a string and counts the number of upper and
lower case letters.
10) Write a Python function that takes a list and returns a new list with distinct
elements from the first list.
Unit-11: Modules & Packages
What are Modules in Python?
Types of modules
Variables in module
Import statement
Module Aliasing
Reloading a module
The dir() method
Modules search path
Introduction to Packages
Importing a module from package
Installing package globally
Import statement
Importing attributes using the from import statement
Importing modules using the from import * statement
Importing modules in python using import as statement
Importing class/function from module
Import user-defined module
Importing from another directory
Importing class from another file
Modules & Packages
What are Modules in Python?

Modules in Python are the python files containing definitions and statements of the
same. It contains Python Functions, Classes or Variables. Modules in Python are
saved with the extension .py.

Consider a bookstore. In the bookstore, there are a lot of sections like fiction, physics,
finance, language, and a lot more, and in every section, there are over a hundred
books.
In the above example, consider the book store as a folder, the section as
python modules or files, and the books in each section as python functions, classes,
or python variables.

Formal Definition of Module:

Modules in Python can be defined as a Python file that contains


Python definitions and statements. It contains Python code along with
Python functions, classes, and Python variables. The Python modules are files with
the .py extension.

Features of modules:

 Modules provide us the flexibility to organize the code logically. Modules help
break down large programs into small manageable, organized files.
 It provides reusability of code.

Examples for Modules:

Let's create a small module.


 Create a file named example_.py. The file's name is example_.py, but the
module's name is example_.
 Now, in the example_.py file, we will create a function called print_name().

Code(example_.py):
 Now, we have created Python modules example_.
 Now, create a second file at the same location where we have created
our example_ module. Let's name that file as test_.py.

Code(test_.py):

Types of Modules:

There are two types of Python modules:


1. Inbuilt modules in Python
2. User-Defined Modules in Python

Inbuilt Modules:

There are several modules built-in modules available in Python.


Built-In modules like:
 math
 sys
 os
 random and many more.

Working with math module:


Working with Random Module:

This module defines several functions to generate random numbers. We can use these
functions while developing games, in cryptography and to generate random numbers on
fly for authentication.

1. random():

This function always generate some float value between 0 and 1 ( not inclusive).

Syntax:
Import random
Value = randint()

2. ranint():

To generate random integer between two given numbers(inclusive).

Syntax:
randint(n1, n2)
3. uniform():

It returns random float values between 2 given numbers (not inclusive).

Syntax:
uniform(n1, n2)

4. randrange():

returns a random number from range.

Syntax:
randrange(start, stop, step)

5. choice():

It cannot return random number. It will return a random object from the given list or
tuple.

Syntax:
choice(collection)
Variables in Modules

We have already discussed that modules contain functions and classes. But apart from
functions and classes, modules in Python can also contain variables in
them. Variables like tuples, lists, dictionaries, objects, etc.

Let's create one more module variables, and save the .py as variables.py.

Create another Python file, and use the variables module to print the factorial of a
number, print the power of 6, and what is the second alphabet in the alphabet_list.
Import Statement:

The import statement is used to import all the functionality of one module to another.
Here, we must notice that we can use the functionality of any Python source file by
importing that file as the module into another Python source file. We can import multiple
modules with a single import statement, but a module is loaded once regardless of the
number of times it has been imported into our file.

Importing Modules in Python:

For importing modules in Python, we need an import statement to import the modules in
a Python file.

When we are using the import statement to import either built-in modules or user-
defined modules, that states we are importing all the functions/classes/variables
available in that modules. But if we want to import a specific function/class/variable of
that module.

We can import that specific function/class/variable, by using from <module_name>


import <class/function/variable_name> statement then we can import that specific
resource of that module.
Syntax:
from <module_name> import <function_name>, <class_name>,
<function_name2>,<variable_name>

Module Aliasing:

Syntax:
import module-name as new-name

Reloading a Module:

We can import a module only once in a session.

Suppose you are using two modules, variables_ and example_ simultaneously in a
Python file, and the variables_ module is updated while you are using these modules.
You want the updated code of that module, which is updated. Now that we know, we
can import a module in our session only once.
So, we will use the reload function available in the imp module to get the updated
version of our module.

Python Module Search Path:

In the previous sections, we have seen how to import the modules using the import
statement. Now we will see how Python searches for the module.
In Python, when we use the import statement to import the modules. The Python
interpreter looks at the different locations.
After using the import statement to import modules, firstly, the Python interpreter will
check for the built-in modules. If the module is not found, then the Python interpreter will
look for the directories defined in the path sys. path.
The order of search is in the following order:
 At first, the interpreter looks in the current working directory.
 If the module is not found in the current working directory, then the interpreter will
search each directory in the PYTHONPATH environmental variable.
 If now also the module is not found, then it will search in the default installation
directory.

The dir() method:

The dir() is a built-in function returns a sorted list of strings containing the names
defined by a module. The list contains the names of all the classes, variables, and
functions that are defined in a module.

Practice Programs:

1) Write a program to display members of particular module.


2) Write a Python program to generate a random color hex, a random
alphabetical string, random value between two integers (inclusive) and a
random multiple of 7 between 0 and 70.
3) Write a Python program to select a random element from a list, set,
dictionary-value, and file from a directory.
4) Write a Python program that generates random alphabetical characters,
alphabetical strings, and alphabetical strings of a fixed length.
5) Write a Python program to shuffle the elements of a given list.
6) Write a Python program to check if a given value is a method of a user-
defined class.

Packages

Introduction to Packages:

We usually organize our files in different folders and subfolders based on criteria
so that they can be managed quickly and efficiently. A Python module may contain
several classes, functions, variables, etc., whereas a Python package can contain
several modules. In simpler terms, a package is a folder that contains various modules
as files.

The meaning of Packages lies in the word itself. Packages do the work of
organizing files in Python. Physically a package is a folder containing sub-packages or
one or more modules (or files). They provide a well-defined organizational hierarchy
of modules in Python. Packages usually are named such that their usage is apparent to
the user. Python packages ensure modularity by dividing the packages into sub-
packages, making the project easier to manage and conceptually clear.

To better understand what Packages in Python, mean, let’s take an example


from real life. Your family is shifting to a new apartment. Your mom has asked you to
pack your books, CDs, and toys so that it’s easy to unpack and organize them in your
new house. The simplest way to do this would be to pack these items separately into
three unique packages (boxes for CDs, books, and toys, respectively) and name them
based on their utility. Furthermore, you can also add sections to your book package
based on the genre of books. We can do the same thing for CDs and toys as well.

Have you come across this way of organization somewhere? The most common
example would be that of files on your phone. All your files would be saved in a folder
that could further be distinguished based on the source (WhatsApp Documents,
Downloads, etc.).

Every package in Python must contain an __init__.py file since it identifies the
folder as a package. It generally contains the initialization code but may also be left
empty. A possible hierarchical representation of the shifting items package in the first
example can be given below. Here, shifting items is our main package. We further
divide this into three sub packages: books, CDs and toys. Each package and sub
package contains the mandatory __init__.py file. Further, the sub packages contain files
based on their utility. Books contain two files fiction.py and non_fiction.py, the package
CDs contain music.py and dvd.py, and the package toys contain soft_toys.py and
games.py.

Importing a module from package:

Packages help in ensuring the reusability of code. To access any module or file from a
Python package, use an import statement in the Python source file where you want to
access it. Import of modules from Python Packages is done using the dot operator (.).
Importing modules and packages helps us make use of existing functions and code that
can speed up our work.

Syntax:
import module1[, module2,... moduleN]

Where import is a keyword used to import the module, module1 is the module to be
imported. The other modules enclosed in brackets are optional and can be mentioned
only when more than 1 module is to be imported.

Consider the writing package given below.

Where import is a keyword used to import the module, module1 is the module to be
imported. The other modules enclosed in brackets are optional and can be mentioned
only when more than 1 module is to be imported.
Consider the writing package given below.
To access a function called plagiarism_check() of the edit module, you use the following
code:

The calling method seems lengthy and confusing, right? Another way to import a
module would be to simply import the package prefix instead of the whole package and
call the function required directly.

However, the above method may cause problems when 2 or more packages have
similarly named functions, and the call may be ambiguous. Thus, this method is avoided
in most cases.

Installing a package globally:

To ensure system-wide use of the Python package just created, you need to run the
setup script. This script uses the setup() function from the setup tools module. As a
prerequisite, you need to have the latest versions of pip and setup tools installed on
your system. Pip and setup tools are usually installed along with the Python binary
installers. To upgrade the version of pip, use the following command:

Syntax:
python -m pip install --upgrade pip

Once you confirm that you have the latest versions of pip and setup tools installed, you
can create a setup.py file in the main package (Writing) folder. The setup() function that
will be imported here takes various arguments like the package's name, version,
description, author, license, etc. The zip_safe argument is used to know the mode of
storage of the package (compressed or uncompressed).
Now to install the Writing package, open a terminal in your parent package folder
(Writing) and type in the following command:

Syntax:
pip install Writing

The Writing package, which contains functions to assist writing (like count_words which
is used to count the number of words in a string) will now be available for use anywhere
on the system and can be imported using any script or interpreter by using the following
commands:

Import statement:

The files in packages that contain Python code are called modules. Modules are used to
break down large code into smaller and more understandable parts. Commonly used
code (functions) can be written in the form of modules and imported as and when
needed, thus ensuring the reusability of code.

Let’s create a function prod(x,y) to multiply two numbers x and y, which are passed as
arguments to a function, and store it in a module named product.py.
To import the prod function in another module or use it in the interactive interpreter shell
of Python, type:

This statement does not import the module's functions into the symbol table. To access
functions of the given module, we use the dot (.) operator as follows:

Python has a lot of in-built modules which can be accessed in the same way. For
example, to print the value of pi, we can import the math module.

Importing attributes using from import statement:

We can also import individual attributes from the module. This reduces the complexity of
writing the function calls.

Syntax:
from <module_name> import <attribute_name(s)>

In the previous example, we could import pi directly from the math module as follows:

You can import more than one attribute by separating them with commas (,). In the
below example, we import the functions pi, floor (used to find the smallest integer
greater than or equal to the given number) and fabs (used to find the absolute value of a
number) from the math package.
Importing modules using from import * statement:

To import all modules' definitions, use the asterisk (*) operator.

Syntax:
from <module_name> import *

Importing modules using import as statement:

You can alter how a module is called in your program by aliasing it, i.e. giving it another
name. The as operator is used for this purpose.

Syntax:
import <module_name> as <new_module_name>
Importing Class/Function from module:

To import classes or functions from a module in Python, use the following syntax:

Syntax:
from <module_name> import <class_name/function_name>

Example: To import the prod function from the math module, which is used to calculate
the product of 2 given numbers, we import prod specifically as shown. We then can
access prod() directly without using the dot (.) operator.

Import user-defined module:

To import modules defined by the user from different code files, use the following
syntax:
Syntax:
import <user_defined_module_name>

To import the val function in another module or use it in the interactive interpreter shell
of Python, type:

Interview Questions:

1) Write a Python program to generate a random color hex, a random


alphabetical string, random value between two integers (inclusive) and a
random multiple of 7 between 0 and 70. Use random.randint().
2) Write a Python program to select a random element from a list, set,
dictionary-value, and file from a directory. Use random.choice()
3) Write a Python program to construct a seeded random number generator,
also generate a float between 0 and 1, excluding 1. Use random.random()
4) Write a Python program to generate a random integer between 0 and 6 -
excluding 6, random integer between 5 and 10 - excluding 10, random
integer between 0 and 10, with a step of 3 and random date between two
dates. Use random.randrange().
5) Write a Python program to shuffle the elements of a given list. Use
random.shuffle()
6) Write a Python program to check if a given function is a generator or not.
Use types.GeneratorType()
7) Write a Python program to construct a Decimal from a float and a Decimal
from a string. Also represent the decimal value as a tuple.
8) Write a Python program to configure rounding to round up and round down
a given decimal value.
9) Write a Python program to display a given decimal value in scientific
notation.
Unit-12: File Handling
Introduction
Advantages File Handling
Disadvantages of File Handling
Mode of File operations
Opening files
Properties of File Object
Writing data into files
Reading data from files
Closing of File
The with statement
Seek() and tell() methods
Handling of Binary Data
Handling of CSV files
Zipping and Unzipping Files
Pickling and Unpickling of Objects
File Handling
Introduction:

Python file handling is a versatile and powerful mechanism for performing operations on
file. Python file handling allows users to work on different types of files and allows them
to perform different operations on files. File handling is important as it allows us to store
data in file after running the program.

As the part of programming requirement, we have to store our data permanently for
future purpose. For this requirement we should go for files. Files are very common
permanent storage areas to store our data.

There are 2 types of files:

1. Text Files:

Usually, we can use text files to store character data

Ex: any_file.txt

2. Binary Files:
Usually, we can use binary files to store binary data like images, video files, audio
files etc...

Advantages of file handling:

 Versatility: Python file handling allows users to perform a variety of operations


on files like creating, writing, reading, and deleting files.

 Flexibility: Python file handling provides flexibility as it allows to work with


different types of files like binary, text, CSV Files, etc. and allows to perform a
variety of operations.

 User–friendly: Python provides a user-friendly, simple and short way for file
handling.

 Cross-platform: Python file handling can be performed on different platforms


such as Linux, Mac, Windows, etc.

Disadvantages of file handling:

 Error-prone: Python file handling sometimes throws an error when the code is
not written properly or if there is some issue in the file system.

 Security risks: Sometimes there is a security risk in python file handling


especially when the input is taken from the user and it tries to modify and access
the sensitive files of the system.

 Complexity: Python file handling becomes complex while working with


advanced file types and operations.

 Performance: File handling in Python is slow in comparison to file handling of


other programming languages, especially at the time of working with complex
operations and large files.

Opening files:

Before performing any operation (like read or write) on the file, first we have to open that
file. For this we should use Python's inbuilt function open() But at the time of open, we
have to specify mode, which represents the purpose of opening file.

Open():
Syntax:
Open(file-name, mode-name)

In the above code, we have created the object of the file with the name f. This name will
be used further for performing operations on file.

Files will be opened in read mode by default. f = open("example.txt") is equivalent to the


code f = open("example.txt", "r"), in this we have explicitly specified the read mode for
opening the file.

File modes:

r-mode:

open an existing file for read operation. The file pointer is positioned at the beginning of
the file. If the specified file does not exist then we will get FileNotFoundError. This is
default mode.

w-mode:

open an existing file for write operation. If the file already contains some data then it will
be overridden. If the specified file is not already available then this mode will create that
file.

a-mode:

open an existing file for append operation. It won't override existing data. If the specified
file is not already available then this mode will create a new file.

r+-mode:
To read and write data into the file. The previous data in the file will not be deleted. The
file pointer is placed at the beginning of the file.

w+-mode:

To write and read data. It will override existing data.

a+-mode:

To append and read data from the file. It won’t override existing data.

x-mode:

To open a file in exclusive creation mode for write operation. If the file already exists
then we will get FileExistsError.

Properties of file object:

Once we opened a file and we got file object, we can get various details related to that
file by using its properties.

name: return Name of opened file.


mode: This can give mode in which the file is opened.

closed: Returns boolean value indicates that file is closed or not.

readable(): Returns boolean value indicates that whether file is readable or not.

writeable(): Returns boolean value indicates that whether file is writable or not.

Closing of files:

After completing our operations on the file, it is highly recommended to close the file.
For this we have to use close() function.

Syntax:
File-name.close()
Writing data into files:

write():

The write() method is used for writing data into the file, we need to open the file in write
mode for writing data into it, and we need to pass w as the second of the open() method
while writing to the file two things can happen:
 If the file does not exist, then a new file will be created and data will be written
into it.
 If the file already exists, then the whole data of the file will be deleted, and new
content will be inserted into it.

Syntax:
File-object.write(“any text”)

writelines():

Syntax:
File-object.writelines(“lines of text”)
Reading data from the file:

read(): To read total data from the file.

read(n): To read 'n' characters from the file.

readline(): To read only one line.

readlines(): To read all lines into a list.

The ‘with’ statement:

The with statement can be used while opening a file. We can use this to group file
operation statements within a block. The advantage of with statement is it will take care
closing of file, after completing all operations automatically even in the case of
exceptions also, and we are not required to close explicitly.

The seek() and tell() methods:

tell():

We can use tell() method to return current position of the cursor(file pointer) from
beginning of the file. The position(index) of first character in files is zero just like string
index.
Syntax:
File-object.tell()

seek():

We can use seek() method to move cursor(file pointer) to specified location.

Syntax:
File-object.seek(offset, from where)
Here:
offset represents the number of positions
from where:
0---->From beginning of file (default value)
1---->From current position
2--->From end of the file

Note:
Python 2 supports all 3 values but Python 3 supports only zero.

Handling of Binary Data:

It is very common requirement to read or write binary data like images, video files, audio
files etc.

Handling CSV Files:


CSV==>Comma separated values
As the part of programming, it is very common requirement to write and read data with
respect to csv files. Python provides csv module to handle csv files.

Zipping and Unzipping files:

It is very common requirement to zip and unzip files. The main advantages are:
1. To improve memory utilization
2. We can reduce transport time
3. We can improve performance.
To perform zip and unzip operations, Python contains one in-built module zip file. This
module contains a class : ZipFile.

Creating the zip file:

We have to create ZipFile class object with name of the zip file, mode and constant
ZIP_DEFLATED. This constant represents we are creating zip file.

Syntax:
f = ZipFile("files.zip","w","ZIP_DEFLATED")

Once we create ZipFile object, we can add files by using write() method.
Syntax:
Zipfile-object.write(file-name)

Unzip Operation:

Syntax:
f = ZipFile("files.zip","r",ZIP_STORED)

ZIP_STORED represents unzip operation. This is default value and hence we are not
required to specify. Once we created ZipFile object for unzip operation, we can get all
file names present in that zip file by using namelist() method.

Syntax:
Names = file-object.namelist()
Pickling and Unpickling:

Sometimes we have to write total state of object to the file and we have to read total
object from the file. The process of writing state of object to the file is called pickling and
the process of reading state of an object from the file is called unpickling. We can
implement pickling and unpickling by using pickle module of Python. pickle module
contains dump() function to perform pickling.

Syntax:
pickle.dump(object, file)

pickle module contains load() function to perform unpickling.

Syntax:
Object = pickle.load(file)
Unpickling:
Practice Programs:

1) Write a program to read the data from the file.


2) Write a program to only first 10 characters of the file.
3) Write a program to read the data of the file line by line.
4) Write a program to check whether the given file exists or not. If it is available then
print its content?
5) Program to print the number of lines, words and characters present in the given
file?
6) Program to read image file and write to a new image file?
7) Program to read the data from .csv file.
8) Write a program to display all contents of Current working directory including sub
directories.
9) Write a Python program to read last n lines of a file.
10) Write a python program to find the longest words.
11) Write a Python program to count the number of lines in a text file.
12) Write a Python program to count the frequency of words in a file.
13) Write a Python program to copy the contents of a file to another file.
14) Write a Python program to combine each line from first file with the
corresponding line in second file.
15) Write a Python program to read a random line from a file.
Unit-13: Exception Handling
Introduction
What is an Exception?
Common Exceptions
Catching specific Exceptions
Raising Custom Exceptions
Try except and else
Try clause with finally
Types of Exceptions
Exception Handling
Exceptions are errors that are detected during execution. Whenever there is an error in
a program, exceptions are raised. If these exceptions are not handled, it drives the
program into a halt state. Exception handling in python is required to prevent the
program from terminating abruptly. This article will further explain Exception Handling in
Python.

Introduction:

In any programming language there are 2 types of errors are possible.


1. Syntax Errors
2. Runtime Errors

Syntax Error:

The errors which occur because of invalid syntax are called syntax errors.

Note:
Programmer is responsible to correct these syntax errors. Once all syntax errors
are corrected then only program execution will be started.

Run time Error:

Also known as exceptions. While executing the program if something goes wrong
because of end user input or programming logic or memory problems etc., then we will
get Runtime Errors.

print(10/0) ==>ZeroDivisionError: division by zero

Note:
Exception Handling concept applicable for Runtime Errors but not for syntax
errors.

What is an Exception?

An unwanted and unexpected event that disturbs normal flow of program is called
exception.
Ex: ZeroDivisionError, TypeError, ValueError, FileNotFoundError, EOFError,
SleepingError, TyrePuncturedError
It is highly recommended to handle exceptions. The main objective of exception
handling is Graceful Termination of the program (i.e., we should not block our resources
and we should not miss anything) Exception handling does not mean repairing
exception. We have to define alternative way to continue rest of the program normally.

Default Exception:

Every exception in Python is an object. For every exception type the corresponding
classes are available. Whenever an exception occurs PVM will create the
corresponding exception object and will check for handling code. If handling code is not
available then Python interpreter terminates the program abnormally and prints
corresponding exception information to the console. The rest of the program won't be
executed.

Exception Hierarchy:

Every Exception in Python is a class. All exception classes are child classes of
BaseException. i.e., every exception class extends BaseException either directly or
indirectly. Hence BaseException acts as root for Python Exception Hierarchy. Most of
the times being a programmer we have to concentrate Exception and its child classes.

Customized Exceptions:

It is highly recommended to handle exceptions. The code which may raise exception is
called risky code and we have to take risky code inside try block. The corresponding
handling code we have to take inside except block.

Try with multiple exceptions:

The way of handling exception is varied from exception to exception. Hence for every
exception type a separate except block we have to provide. i.e., try with multiple except
blocks is possible and recommended to use.

If try with multiple except blocks available then based on raised exception the
corresponding except block will be executed.

Single Except block that can handle multiple exceptions:


Syntax:
except (Exception1,Exception2,exception3,..) as msg :

Default Except Block:

We can use default except block to handle any type of exceptions. In default except
block generally we can print normal error messages.

Syntax:
except:
statements

Finally Block:

1. It is not recommended to maintain clean up code (Resource Deallocating Code


or Resource Releasing code) inside try block because there is no guarantee for
the execution of every statement inside try block always.
2. It is not recommended to maintain clean up code inside except block, because if
there is no exception then except block won't be executed.
Hence, we required some place to maintain clean up code which should be executed
always irrespective of whether exception raised or not raised and whether exception
handled or not handled. Such type of best place is nothing but finally block. Hence the
main purpose of finally block is to maintain clean up code.

Syntax:
try:
Risky Code
except:
Handling Code
finally:
Cleanup code

Types of Exceptions:

In Python there are 2 types of exceptions are possible.


1. Predefined Exceptions
2. User Defined Exceptions

Pre-defined Exceptions:

Also known as in-built exceptions. The exceptions which are raised automatically by
Python virtual machine whenever a particular event occurs, are called pre-defined
exceptions.

Ex: Whenever we are trying to perform Division by zero, automatically Python will raise
ZeroDivisionError. print(10/0)

User Defined Exceptions:


Also known as Customized Exceptions or Programmatic Exceptions Some time we
have to define and raise exceptions explicitly to indicate that something goes wrong,
such type of exceptions is called User Defined Exceptions or Customized Exceptions
Programmer is responsible to define these exceptions and Python not having any idea
about these. Hence, we have to raise explicitly based on our requirement by using
"raise" keyword.

Ex:
InSufficientFundsException
InvalidInputException
TooYoungException
TooOldException

Interview Questions:

1) Write a Python program to handle a ZeroDivisionError exception when


dividing a number by zero.
2) Write a Python program that prompts the user to input an integer and
raises a ValueError exception if the input is not a valid integer.
3) Write a Python program that opens a file and handles a FileNotFoundError
exception if the file does not exist.
4) Write a Python program that prompts the user to input two numbers and
raises a TypeError exception if the inputs are not numerical.
5) Write a Python program that prompts the user to input a number and
handles a KeyboardInterrupt exception if the user cancels the input.
6) Write a Python program that executes an operation on a list and handles
an IndexError exception if the index is out of range.
7) Write a Python program that executes a list operation and handles an
AttributeError exception if the attribute does not exist.
8) Write a Python program that executes division and handles an
ArithmeticError exception if there is an arithmetic error.
9) Write a Python program that prompts the user to input a number and
handles a KeyboardInterrupt exception if the user cancels the input.
Unit-14: Logging and Debugging
Introduction To Logging
How to Implement Logging
How to write Python program exceptions to the log file
Debugging by using assertions
Types of Assert Statements
Exception Handling Vs Assertion
Logging and Debugging

Introduction to Logging:

Logging is widely used in the software development process and software testing for
debugging and future testing. Python logging is a built-in module that is used to store
the log messages generated by Python programs into a file. The Python logging module
contains several functions and methods that are used to log several events. We can use
various methods to detect the error causing part in program execution and the exact
problem. For logging a program, we first import the module, and then the logger must
be configured. Finally, we can create an object of the logger and start using various
methods.

what is logging?

Logging refers to tracking the events that occur when we run a particular program or
software so that we can use the data for further improvement or error checking. Let us
learn about Python logging.

Python logging is a built-in module that comes with a Python interpreter. We can use
the Python logging module to store the log messages generated by Python programs
(or software working with Python frameworks) into a file. Logging is widely used in the
software development process and software testing process where developers log the
running process of the program for debugging and future testing. We can store the log
results in a file and can use it as a reference for other programs as well.

To understand the need for logging, let us suppose a situation where there is nothing
like logging. We have developed a program having a large code base but it is crashing
due to some reason that we need to find. Since the program is pretty large, we need to
check every step of the program and this can be pretty hectic. We may not even get the
exact reason for the problem. In such scenarios, we use something like a logging tool
that will trace the entire program execution and store it in a file so that we can refer to
the file and get the exact problem. Logging saves us time as well because debugging is
a time-consuming process.

The main advantages of logging are:


1. We can use log files while performing debugging
2. We can provide statistics like number of requests per day etc.,

To implement logging, Python provides one inbuilt module logging.


Logging Levels:

Depending on type of information, logging data is divided according to the following 6


levels in Python.
1. Critical: Represents a very serious problem that needs high attention.
2. Error: Represents a serious error.
3. Warning: Represents a warning message, some caution needed. It is alert to the
programmer
4. Info: Represents a message with some important information
5. Debug: Represents a message with debugging information.
6. Notset: Represents that the level is not set.

By default, while executing Python program only WARNING and higher-level messages
will be displayed.

How to implement Logging?

To perform logging, first we required to create a file to store messages and we have to
specify which level messages we have to store. We can do this by using basicConfig()
function of logging module.

Syntax:

logging.basicConfig(filename='log.txt',level=logging.WARNING)

The above line will create a file log.txt and we can store either WARNING level or
higher-level messages to that file. After creating log file, we can write messages to that
file by using the following methods.

logging.debug(message)
logging.info(message)
logging. Warning(message)
logging.error(message)
logging.critical(message)
How to write Python program exceptions to the log file:

By using the following function we can write exceptions information to the log file.

Syntax:
logging.exception(msg)

Debugging by using assertions:


Debugging Python Program by using assert keyword:

The process of identifying and fixing the bug is called debugging. Very common way of
debugging is to use print() statement. But the problem with the print() statement is after
fixing the bug, compulsory we have to delete the extra added print() statements,
otherwise these will be executed at runtime which creates performance problems and
disturbs console output. To overcome this problem we should go for assert statement.
The main advantage of assert statement over print() statement is after fixing bug we are
not required to delete assert statements. Based on our requirement we can enable or
disable assert statements. Hence the main purpose of assertions is to perform
debugging. Usually we can perform debugging either in development or in test
environments but not in production environment. Hence assertions concept is applicable
only for dev and test environments but not for production environment.

Types of Assert statements:

There are 2 types of assert statements:


1. Simple Version
2. Augmented Version

Simple Version:

Syntax:
assert conditional_expression

Augmented Version:

Syntax:
assert conditional_expression, message

Here:
conditional_expression will be evaluated and if it is true then the program will be
continued.

If it is false then the program will be terminated by raising AssertionError. By seeing


AssertionError, programmer can analyze the code and can fix the problem.
Exception Handling vs Assertions:

Assertions concept can be used to alert programmer to resolve development time


errors. Exception Handling can be used to handle runtime errors.

Unit-15: OOP Concepts

Introduction
OOPs Concepts
Benefits of OOPs
Class and Object
__init__() Method
Types of Attributes
Instance Methods
OOPs Concepts
Inheritance
super() method
Polymorphism
Encapsulation
Access Modifiers
Abstraction
Object Oriented Programming
Introduction:

OOPS concepts in Python are very closely related to our real world, where we write
programs to solve our problems. Solving any problem by creating objects is the most
popular approach in programming. This approach is termed as Object Oriented
Programming. Object-oriented programming maps our code instructions with real-
world problems, making it easier to write and simpler to understand. They map real-
world entities (such as companies and employees) as 'software objects' that have some
'data' associated with them and can perform some 'functions'.

OOPs Concepts in Python:

OOPS in programming stand for Object Oriented Programming System. It is a


programming paradigm or methodology, to design a program using classes and
objects OOPS treats every entity as an object. Object-oriented programming in Python
is centered around objects. Any code written using OOPS is to solve our problem but is
represented in the form of Objects. We can create as many objects as we want, for a
given class. So, what are objects? Objects are anything that has properties and some
behaviors. The properties of objects are often referred to as variables of the object, and
behaviors are referred to as the functions of the objects. Objects can be real-life or
logical.
Suppose, a Pen is a real-life object. The property of a pen includes its color, and type
(gel pen or ball pen). And, the behavior of the pen may include that, it can write, draw,
etc.
Any file in your system is an example of a logical object. Files have properties
like file_name, file_location, file_size and their behaviors include they can hold data, can
be downloaded, shared, etc.

Benefits of OOPs:

1. They reduce the redundancy of the code by writing clear and reusable codes
(using inheritance).
2. They are easier to visualize because they completely relate to real-world
scenarios. For example, the concept of objects, inheritance, and abstractions,
relate very closely to real-world scenarios.
3. Every object in OOPS represent a different part of the code and has its own logic
and data to communicate with each other. So, there are no complications in the
code.

Class and Objects:

Suppose you wish to store the number of books you have, you can simply do that by
using a variable. Or, say you want to calculate the sum of 5 numbers and store it in a
variable, well, that can be done too! Primitive data structures like numbers, strings, and
lists are designed to store simple values in a variable. Suppose, your name, or square
of a number, or count of some marbles (say). But what if you need to store the details of
all the Employees in your company? For example, you may try to store every employee
in a list, you may later be confused about which index of the list represents what details
of the employee (e.g. which is the name field, or the empID etc.)

Even if you try to store them in a dictionary, after an extent, the whole codebase will be
too complex to handle. So, in these scenarios, we use Classes in python. A class is
used to create user-defined data structures in Python. Classes define functions, which
are termed methods, that describe the behaviors and actions that an object created
from a class can perform. OOPS concepts in Python majorly deal with classes and
objects. Classes make the code more manageable by avoiding complex codebases. It
does so, by creating a blueprint or a design of how anything should be defined. It
defines what properties or functions, any object which is derived from the class should
have.

Note:

A class just defines the structure of how anything should look. It does not point to
anything or anyone in particular. For example, say, HUMAN is a class, which has suppose --
name, age, gender, city. It does not point to any specific HUMAN out there, but yes, it explains the
properties and functions any HUMAN should or any object of class HUMAN should have.

An instance of a class is called the object. It is the implementation of the class and
exists in real. An object is a collection of data (variables) and methods (functions) that
access the data. It is the real implementation of a class.

Consider this example, here Human is a class - It is just a blueprint that defines
how Human should be, and not a real implementation. You may say that "Human" class
just exists logically.

However, "Ron" is an object of the Human class (please refer to the image given above
for understanding). That means, Ron is created by using the blueprint of
the Human class, and it contains the real data. "Ron" exists physically,
unlike "Human" (which just exists logically). He exists in real, and implements all
the properties of the class Human, such as, Ron have a name, he is 15 years old, he is
a male, and lives in Delhi. Also, Ron implements all the methods of Human class,
suppose, Ron can walk, speak, eat, and sleep. And many humans can be created using
the blueprint of class Human. Such as, we may create 1000s of more humans by
referring to the blueprint of the class Human, using objects.

Note:
class = blueprint (suppose an architectural drawing). The Object is an actual thing that
is built based on the ‘blueprint’ (suppose a house). An instance is a virtual copy (but not
a real copy) of the object.

When a class is defined, only the blueprint of the object is created, and no memory is
allocated to the class. Memory allocation occurs only when the object or instance is
created. The object or instance contains real data or information.

Class Definition:

Classes in Python can be defined by the keyword class, which is followed by the name
of the class and a colon.

Syntax:
class Name-Of-Class:
implementation of Class

Indented code below the class definition is considered part of the class body.

'pass' is commonly used as a placeholder, in the place of code whose implementation


we may skip for the time being. "pass" allows us to run the code without throwing an
error in Python.

__init_ _() method:

The properties that all Human objects must have been defined in a method called init(). Every
time a new Human object is created, __init__() sets the initial state of the object by
assigning the values we provide inside the object’s properties. That
is, __init__() initializes each new instance of the class.

__init__() can take any number of parameters, but the first parameter is always a
variable called self.

The self parameter is a reference to the current instance of the class. It means,
the self parameter points to the address of the current object of a class, allowing us to access the data of
its(the object's) variables.
So, even if we have 1000 instances (objects) of a class, we can always get each of their individual
data due to this self because it will point to the address of that particular object and return the
respective value.

Note:

We can use any name in place of self, but it has to be the first parameter of any function in the
class.

Types of Attributes:

There are 2 types of attributes in Python:

1. Class Attribute:

These are the variables that are the same for all instances of the class. They do not
have new values for each new instance created. They are defined just below the
class definition.

2. Instance Attribute:

Instance attributes are the variables that are defined inside of any function in class.
Instance attributes have different values for every instance of the class. These
values depend upon the value we pass while creating the instance.
Object Creation:

When we create a new object from a class, it is called instantiating an object. An object
can be instantiated by the class name followed by the parentheses. We can assign the object of a class
to any variable.

Syntax:
Identifier-for-Object = ClassName()

As soon as an object is instantiated, memory is allocated to them. So, if we compare 2


instances of the same class using '==', it will return false(because both will have
different memory assigned).

Note:

If we do not pass the required arguments, it will throw a TypeError: TypeError: init()
missing 3 required positional arguments: 'name', 'age', and 'gender'.
However, we can change the value of class attributes, by
assigning classname.classAttribute with any new value.
Instance Methods:

An instance method is a function defined within a class that can be called only from
instances of that class. Like init(), an instance method's first parameter is always self.
OOPs Concepts:

There are four fundamental concepts of Object-oriented programming:

1. Inheritance
2. Encapsulation
3. Polymorphism
4. Data abstraction

Inheritance:

People often say to newborn babies that they have got similar facial features to their
parents, or that they have inherited certain features from their parents. It is likely that
you too have noticed that you have inherited some or the other features from your
parents.

Inheritance too is very similar to the real-life scenario. But here, the " child classes" inherit
features from their "parent classes." And the features they inherit here are termed as "properties" and
"methods"!

Inheritance is the process by which a class can inherit or derive the properties(or data)
and methods(or functions) of another class. Simply, the process of inheriting the
properties of a parent class into a child class is known as inheritance.

The class whose properties are inherited is the Parent class, and the class that inherits the
properties from the Parent class is the Child class.

So, we define a normal class as we were defining in our previous examples. Then, we
can define the child class and mention the parent class name, which it is inheriting in
parentheses.
Let's see the issue we face if we are trying to call child class's methods using parent
class's object:

So, here we get the AttributeError: 'Human' object has no attribute 'schoolName'. Because the
child classes can access the data and properties of parent class but vice versa is not possible.

super() method:

The super() function in python is a inheritance-related function that refers to the parent
class. We can use it to find the method with a particular name in an object’s superclass.
It is a very useful function.
Syntax:
super().methodName()

Polymorphism:

Suppose, you are scrolling through your Instagram feeds on your phone. You suddenly
felt like listening to some music as well, so you opened Spotify and started playing your
favorite song. Then, after a while, you got a call, so you paused all the background
activities you were doing, to answer it. It was your friend's call, asking you to text the
phone number of some person. So, you messaged him the number, and resumed your
activities.

Did you notice one thing? You could scroll through feeds, listen to music, attend/make
phone calls, message -- everything just with a single device - your Mobile Phone! Whoa!

So, Polymorphism is something similar to that. 'Poly' means multiple and 'morph' means
forms. So, polymorphism altogether means something that has multiple forms. Or, 'some thing' that can
have multiple behaviors depending upon the situation.

Polymorphism in OOPS refers to the functions having the same names but carrying
different functionalities. Or, having the same function name, but different function
signature (parameters passed to the function).

A child class inherits all properties from its parent class methods. But sometimes, it
wants to add its own implementation to the methods. There are ample of ways we can
use polymorphism in Python.

Inbuilt Polymorphic Functions:


len() is an example of inbuilt polymorphic function. Because, we can use it to calculate
the length of various types like string, list, tuple or dictionary, it will just compute the
result and return.

We also have polymorphism with the '+' addition operator. We can use it to 'add'
integers or floats or any arithmetic addition operation. In the other hand, with String, it
performs the 'concatenation' operation.

Polymorphism with Class methods:


Polymorphism with Inheritance:

We can have polymorphism with inheritance as well. It is possible to modify a method in


a child class that it has inherited from the parent class, adding its own implementation to
the method. This process of re-implementing a method in the child class is known
as Method Overriding in Python.
Encapsulation:

You must have seen medicine capsules, where all the medicines remain enclosed
inside the cover of the capsule. Basically, a capsule encapsulates several combinations
of medicine.

Similarly, in programming, the variables and the methods remain enclosed inside a
capsule called the 'class'! Yes, we have learned a lot about classes in Python and we
already know that all the variables and functions we create in OOP remain inside the class.
The process of binding data and corresponding methods (behavior) together into a
single unit is called encapsulation in Python.

In other words, encapsulation is a programming technique that binds the class members
(variables and methods) together and prevents them from being accessed by other
classes. It is one of the concepts of OOPS in Python.

Encapsulation is a way to ensure security. It hides the data from the access of outsiders. An
organization can protect its object/information against unwanted access by clients or any unauthorized
person by encapsulating it.

Getters and Setters:

We mainly use encapsulation for Data Hiding. We do so by defining getter and setter methods
for our classes. If anyone wants some data, they can only get it by calling the getter method. And, if they
want to set some value to the data, they must use the setter method for that, otherwise, they won't be
able to do the same. But internally, how these getter and setter methods are performed remains hidden
from the outside world.
Access Modifiers:

Access modifiers limit access to the variables and methods of a class. Python
provides three types of access modifiers private, public, and protected.

In Python, we don’t have direct access modifiers like public, private, and protected. We
can achieve this by using single underscore and double underscores.

 Public Member: Accessible anywhere from outside the class.


 Private Member: Accessible only within the class
 Protected Member: Accessible within the class and it's sub-classes

Single underscore _ represents Protected class. Double underscore __ represents


Private class.

We can access private members from outside of a class by creating public method to access
private members (just like we did above). There is one more method to get access called name
mangling.

A protected data member is used when inheritance is used and you want the data members to have
access only to the child classes.

So, encapsulation protects an object from unauthorized access. It allows private and
protected access levels to prevent accidental data modification.

Abstraction:

It is likely that you are reading this article on your laptop, phone, or tablet. You are also
probably making notes, and highlighting important points, and you may be saving some
points in your internal files while reading it. As you read this, all you see before you is a
'screen' and all this data that is shown to you. As you type, all you see are the keys on
the keyboard and you don't have to worry about the internal details, like how pressing a
key may lead to displaying that word onscreen. Or, how clicking on a button on your
screen could open a new tab! So, everything we can see here is at an abstract level. We are not
able to see the internal details, but just the result it is producing (which actually matters to us).

Abstraction in a similar way just shows us the functionalities anything holds, hiding all
the implementations or inner details.

The main goal of Abstraction is to hide background details or any unnecessary implementation
about the data so that users only see the required information. It helps in handling the complexity of the
codes.

Key Points Abstract Class:

 Abstraction is used for hiding the background details or any unnecessary


implementation of the data, so that users only see the required information.
 In Python, abstraction can be achieved by using abstract classes
 A class that consists of one or more abstract methods is called the "abstract
class".
 Abstract methods do not contain any implementation of their own.
 Abstract class can be inherited by any subclass. The subclasses that inherit
the abstract classes provide the implementations for their abstract methods.
 Abstract classes can act like blueprint to other classes, which are useful when
we are designing large functions. And the subclass which inherits them can refer
to the abstract methods for implementing the features.
 Python provides the abc module to use the abstraction.

Syntax:
from abc import ABC
class ClassName(ABC):

ABC stands for Abstract Base class. The abc module provides the base for defining
Abstract Base classes (ABC).
Note:

1. Abstract classes cannot be instantiated. In simple words, we cannot create


objects for the abstract classes.
2. An Abstract class can contain the both types of methods -- normal and abstract
method. In the abstract methods, we do not provide any definition or code. But in
the normal methods, we provide the implementation of the code needed for the
method.

Advantages of OOPs:

There are numerous advantages of OOPS concepts in Python, making it favorable for
writing serious software’s.

1. Effective problem solving because, for each mini-problem, we write a class that
does what is required. And then we can reuse those classes, which makes it
even quicker to solve the next problem.
2. Flexibility of having multiple forms of a single class, through polymorphism
3. Reduced high complexity of code, through abstraction.
4. High security and data privacy through encapsulation.
5. Reuse of code, by the child class inheriting properties of parent class through
inheritance.
6. Modularity of code allows us to do easy debugging, instead of looking into
hundreds of lines of code to find a single issue.

Practice Programs:

1) Write a Python program to create a class representing a Circle. Include methods


to calculate its area and perimeter.
2) Write a Python program to create a person class. Include attributes like name,
country and date of birth. Implement a method to determine the person's age.
3) Write a Python program to create a class that represents a shape. Include
methods to calculate its area and perimeter. Implement subclasses for different
shapes like circle, triangle, and square.
4) Write a Python program to create a class representing a stack data structure.
Include methods for pushing and popping elements.
5) Write a Python program to create a class representing a bank. Include methods
for managing customer accounts and transactions.
6) what is the need of OOPs?
7) Write a Python program to create a class representing a shopping cart. Include
methods for adding and removing items, and calculating the total price.
8) Write a Python program to create a class representing a stack data structure.
Include methods for pushing, popping and displaying elements.
9) Write a Python program to create a class representing a bank. Include methods
for managing customer accounts and transactions.
Unit-16: Regular Expressions
Introduction
RegEx Module
RegEx Functions
Math Object
Regular Expressions
Introduction:

Regular expression is a sequence of characters that forms a pattern which is mainly


used to find or replace patterns in a string.
These are supported by many languages such as python, java, R etc., Most common
uses of regular expressions are:

1. Finding patterns in a string or file. (Ex: find all the numbers present in a string)
2. Replace a part of the string with another string.
3. Search substring in string or file.
4. Split string into substrings.
5. Validate email format.

RegEx Module:

In python we have a built-in package called re to work with regular expressions.

RegEx Functions:

findall(pattern, string):

This function is the same as search but it matches all the occurrences of the pattern in
the given string and returns a list. The list contains the number of times it is present in
the string.
search(pattern, string):

This is the same as match function but this function can search patterns irrespective of
the position at which the pattern is present. The pattern can be present anywhere in the
string. This function matches the first occurrence of the pattern.

split(pattern, string):

This function splits a string on the given pattern. This returns the result as a list after
splitting.

sub(pattern, replace, string):

This function replaces a pattern with the given substring in a given string.
Math Object:

Whenever we call any regex method/function it searches the pattern in the string. If it
finds a match then it returns a match object else return None. We will see how the
match object looks like and how to access methods and properties of that object.

Now we will see the attributes and properties of re.Match objects one by one. They are
as follows:
 match.group(): This returns the part of the string where the match was there.
 match.start(): This returns the start position of the matching pattern in the string.
 match.end(): This returns the end position of the matching pattern in the string.
 match.span(): This returns a tuple which has start and end positions of matching
pattern.
 match.re: This returns the pattern object used for matching.
 match.string: This returns the string given for matching.
 Using r prefix before regex: This is used to convert the pattern to raw string.
This means any special character will be treated as normal character. Ex: \
character will not be treated as an escape character if we user before the pattern.
Interview Questions:

1) Write a Python program to check that a string contains only a certain set of
characters (in this case a-z, A-Z and 0-9).
2) Write a Python program that matches a string that has an a followed by zero or
more b's.
3) Write a Python program that matches a string that has an a followed by one or
more b's.
4) Write a Python program that matches a string that has an a followed by zero or
one 'b'.
5) Write a Python program that matches a string that has an a followed by three 'b'.
6) Write a Python program to find sequences of lowercase letters joined by an
underscore.
7) Write a Python program that matches a string that has an 'a' followed by anything
ending in 'b'.
8) Write a Python program that matches a word at the end of a string, with optional
punctuation.
9) Write a Python program that matches a word containing 'z', not the start or end
of the word.
10) Write a Python program that starts each string with a specific number.
Unit-17: Multithreading
Introduction
What is Process
What is Thread
What is Multithreading
What is Multiprocessing
Why Multithreading?
Starting the thread
The Threading Module
Working with Multiple Threads
Race Conditions
Synchronizing Threads
Multithreading Priority Queues
Threading Objects
Advantages of Multithreading
Multithreading
Introduction:

We all know the famous saying- Time is money. It is always said that humans are not
built for multitasking. But that is where machines come in. So while you might not be
able to multitask easily, we will talk about the tips and tricks that increase performance
and reduce time consumption, in the case of computers. Can you guess what we are
going to learn about today? The multitasking approach that we will discuss in this
tutorial is multithreading in Python!

What is Process?

A program in execution is known as a process. When you start any app or program on
your computer, such as the internet browser, the operating system treats it as a
process.

A process may consist of several threads of execution that may execute concurrently. In
other words, we can say a process facilitates multithreading.

What is Thread?

In Computer Science, a thread is synonymous with lightweight processes. So a thread


is nothing but an independent flow of execution. It can also be defined as an instance of
a process. Well, you must be wondering, what's a process? It's nothing but a program in
execution.

Simply put, a thread is a sequence of instructions that the computer performs. It is


executed independently. Depending on the scenario, a thread can also be pre-empted
or put to sleep. Note-Preemption refers to the action of stopping a task temporarily to
continue it at a later time. So, in this case, the thread can be temporarily interrupted by
the processor. But in the case of the implementations of Python 3, the threads merely
appear to be executing simultaneously. To facilitate multithreading in Python, we can
make use of the following modules offered by Python:

 Thread Module
 Threading Module

With the Threading module in Python, which provides a very intuitive API for spawning
threads, we can perform multithreading in Python quite effectively.

What is multithreading?

If you wish to save time and improve performance, you should use multithreading in
Python! Multithreading in Python is a popular technique that enables multiple tasks to
be executed simultaneously. In simple words, the ability of a processor to execute
multiple threads simultaneously is known as multithreading. Python multithreading
facilitates sharing data space and resources of multiple threads with the main thread. It
allows efficient and easy communication between the threads.

What is Multiprocessing?

The ability of a processor to execute several unrelated processes simultaneously is


known as multiprocessing. These processes do not share any resources.

Multiprocessing breaks down processes into smaller routines that run independently.
The more tasks a single processor is burdened with, the more difficult it becomes for the
processor to keep track of them.

It evidently gives rise to the need for multiprocessing. Multiprocessing tries to ensure
that every processor gets its own processor/processor core and that execution is
hassle-free.

Note:
In the case of multicore processor systems like Intel i3, a processor core is
allotted to a process.
Multithreading Vs Multiprocessing:

Why Multithreading?

If you wish to break down your tasks and applications into multiple sub-tasks and then
execute them simultaneously, then multithreading in Python is your best bet.

All important aspects such as performance, rendering, speed and time consumption will
drastically be improved by using proper Python multithreading.
Multithreading in Python should be used only when there is no existing inter-
dependency between the threads.

Starting the thread:

After learning what a thread is, the next step is to learn how to create one. Python offers
a standard library called "threading" to perform multithreading in Python.

In Python multithreading, there are two ways in which you can start a new thread:

1. Using the Threading Module:

2. Using the Thread Module:

Working with Multiple Threads:

More often than not, you will be working with multiple threads and doing exciting work
with them. You can create the threads individually, as we saw above. But there is an
easier and more efficient way of doing that. We do this by using the
ThreadPoolExecutor in Python!
Using theThreadPoolExecutor:

The easiest way to work with multiple threads is by using the ThreadPoolExecutor, part
of the standard Python library. It falls under the concurrent.features library. Using
the with statement, you can create a context manager. It would enable you to create
and delete a pool efficiently. We can also import the ThreadPoolExecutor directly from
the concurrent.features library.

Syntax:
executor = ThreadPoolExecutor(max_workers=””)

The Threading Module:

The threading module is the high-level implementation of multithreading in Python. It is


the go-to approach for managing multithreaded applications. The benefits of the
Threading module outweigh the ones of the Thread module. Along with the methods of
the Thread module, the Threading module offers additional methods such as:

 threading.activeCount() − This returns the number of active thread objects.


 threading.currentThread() − This returns the number of objects that are under
the thread control of the caller.

 threading.enumerate() −This returns the list of all thread objects that are
presently active

Race Condition:

Race conditions are one of the primary issues you will face while working with
multithreading in Python. Most commonly, race conditions happen when two or more
threads access the shared piece of data and resource. In real-time multithreading in
Python, it can occur when threads overlap. The solution to this is synchronizing threads
which we will see further.

Synchronizing Threads:

In Python, you can implement the locking mechanism to enable you to synchronize the
threads.

The low-level synchronization primitive lock is implemented through the _thread


module. A thread can have one of the following two states:

 Locked
 Unlocked

The class that is used to implement primitive locks is known as Lock. Lock objects are
created to make the threads run synchronously. Only one thread at a time can have a
lock.

The two methods supported by a lock object are –


1. acquire()– This method changes the state of an unlocked lock. But if it is already
locked, the acquire() method is blocked.
2. release()– This method is used to free up the locks when no longer required. It
can be called by any state, irrespective of their state.

The parameter that we pass through the Lock class' acquire() method is known as the
blocking parameter. Let's assume we have a thread object T to understand how all
these work together. As mentioned before, if we wish to call the acquire() method for T,
we will pass the blocking parameter through it. The blocking parameter can have only
two possible values- True or False. It gives rise to two scenarios.

 Scenario 1: When the blocking parameter is set to True, and we call the acquire
method as T.acquire (blocking=True), the thread object will acquire the lock T.
This can happen only when T has no existing locks. On the flip side, if the thread
object T is already locked, the acquire() call is suspended, and it waits until T
releases the lock. The moment thread T frees up, the calling thread immediately
re-locks it. The calling thread then acquires the released lock.

 Scenario 2: When the blocking parameter is set to False, and T is unlocked, it


acquires a lock and returns True. Whereas if T is already locked and the blocking
parameter is set to False, the acquire method does not affect T. It simply returns
False.

Multithreading Priority Queues:

A new queue object can be created using the Queue module. It can hold a specific
number of items. You can use the following methods to control the queue:

 get(): It returns and removes an item from the queue.


 put(): It adds an item to the queue.
 qsize(): It returns the number of items currently in the queue.
 empty(): It returns True or False based on whether the queue is empty or not.
 full(): It returns True if the queue is full otherwise, it returns False.

Threading Objects:

1. Semaphore
2. Timer
3. Barrier
Semaphore:

 The threading. Semaphore is the first on the list.


 It is a counter with certain special properties.
 Since the counting is atomic, you can be sure that the operating system will not
switch the thread in the middle of an increment or decrement.
 The counter is incremented when threading.release() is called.
 The counter is decremented when threading.acquire() is called.

Time:

 The object used to schedule a function to be called after a certain amount of time
has passed is the threading.Timer.
 The Timer is started by using the .start() method.
 The Timer is stopped by using the .cancel() method.

Barrier:

 The object used to keep multiple threads in sync is the threading.Barrier() object.
 You need to specify the number of threads to be synchronized while creating the
Barrier.
 The .wait() method is called by each thread on a Barrier.

Advantages of Multithreading:

 Python multithreading enables efficient utilization of the resources as the threads


share the data space and memory.
 Multithreading in Python allows the concurrent and parallel occurrence of various
tasks.
 It causes a reduction in time consumption or response time, thereby increasing
the performance.
Interview Questions:

1) Write a Python program to create multiple threads and print their names.
2) Write a Python program to download multiple files concurrently using threads.
3) Write a Python program that creates two threads to find and print even and odd
numbers from 30 to 50.
4) Write a Python program to implement a multi-threaded merge sort algorithm.
5) Write a Python program to calculate the factorial of a number using multiple
threads.
6) Write a Python program that performs concurrent HTTP requests using threads.
7) Write a Python program to implement a multi-threaded quicksort algorithm.
Unit-18: Data Structures

Collection Module
Counters
Ordered Dict
Default Dict
Chain Map
Named Tuple
Deque
User Dict
User String
Linked List
Stack
Queue
Priority Queue
Heap Queue
Binary Tree
Graphs

Collection Module in Python:

The collections module in Python is a built-in module that provides alternatives to


Python's general-purpose built-in containers, such as dict, list, set, and tuple. It includes
a set of specialized container datatypes that offer various alternatives to Python's built-
in containers.

Counters:

Counters are a subclass of dictionary designed to count hashable objects. They are an
incredibly useful tool for tallying elements and implementing counting algorithms.
Ordered Dict:

An OrderedDict is a subclass of the dictionary that maintains the sequence of items as


they are added, facilitating the insertion and removal of elements.

Default Dict:

A Default Dict is a dictionary subclass that calls a factory function to supply missing
values, simplifying handling of missing keys.
Chain Map:

A Chain Map groups multiple dictionaries into a single view, making it convenient to
manage multiple scopes (e.g., variable scopes in programming languages).

Named Tuple:

Named Tuples enable the creation of objects akin to tuples that are indexable, iterable,
and whose fields can be accessed via attribute lookup.

Deque:
A deque (double-ended queue) is a generalization of stacks and queues which supports
memory-efficient and fast appends and pops from either side.

User Dict:

User Dict is a wrapper around dictionary objects for easier dictionary subclassing.

User String:

User String is a wrapper around string objects for easier string subclassing.

Linked List:
A linked list is a linear collection of data elements where each element points to the
next, allowing for a dynamic data structure with efficient insertions and deletions.

Stack:

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle.
Queue:

Similar to a stack, a queue in Python is a fundamental data structure that organizes


items sequentially, adhering to a First In, First Out (FIFO) principle.

Queues can be implemented in Python using several methods:


 Using a list
 Using collections.deque
 Using queue.Queue

Implementing Queue using List:

In a list-based implementation, the append() method is used for enqueue operations, while
the pop(0) method is employed for dequeue operations, as shown below:
Implementation using collections.deque:

The collections.deque is preferred for queue implementations due to its efficient O(1) time complexity
for append and pop operations from both ends, compared to the list's O(n) for certain operations.
Implementation using queue.queue:

The queue. Queue class provides a FIFO queue implementation suitable for multi-
threading environments, with methods to check if the queue is full or empty.
Priority Queue:

Priority queues in Python are specialized data structures using Python that organize
elements such that each is assigned a certain priority. This concept in data structures
using Python mirrors real-world situations where tasks of higher importance are
addressed first, irrespective of the sequence in which they come up.
Heap Queue:

The heap queue module in Python provides an array of functions for managing heaps,
which are a specialized data structure using Python that follows the heap queue or
priority queue algorithm. In these data structures using Python, heaps are implemented
as binary trees where the value of each parent node is less than or equal to the values
of its children, ensuring the smallest element is consistently positioned at the
root, heap[0]. The module facilitates efficient operations—such as inserting and
extracting the smallest element—within O(log n) time, making it exceptionally suitable
for tasks that demand regular retrieval of the smallest item.
Binary Tree:

A binary tree is a specialized form of a tree utilized in data structures using python,
where each node can have no more than two children, commonly identified as the left
and right child. In the realm of data structures using Python, this structure is vital for a
multitude of computing tasks, ranging from straightforward data storage to the execution
of intricate algorithms.
Graphs:

Graphs as one of the more complex data structures in Python, are characterized by
their capacity to depict intricate connections through nodes (or vertices) and edges that
link these nodes. This type of data structures in Python is defined by a collection of
vertices (V) and edges (E) which join vertex pairs, thereby showcasing the interlinked
attributes of the data they represent. Graphs can be represented in Python using two
primary methods: the Adjacency Matrix and the Adjacency List.

Adjacency Matrix:

An Adjacency Matrix takes the form of a square matrix and serves to depict a finite
graph. The matrix entries denote the adjacency between vertex pairs; a non-zero value
implies the presence of an edge connecting those vertices. In the matrix representation,
if there is an edge between vertex (i) and vertex (j), then the matrix cell ([i][j]) is set to
(1), or a weight in the case of a weighted graph. This method is excellent for
representing dense graphs, where the number of edges is large.
Adjacency List:

The Adjacency List is a more space-efficient way to represent graphs, especially sparse
ones. It consists of an array of lists, where the index of the array represents a vertex
and the list at each index contains the vertices adjacent to that vertex. This method
allows for faster and more efficient storage of graphs when you have a large number of
vertices but few edges.
Interview Questions:

1) Write a Python program for binary search.


2) Write a Python program for binary search of an ordered list.
3) Write a Python program to sort a list of elements using the selection sort
algorithm.
4) Write a Python program to sort a list of elements using the merge sort
algorithm.
5) Write a Python program for counting sort.
Unit-19: NumPy Python Library
Introduction to NumPy:

What is NumPy?

NumPy in Python or Numerical Python is an open-source Python library created


by "Travis Oliphant" in 2005 for numerical and scientific computing in Python. NumPy
arrays are stored in a single continuous block of memory; this makes NumPy faster than
the Python list and takes lesser memory. In the field of data science and Artificial
Intelligence, NumPy is used widely.

 It is a group of same-type elements.


 The array in NumPy is called ndarray, which is also known as an alias array.
 Axes are the dimensions in NumPy.The number of axes determines the rank.

Operations using NumPy:

Indexing:

Indexing is used for accessing elements from an array. It starts from 0. Below is a code
example where the element of the index (0,2)(0,2) are accessed, where 0 stands for the
1st row and 1 for the 3rd column from the 2-D array.
Slicing:

Slicing is the method for getting substrings from the original arrays by mentioning the
start and end inside the slice operator []. Let's see the below example where the
substring from the 2nd element to the 5th element is sliced.

Note:
elements are accessed through indexing.

array.ndim:

array.ndim is used to find the number of dimensions of the array.

array.itemsize:

array.itemsize is used to find the size of each element of the Numpy array in bytes.

array.dtype:

array.dtype is used to find the data type of elements of an array.


array.size:

array.size is used to find the size of the array by counting the number of elements from
the given array.

 It returns the count of elements along a specific axis.

array.shape:

By using the array.shape function, we can find the shape, i.e., the number of rows and
columns of an array.

 It returns a tuple.
 The lengths of the corresponding array dimensions are given by the tuple items.

array.reshape():

array.reshape is used to reshape the array; it means changing the shape, i.e., rows and
columns of the array.
array.sum():

By using an array.sum, we can find the sum of the array.

Why Numpy?

 Fast
 It works very well with SciPy and other Libraries
 Matrix arithmetic
 It has lot of inbuilt functions.
 it has universal functions

Features of NumPy:

 NumPy is a combination of Python and the C language as it is partially written in


Python, and most of its parts are written in C or C++.
 The object-oriented approach is also fully supported by Numpy.
 NumPy functions can be used to work with code that is written in other
programming languages and provides tools for integrating with languages such
as C, Fortran, etc.
 NumPy is an open-source core Python package for scientific computing.
 NumPy uses less space and stores data in contiguous memory.
 It offers a multidimensional array object with excellent performance as well as
methods for working with these arrays.
 Arrays can be reshaped into different dimensions using the reshape function
provided by NumPy.
 We can work with different data types using NumPy and can determine the type
of data using the dtype function.
 NumPy comes with a plethora of built-in functions such as sum, sort, max, and
so on, allowing users to write fewer lines of code while improving the quality of
their work.
 NumPy provides a broadcasting technique by which we can perform arithmetic
operations on arrays of different shapes.
 NumPy with SciPy is also used as an alternative to MATLAB.

Applications of NumPy:

 Numpy arrays are used as an alternative for Python lists.


 Numpy in Python is used for performing mathematical operations on
Multidimensional arrays.
 Numpy is used with different libraries like Scipy, Pandas, Tkinter, etc.
 Numpy is also used for reshaping the arrays called Broadcasting for
performing operations on different sized arrays.
 Scipy with Numpy in Python can be used in place of MATLAB.

NumPy Installation:

On Windows:

1. Install NumPy using the following PIP command in the command prompt
terminal:

Syntax:
pip install numpy

The installation will start automatically, and Numpy will be successfully installed
with its latest version.
2. Verify NumPy Installation by typing the command given below in command:

Syntax:
pip show Numpy

3. Import NumPy Package

1. Create python Environment in cmd by typing:Python

2. Type command import numpy as np


Upgrade NumPy by using the following command:

pip install –upgrade numpy

Indexing and Slicing:


Indexing is used to access individual elements. It is also possible to extract entire rows,
columns, or planes from multi-dimensional arrays with numpy indexing. Indexing starts
from 0.
Interview Questions:

1) Write a NumPy program to get help with the add function.


2) Write a NumPy program to test whether none of the elements of a given
array are zero.
3) Write a NumPy program to test elements-wise for positive or negative
infinity.
4) Write a NumPy program to test whether two arrays are element-wise equal
within a tolerance.
5) Write a NumPy program to create an array with the values 1, 7, 13, 105
and determine the size of the memory occupied by the array.
6) Write a NumPy program to create an array of all even integers from 30 to
70.
7) Write a NumPy program to create a 3x3 identity matrix.
8) Write a NumPy program to generate a random number between 0 and 1.
9) Write a NumPy program to create a 3X4 array and iterate over it.
10) Write a NumPy program to create a vector with values from 0 to 20 and
change the sign of the numbers in the range from 9 to 15.
11) Write a NumPy program to multiply the values of two given vectors.
12) Write a NumPy program to create a 3x4 matrix filled with values from 10 to
21.
13) Write a NumPy program to create a vector of length 10 with values evenly
distributed between 5 and 50.
14) Write a NumPy program to create a 5x5 zero matrix with elements on the
main diagonal equal to 1, 2, 3, 4, 5.
15) Write a NumPy program to create a 3x3x3 array filled with arbitrary values.
Unit-20: Pandas Python Library
What are Pandas in Python?

Let's now see what is pandas in Python. Pandas is an open-source Python library that
has a BSD license (BSD licenses are a low-restriction type of license for open source
software that imposes minimum restrictions on the use and distribution of open source
software) and is used in data science, data analysis, and machine learning activities.
Both readily and intuitively, it functions with relational or labeled data.

It offers a variety of data structures and operations for working with time series and
numerical data. This library is developed on top of the NumPy library, which supports
multi-dimensional arrays. As a result, pandas are quick and offer users high
performance and productivity. Being one of the most widely used data-wrangling tools,
Pandas integrates well with a variety of different data science modules within the
Python environment and is frequently available in all Python distributions, including
those that come with your operating system and those sold by commercial vendors like
Active State’s ActivePython.

Features of Pandas:

 Quick and efficient data manipulation and analysis.


 Tools for loading data from different file formats into in-memory data objects.
 Label-based Slicing, Indexing, and Subsetting can be performed on large
datasets.
 Merges and joins two datasets easily.
 Pivoting and reshaping data sets
 Easy handling of missing data (represented as NaN) in both floating point and
non-floating point data.
 Represents the data in tabular form.
 Size mutability: DataFrame and higher-dimensional object columns can be added
and deleted.
 It provides time-series functionality.
 Effective grouping by functionality for splitting, applying, and combining data sets.

Advantages of Pandas:

 Data visualization Data representation with Pandas is incredibly simplified. This


helps with improved data analysis and understanding. Data science projects
produce better results when the data is represented more simply.

 Less writing and more productivity It is one of the Pandas' best features. With
the help of Pandas, multiple lines of Python code in the absence of any support
libraries can be easily completed in one or two lines. As a result, Pandas help to
reduce time and procedures while also speeding up the data-handling process.
As a result, we can devote more time to data analysis algorithms.

 Efficiently handles large amounts of data Pandas handle large datasets very
efficiently. Pandas save a lot of time by importing large amounts of data quickly.

 A large number of features Pandas provide you with a large set of important
commands and features by which data can be easily analyzed. In addition,
pandas can perform various tasks, such as data filtering based on certain
conditions, segmenting and segregating the data by preferences, and so on.

 Flexibility and customization of data With the help of Pandas, you may apply a
wide range of features. For example, we can alter, customize, and pivot the
existing data according to our wishes. Your data may be used to its greatest
extent by doing this.

Python Pandas Data Structures:

Series:

A series is a one-dimensional array that contains elements of the same data type.
Series are mutable means we can modify the elements of a series but its size is
immutable, i.e. we cannot change the size of the series once declared. It has two main
components: data and an index.

Parameters:

 data(required): This is the input data, which can be any list, dictionary, etc.
 index(Optional): The index for the value you use for the series is represented by
this number.
 dtype(Optional): This describes the values contained in the series.
 copy(Optional): This makes a copy of the input data.
Dataframe:

Dataframe is a 2-dimensional data structure that contains elements of the same data. It
is mutable, and its size is also mutable, i.e. we can change both data and size of the
dataframe data structure. It has labeled axes (rows and columns) and has two different
indexes (row index and column index) as both rows and columns are indexed.

Parameters:

 data(required): Input data, can be ndarray, series, map, lists, dict, constants,
and another DataFrame.
 index(optional): For labeling rows.
 columns(Optional): For labeling columns.
 dtype(Optional): Data type of each column.
 copy(Optional): This makes a copy of the input data.

Installation of Pandas on Windows:

Method-1: Using pip:


It's a package installation tool that simplifies the installation of Python modules and
frameworks. Pip will be installed with Python by default if you have a later version of
Python available (greater than Python 3.5.x). If you're using an earlier version of Python,
you'll need to install pip before you can install Pandas.

Step 1: Launch Command Prompt

To open the start menu, use the Windows key on your keyboard or click the Start
button. For example, when you type "cmd" the Command Prompt app should display in
the start menu, and once you can view the command prompt app, launch the app.
Alternatively, you may hit the Windows key + r to bring up the "RUN" box, where you
can input “cmd” and then press enter. It will also launch the Command prompt.

Step 2: Enter the command:

After you open the command prompt, the following step is to enter the needed
command to begin the pip installation.

Syntax:
pip install pandas
(or)
pip3 install pandas
Using Conda:

Installing Pandas using Anaconda is the best option if you are unfamiliar with command-
line programming. Anaconda is a sophisticated Python distribution that provides access
to various libraries besides Pandas. Anaconda will become increasingly handy as you
learn further about Python.

Step 1 : Download Anaconda:

To install Anaconda, go to this page and then click on the "Download" button
on the right.

Step 2 : Install Anaconda:

Start your installation from the website by clicking the "Next" button.
Then, click the "I Agree" option to accept the licensing agreement.

Then, pick the user accounts for whom Pandas should be installed. We proceeded by
selecting the recommended "Just Me" option.

In the wizard's concluding stage, you must specify where the distribution will be
downloaded.
Finally, under the advanced installation options area, tick the "Add Anaconda to my
PATH environment variable" and "Register Anaconda3 as my preferred Python 3.x (x
over here denotes whatever the current version could be)" choices.

The installation of Anaconda will begin when you click the "Install" button. When the
setup is finished, you will see the "Installation Complete" screen within a few minutes.
=== Learn Here.. Lead Anywhere..!! ===

You might also like