Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (1 vote)
252 views

Introduction of Python

Python is a high-level programming language that can be used to write programs to perform tasks like data analysis, building machine learning models, and web development. It provides tools and libraries that support these types of applications. The Python interpreter converts Python code into machine-readable instructions in a step-by-step process: first through preprocessing, lexical analysis, parsing and then compilation before producing executable code. Popular Python IDEs and compilers that facilitate this process include PyCharm, Spyder, and IDLE.

Uploaded by

Riya Santoshwar
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (1 vote)
252 views

Introduction of Python

Python is a high-level programming language that can be used to write programs to perform tasks like data analysis, building machine learning models, and web development. It provides tools and libraries that support these types of applications. The Python interpreter converts Python code into machine-readable instructions in a step-by-step process: first through preprocessing, lexical analysis, parsing and then compilation before producing executable code. Popular Python IDEs and compilers that facilitate this process include PyCharm, Spyder, and IDLE.

Uploaded by

Riya Santoshwar
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 217

Introduction to Python Basic program:

https://www.tutorialspoint.com/basics_of_computers/
basics_of_computers_system_software.htm
https://www.programiz.com/python-programming/
statement-indentation-comments

Computer:
A computer is a machine( Electronics)

that can be instructed to carry out sequences of arithmetic or logical operations automatically

Radio: its also electronic Machine( Electronics), Sound can be sent by radio,

sometimes through Frequency Modulation (FM) or Amplitude Modulation (AM).

Television (also known as a TV) :is a machine ( Electronics) with a screen.

Televisions receive broadcasting signals and change them into pictures and sound.

computer program:

computers have the ability to follow generalized sets of INSTRUCTION OR operations, called programs.

programs enable computers to perform an extremely wide range of tasks.

computer programming: to carry out sequences of arithmetic or logical operations.


Arithmetic operations: Addition + ,

Subtraction _ ,

Multiplication * ,

Division /,

logical operations: Less Than <

Greater than >

Equal to =

ALU: An arithmetic-logic unit is the part of a computer processor (CPU)

that carries out arithmetic and logic operations on the operands in computer

instruction words(Program).
Central processing unit (CPU), principal part of any digital computer system, composed of the

main memory, control unit, and arithmetic-logic unit.

RAM
RAM stands for Random Access Memory. The processor accesses all memory addresses
directly, irrespective of word length, making storage and retrieval fast.

ROM
ROM stands for Read Only Memory. As the name suggests, ROM can only be read by the
processor. New data cannot be written into ROM. Data to be stored into ROM is written during
the manufacturing phase itself.

Secondary Memory:

Characteristics of Secondary Memory

These are some characteristics of secondary memory, which distinguish it from primary memory

 It is non-volatile, i.e data are permant . it retains data when power is switched off
 It is large capacities to the tune of terabytes
 A bus is a common pathway through which information flows from one computer component to another. This pathway is used for communication purposes and it is established
between two or more computer components. We are going to check different computer bus architectures that are found in computers.

Different Types of Computer Buses:


A bus is a common pathway through which information flows from one
computer component to another. This pathway is used for communication
purposes and it is established between two or more computer components .

1) Data Bus

2) Address bus

3) Control bus

OUTPUT devices:
10 Examples of Output Devices
1. Monitor
2. Printer
3. Headphones
4. Computer Speakers
5. Projector
6. GPS
7. Sound Card
8. Video Card
9. Braille Reader
10. Speech-Generating Device

Basics of Computers - Input/Output Ports

A connection point that acts as interface between the computer and external devices like mouse,
printer, keyboard, etc. is called port. Ports are of two types −
 Internal port − It connects the motherboard to internal devices

like hard disk drive, CD drive, internal modem, etc.

 External port − It connects the motherboard to external devices

like modem, mouse, printer, flash drives, etc.

Computer study
1) Hardware system: Physical existence, eg mouse , keyboard, cpu, harddisk ,ram etc

2) software system: logical existence, program eg. window operating system. xp. window10,

linux. java . python. etc

Language Processor: Python

As discussed earlier, an important function of system software is to convert all user instructions
into machine understandable language. When we talk of human machine interactions, languages
are of three types −

 Machine-level language − This language is nothing but a string of 0s and 1s that the
machines can understand. It is completely machine dependent.

Binary means two state : High and Low. Yes or No, True or False, ON and OFF
i. e 1 and 0

Binary Number System

The easiest way to vary instructions through electric signals is two-state system – on and off.
On is represented as 1 and off as 0, though 0 is not actually no signal but signal at a lower
voltage. The number system having just these two digits – 0 and 1 – is called binary number
system.

Each binary digit is also called a bit. Binary number system is also positional value system,
where each digit has a value expressed in powers of 2, as displayed here.


 Assembly-level language − This language introduces a layer of abstraction by
defining mnemonics. Mnemonics are English like words or symbols used to denote a
long string of 0s and 1s. use Hexa-decimal 0,1,2,3,4,5,6,7,8,9,A,B.C,D.E.F

For example, the word “READ” can be defined to mean that computer has to retrieve data
from the memory. The complete instruction will also tell the memory address. Assembly
level language is machine dependent.

High level language − This language uses English like statements


and is completely independent of machines. Programs written using
high level languages are easy to create, read and understand. A To Z
and 0,1,2,3,4,5,6,7,8,9
When we talk of human machine interactions,

languages Program written in high level programming languages

like Python ,Java, C++, etc. is called source code.

Set of instructions in machine readable form is called object code or machine code.

System software that converts source code to object code is called language processor.

There are three types of language interpreters−

 Assembler − Converts assembly level program into machine level program.


 Interpreter − Converts high level programs into machine level program line by line.
 Compiler − Converts high level programs into machine level programs at one go rather
than line by line.(whole program excute)

Which interpreter is best for Python?


The Best Python IDEs and Code Editors
(According to Our Developers and the Python Community)
 PyCharm.
 Visual Studio Code.
 Sublime Text.
 Vim.
 Atom.
 Jupyter Notebook.
 Eclipse + PyDev + LiClipse.
 GNU Emacs

Which compiler is best for Python?


Below is the detailed description of python compilers:
1. PyCharm. It is one of the best and extensively used IDE, which is created by Jet Brains. ...
2. Spyder. It is another open-source IDE that can be used as a python compiler for python code
development. ...
3. Pydev. ...
4. IDLE. ...
5. Wing. ...
6. Eric Python. ...
7. Rodeo.

Compiler
System software that store the complete program, scan it, translate the complete program into
object cod ce and then creates an executable code is called a compiler. On the face of it
compilers compare unfavorably with interpreters because they −

 are more complex than interpreters


 need more memory space
 take more time in compiling source code

However, compiled programs execute very fast on computers.

The following image shows the step-by-step process of how a source code is transformed into an
executable code
( How Program is computer excute?)

These are the steps in compiling source code into executable code −

 Pre-processing − In this stage pre-processor instructions, typically used by languages


like C and C++ are interpreted, i.e. converted to assembly level language.
 Lexical analysis − Here all instructions are converted to lexical units like constants,
variables, arithmetic symbols, etc.
 Parsing − Here all instructions are checked to see if they conform to grammar rules of
the language. If there are errors, compiler will ask you to fix them before you can
proceed.
 Compiling − At this stage the source code is converted into object code.
 Linking − If there are any links to external files or libraries, addresses of their executable
will be added to the program. Also, if the code needs to be rearranged for actual
execution, they will be rearranged. The final output is the executable code that is ready
to be executed.

https://docs.python.org/3.8/tutorial/index.html

Mark Hammond is an independent Microsoft Windows consultant working out of Melbourne, Australia.
He studied computer science at the South Australian Institute of Technology (now the University of South
Australia), and then worked with several large financial institutions in Australia. He started his consulting
operation in 1995. Mark has produced many of the Windows extensions for Python, including PythonWin,
Active Scripting, and Active Debugging support, and coauthored the COM framework and extensions. He
is also a leading authority on Active Scripting and related technologies and has spoken on this subject at
Microsoft�s three most recent Professional Developers conferences. Apart from being a father to his
teenage daughter, having an interest in live music, and providing way-too-many free Python extensions,
Mark has no life!
ASCII (American Standard Code for Information Interchange) is the most common format
for text files in computers and on the Internet. In an ASCII file,

Each alphabetic(A-Z), numeric(0-9), or special character (!<@( ) _ >,#,$,%,^.&>*=) is


represented,

7-bit binary number (a string of seven 0s or 1s).

128 possible characters are defined.


aAA

Units of Computer Memory Measurements | What is the basic unit of


computer memory? Which of the following is the smallest unit of
measure?
Computer Programming:

Why Programming?

What Programmers Do?

The Programming Process


Developing a program involves steps similar to any problem-solving task. There are
five main ingredients in the programming process:

1. Defining the problem,


2. Planning the solution,
3. Coding the program,
4. Testing the program,
5. Documenting the program,
1.Introduction to Python
Python was conceived in the late 1980s byGuido van Rossum at Centrum Wiskunde &
Informatica (CWI) in the Netherlands as a successor to ABC programming

language, which was inspired by SETL, capable of exception handling and interfacing with
the Amoeba operating system. Its implementation began in December 1989.

When was Python invented?

Python is the best language to start as a beginner because of the user-friendliness it has over other
languages. Also, it enforces you to write clean and good code, because it does not allow
whitespaces. This allows you also to become a team member everyone loves working with

Guido Van Rossum said that he had derived the name Python from the British sketch-comedy
series Monty Python's Flying Circus, of which he is a big fan. While deciding it, he was in
a “slightly irreverent mood.”

Why is Python so popular?

First and foremost reason why Python is much popular because it is highly productive as
compared to other programming languages like C++ and Java. ... Python is also very famous for
its simple programming syntax, code readability and English-like commands that make coding in
Python lot easier and efficient.

https://www.tutorialspoint.com/python/python_basic_syntax.htm
Python Identifiers
A Python identifier is a name used to identify a variable, function, class, module or other object.
An identifier starts with a letter A to Z or a to z or an underscore ( _ ) followed by zero or
more letters, underscores and digits (0 to 9).

Python does not allow punctuation characters such as @, $, and % within identifiers.

Python is a case sensitive programming language.

Thus, Manpower and manpower are two different identifiers in Python.

Here are naming conventions for Python identifiers −

 Class names start with an uppercase letter. All other identifiers start with a lowercase
letter.
 Starting an identifier with a single leading underscore indicates that the identifier is
private.
 Starting an identifier with two leading underscores indicates a strongly private identifier.
 If the identifier also ends with two trailing underscores, the identifier is a language-
defined special name.

Python Identifiers

An identifier is a name given to entities like class, functions, variables, etc. It helps to
differentiate one entity from another.

Rules for writing identifiers

1. Identifiers can be a combination of letters in lowercase (a to z) or uppercase (A to Z) or digits (0


to 9) or an underscore _. Names like myClass, var_1 and print_this_to_screen, all are
valid example.
2. An identifier cannot start with a digit. 1variable is invalid, but variable1 is a valid name.
3. Keywords cannot be used as identifiers.

global = 1

Output

File "<interactive input>", line 1


global = 1
^
SyntaxError: invalid syntax

4. We cannot use special symbols like !, @, #, $, % etc. in our identifier.

a@ = 0
Output

File "<interactive input>", line 1


a@ = 0
^
SyntaxError: invalid syntax

5. An identifier can be of any length.

6. Python Keywords

Keywords are the reserved words in Python.

We cannot use a keyword as a variable name, function name or any other identifier. They are
used to define the syntax and structure of the Python language.

In Python, keywords are case sensitive.

There are 33 keywords in Python 3.7. This number can vary slightly over the course of time.

All the keywords except True, False and None are in lowercase and they must be written as
they are. The list of all the keywords is given below.

False await else import pass


None break except in raise
True class finally is return
and continue for lambda try
As def from nonlocal while
assert del global not with
Yield
async elif if or
Statements and control flow:

Python's statements include

 The assignment statement (token '=', the equals sign).


 The if statement, which conditionally executes a block of code, along with else and elif (a
contraction of else-if).
 The for statement, which iterates over an iterable object, capturing each element to a local
variable for use by the attached block.
 The while statement, which executes a block of code as long as its condition is true.
 The try statement, which allows exceptions raised in its attached code block to be caught and
handled by except clauses; it also ensures that clean-up code in a finally block will always
be run regardless of how the block exits.
 The raise statement, used to raise a specified exception or re-raise a caught exception.
 The class statement, which executes a block of code and attaches its local namespace to a
class, for use in object-oriented programming.
 The def statement, which defines a function or method.
 The with statement which encloses a code block within a context manager
 The break statement, exits from the loop.
 The continue statement, skips this iteration and continues with the next item.
 The del statement, removes a variable, which means the reference from the name to the value
is deleted and trying to use that variable cause an error. Deleted variable can be reassigned to
later as normal.
 The pass statement, which serves as a NOP. It is syntactically needed to create an empty code
block.
 The assert statement, used during debugging to check for conditions that ought to apply.
 The yield statement, which returns a value from a generator function. From Python 2.5,
yield is also an operator. This form is used to implement coroutines.
 The return statement, used to return a value from a function.
 The import statement, which is used to import modules whose functions or variables can be
used in the current program.

There are three ways of using import: import <module name> [as <alias>] or from
<module name> import * or from <module name> import <definition 1> [as
<alias 1>], <definition 2> [as <alias 2>], ....

 The print statement was changed to the print() function in Python 3.

The assignment statement ('=') operates by binding a name as a reference to a separate,


Reserved Words
The following list shows the Python keywords. These are reserved words and you cannot use
them as constant or variable or any other identifier names. All the Python keywords contain
lowercase letters only.

and exec not


assert finally or
break for pass
class from print
continue global raise
def if return
del import try
elif in while
else is with
except lambda yield

Python Statement
Instructions that a Python interpreter can execute are called statements.

For example, a = 1 is an assignment statement.

if statement, for statement, while statement, etc.

are other kinds of statements which will be discussed later.


Multi-line statement

In Python, the end of a statement is marked by a newline character.

line continuation character ( \ ).

But we can make a statement extend over multiple lines with the line continuation character (\).
For example:

a = 1 + 2 + 3 + \
4 + 5 + 6 + \
7 + 8 + 9

This is an explicit line continuation. In Python, line continuation is implied

inside parentheses ( ), brackets [ ], and braces { }.

For instance, we can implement the above multi-line statement as:

a = (1 + 2 + 3 +
4 + 5 + 6 +
7 + 8 + 9)

Here, the surrounding parentheses ( ) do the line continuation implicitly. Same is the case

with [ ] and { }. For example:

colors = ['red',
'blue',
'green']

We can also put multiple statements in a single line using


semicolons ( ;)
E.g as follows:

a = 1; b = 2; c = 3

Python Indentation ( : )
Most of the programming languages like C, C++, and Java use braces { } to define a block of
code.

(: ) Note statement body ( Block of code)

Python, however, uses indentation :

A code block (body of a function, loop, etc.) starts : with indentation and ends : with the
first unindented line.

The amount of indentation is up to you, but it must be consistent throughout that block.

Generally, four whitespaces are used for indentation and are preferred over tabs. Here is an
example.

for i in range(1,11):
print(i)
if i == 5:
break

The enforcement of indentation in Python makes the code look neat and clean. This results in
Python programs that look similar and consistent.

Indentation can be ignored in line continuation,

but it's always a good idea to indent. It makes the code more readable.

For example:

if True:
print('Hello')
a = 5

and
if True: print('Hello'); a = 5

both are valid and do the same thing, but the former style is clearer.

https://www.programiz.com/python-programming/statement-indentation-comments

Python Comments ( # )
In Python, we use the hash (#) symbol to start writing a comment.

Comments are very important while writing a program. They describe what is going on inside a program,
so that a person looking at the source code does not have a hard time figuring it out.

Comments are for programmers to better understand a program. Python Interpreter ignores
comments.

#This is a comment
#print out Hello
# this my first program
print('Hello')

Multi-line comments

""" or '''

Another way of doing this is to use triple quotes, either ''' or """.
"""This is also a
perfect example of
multi-line comments"""

"""This is a comment
print out Hello
this my first program"""
print('Hello')

Docstrings in Python

A docstring is short for documentation string.


Triple quotes are used while writing docstrings. For example:

def double(num):
"""Function to double the value"""
return 2*num

Output

Function to double the value

https://www.programiz.com/python-programming/statement-indentation-comments

Python Variables, Constants and Literals

Python Variables
A variable is a named location used to store data in the memory. It is helpful to think of variables
as a container that holds data that can be changed later in the program.

For example,

number = 10

Example : Assigning multiple values to multiple variables


a, b, c = 5, 3.2, "Hello"

print (a)
print (b)
print (c)

python variable a,b,c

If we want to assign the same value to multiple variables at once, we can do


this as:

x = y = z = "same"

print (x)
print (y)
print (z)

python variable x, y ,z

assignment operator = to assign a value to a variable.(changeble in program)

e.g
website = "apple.com"
print(website)
e.g next value

website = "apple.com"
print(website)

# assigning a new value to website


website = "programiz.com"

print(website)

Constants
A constant is a type of variable whose value cannot be changed. It is helpful to think of constants
as containers that hold information which cannot be changed later.

Example : Declaring and assigning value to a constant

Create a constant .py:

PI = 3.14
GRAVITY = 9.8

Create a main .py:

import constant

print(constant.PI)
print(constant.GRAVITY)

assignment operator = to assign a value to a constant .( fixed in program)

file format for c language program:

Python............ *.py

.cc C++ source file cloudsit.cc


.cpp C++ source file cloudsit.cpp
.o C/C++ object file cloudsit.o
.h C/C++ header file Cloudsit.h

file format for java language program

List of File Extensions


File Extension File Type
.java Java language file.
.jar Java classes archive file.
.jnl CVS journal file.
.jpg Bitmap graphics (Joint Photography Experts Group).

C# (pronounced "C Sharp"), an object-oriented programming language created by Microsoft for use
with . NET Framework

Rules and Naming Convention for Variables and constants


1. Constant and variable names should have a combination of letters in lowercase (a to z) or
uppercase (A to Z) or digits (0 to 9) or an underscore (_). For example:

snake_case
MACRO_CASE
camelCase
CapWords

2. Create a name that makes sense. For example, vowel makes more sense than v.

1. If you want to create a variable name having two words, use underscore to separate
them. For example:

my_name
current_salary

2. Use capital letters possible to declare a constant.

For example:

PI
G
MASS
SPEED_OF_LIGHT
TEMP

3. Never use special symbols like !, @, #, $, %, etc.

4. Don't start a variable name with a digit.

e.g 1 val ........... its not allow,

val1............ its correct.


Literals
Literal is a raw data given in a variable or constant.

In Python, there are various types of literals they are as follows:

Numeric Literals
String literals
Boolean literals
Special literals
Literal Collections

Numeric Literals:
Numeric Literals are immutable (unchangeable). Numeric literals can belong to 3 different numerical
types: Integer, Float, and Complex.

Example 4: How to use Numeric literals in Python?


a = 0b1010 #Binary Literals
b = 100 #Decimal Literal
c = 0o310 #Octal Literal
d = 0x12c #Hexadecimal Literal

#Float Literal
float_1 = 10.5
float_2 = 1.5e2
#Complex Literal
x = 3.14j

print(a, b, c, d)
print(float_1, float_2)
print(x, x.imag, x.real)

Unicode
Unicode is an information technology (IT) standard for the consistent encoding, representation,
and handling of text expressed in most of the world's writing systems.

The standard is maintained by the Unicode Consortium, and as of March 2020, there is a total
of 143,859 characters, with Unicode 13.0 (these characters consist of 143,696 graphic
characters and 163 format characters) covering 154 modern and historic scripts, as well as
multiple symbol sets and emoji. The character repertoire of the Unicode Standard is
synchronized with ISO/IEC 10646, and both are code-for-code identical.

Encoding:
Encoding is the process of converting data from one form to another.

encoding is the process of putting a sequence of characters (letters, numbers, punctuation, and
certain symbols) into a specialized format for efficient transmission or storage

While "encoding" can be used as a verb, it is often used as a noun, and refers to a specific type
of encoded data. There are several types of encoding, including image encoding, audio and
video encoding, and character encoding.

Decoding:

Decoding is the opposite process -- the conversion of an encoded format back into the
original sequence of characters.

Encoding and decoding are used in data communications, networking, and storage

String literals:

String literals
A string literal is a sequence of characters surrounded by quotes. We can use both single, double,
or triple quotes for a string. And, a character literal is a single character surrounded by single or
double quotes.

Example 7: How to use string literals in Python?


strings = "This is Python"
char = "C"
multiline_str = """This is a multiline string with more than one line code."""
unicode = u"\u00dcnic\u00f6de"
raw_str = r"raw \n string"

print(strings)
print(char)
print(multiline_str)
print(unicode)
print(raw_str)

Output

This is Python
C
This is a multiline string with more than one line code.
Ünicöde
raw \n string

Boolean literals
A Boolean literal can have any of the two values: True or False.

In Python, True represents the value as 1 and False as 0

Example 8: How to use boolean literals in Python?


x = (1 == True)
y = (1 == False)
a = True + 4
b = False + 10

print("x is", x)
print("y is", y)
print("a:", a)
print("b:", b)

Output

x is True
y is False
a: 5
b: 10

Special literals
Python contains one special literal i.e. None. We use it to specify that the field has not been
created.

Example 9: How to use special literals in Python?


drink = "Available"
food = None

def menu(x):
if x == drink:
print(drink)
else:
print(food)

menu(drink)
menu(food)

Output

Available
None

In the above program, we define a menu function. Inside menu, when we set the argument as
drink then, it displays Available. And, when the argument is food, it displays None.

Literal Collections
There are four different literal collections

1)List literals,

2)Tuple literals,

3) Dict literals, and

4)Set literals.

Example 10: How to use literals collections in Python?


fruits = ["apple", "mango", "orange"] #list
numbers = (1, 2, 3) #tuple
alphabets = {'a':'apple', 'b':'ball', 'c':'cat'} #dictionary
vowels = {'a', 'e', 'i' , 'o', 'u'} #set

print(fruits)
print(numbers)
print(alphabets)
print(vowels)

Output

['apple', 'mango', 'orange']


(1, 2, 3)
{'a': 'apple', 'b': 'ball', 'c': 'cat'}
{'e', 'a', 'o', 'i', 'u'}

In the above program, we created a list of fruits, a tuple of numbers, a dictionary dict having
values with keys designated to each value and a set of vowels.

To learn more about literal collections, refer to Python Data Types.

Python Data Types

Data types in Python

Every value in Python has a datatype.

Since everything is an object in Python programming,

data types are actually classes and variables are instance (object) of these classes.

There are various data types in Python. Some of the important types are listed below.

Python Numbers: as int, float and complex classes

Python List: brackets [ ]

Python Tuple: parentheses ()

Python Strings: ''' or """


Python Set: braces { }

Python Dictionary: braces {}

Conversion between data types


Python Numbers
Integers, floating point numbers and complex numbers fall under Python numbers category.
They are defined as int, float and complex classes in Python.

We can use the type() function to know which class a variable or a value belongs to. Similarly,
the isinstance() function is used to check if an object belongs to a particular class.

a = 5
print(a, "is of type", type(a))

a = 2.0
print(a, "is of type", type(a))

a = 1+2j
print(a, "is complex number?", is instance(1+2j,complex))

.
Python List
List is an ordered sequence of items. It is one of the most used datatype in Python and is very
flexible. All the items in a list do not need to be of the same type.

Declaring a list is pretty straight forward. Items separated by commas are enclosed within
brackets [ ].

a = [1, 2.2, 'python']

We can use the slicing operator [ ] to extract an item or a range of items from a list. The index starts
from 0 in Python.

a = [5,10,15,20,25,30,35,40]

# a[2] = 15
print("a[2] = ", a[2])

# a[0:3] = [5, 10, 15]


print("a[0:3] = ", a[0:3])

# a[5:] = [30, 35, 40]


print("a[5:] = ", a[5:])

Output

a[2] = 15
a[0:3] = [5, 10, 15]
a[5:] = [30, 35, 40]
Lists are mutable, meaning, the value of elements of a list can be altered.

Python Tuple
Tuple is an ordered sequence of items same as a list. The only difference is that tuples are
immutable. Tuples once created cannot be modified.

Tuples are used to write-protect data and are usually faster than lists as they cannot change
dynamically.

It is defined within parentheses () where items are separated by commas.

t = (5,'program', 1+3j)

We can use the slicing operator [] to extract items but we cannot change its value.

t = (5,'program', 1+3j)

# t[1] = 'program'
print("t[1] = ", t[1])

# t[0:3] = (5, 'program', (1+3j))


print("t[0:3] = ", t[0:3])

# Generates error
# Tuples are immutable
t[0] = 10

Output

t[1] = program
t[0:3] = (5, 'program', (1+3j))
Traceback (most recent call last):
File "test.py", line 11, in <module>
t[0] = 10
TypeError: 'tuple' object does not support item assignment

Python Strings
String is sequence of Unicode characters. We can use single quotes or double quotes to represent
strings. Multi-line strings can be denoted using triple quotes, ''' or """.

s = "This is a string"
print(s)
s = '''A multiline
string'''
print(s)
Output

This is a string
A multiline
string

Python Set
Set is an unordered collection of unique items. Set is defined by values separated by comma
inside braces { }. Items in a set are not ordered.

a = {5,2,3,1,4}

# printing set variable


print("a = ", a)

# data type of variable a


print(type(a))

Output

a = {1, 2, 3, 4, 5}
<class 'set'>

Python Dictionary
Dictionary is an unordered collection of key-value pairs.

It is generally used when we have a huge amount of data. Dictionaries are optimized for
retrieving data. We must know the key to retrieve the value.

In Python, dictionaries are defined within braces {} with each item being a pair in the form
key:value. Key and value can be of any type.

>>> d = {1:'value','key':2}
>>> type(d)
<class 'dict'>

We use key to retrieve the respective value. But not the other way around.

d = {1:'value','key':2}
print(type(d))

print("d[1] = ", d[1]);

print("d['key'] = ", d['key']);


# Generates error
print("d[2] = ", d[2]);

Output

<class 'dict'>
d[1] = value
d['key'] = 2
Traceback (most recent call last):
File "<string>", line 9, in <module>
KeyError: 2

Conversion between data types


We can convert between different data types by using different type conversion functions like
int(), float(), str(), etc.

>>> float(5)
5.0

Output

5 is of type <class 'int'>


2.0 is of type <class 'float'>
(1+2j) is complex number? True
Integers can be of any length, it is only limited by the memory available
Python Type Conversion and Type Casting

Type Conversion
The process of converting the value of one data type (integer, string, float, etc.) to another data
type is called type conversion. Python has two types of type conversion.

1. Implicit Type Conversion


2. Explicit Type Conversion

Implicit Type Conversion


In Implicit type conversion, Python automatically converts one data type to another data type.
This process doesn't need any user involvement.

Let's see an example where Python promotes the conversion of the lower data type (integer) to
the higher data type (float) to avoid data loss.

Example 1: Converting integer to float


num_int = 123
num_flo = 1.23

num_new = num_int + num_flo

print("datatype of num_int:",type(num_int))
print("datatype of num_flo:",type(num_flo))

print("Value of num_new:",num_new)
print("datatype of num_new:",type(num_new))

When we run the above program, the output will be:

datatype of num_int: <class 'int'>


datatype of num_flo: <class 'float'>

Value of num_new: 124.23


datatype of num_new: <class 'float'>
In the above program,

 We add two variables num_int and num_flo, storing the value in num_new.
 We will look at the data type of all three objects respectively.
 In the output, we can see the data type of num_int is an integer while the data type of
num_flo is a float.
 Also, we can see the num_new has a float data type because Python always converts smaller
data types to larger data types to avoid the loss of data.

Explicit Type Conversion


In Explicit Type Conversion, users convert the data type of an object to required data type.
We use the predefined functions like int(), float(), str(), etc to perform explicit type
conversion.

This type of conversion is also called typecasting because the user casts (changes) the data
type of the objects.

Syntax :

<required_datatype>(expression)
Typecasting can be done by assigning the required data type function to the expression.

Python Input, Output and Import:

input staement input() and

output statement print()

import math
print(math.pi)
This tutorial focuses on two built-in functions print() and input() to perform I/O task in Python.
Also, you will learn to import modules and use them in your program.

Python provides numerous built-in functions that are readily available to


us at the Python prompt.
Some of the functions like input() and print() are widely used for standard input and output
operations respectively. Let us see the output section first.

Python Input
Up until now, our programs were static. The value of variables was defined or hard coded into
the source code.

To allow flexibility, we might want to take the input from the user. In Python, we have the
input() function to allow this. The syntax for input() is:

input([prompt])

where prompt is the string we wish to display on the screen. It is optional.

>>> num = input('Enter a number: ')


Enter a number: 10
>>> num
'10'

Python Import
When our program grows bigger, it is a good idea to break it into different modules.

A module is a file containing Python definitions and statements. Python modules have a filename
and end with the extension .py.

Definitions inside a module can be imported to another module or the interactive interpreter in
Python. We use the import keyword to do this.

For example, we can import the math module by typing the following line:

import math

We can use the module in the following ways:


import math
print(math.pi)

Output

3.141592653589793

>>> import sys


>>> sys.path
['',
'C:\\Python33\\Lib\\idlelib',
'C:\\Windows\\system32\\python33.zip',
'C:\\Python33\\DLLs',
'C:\\Python33\\lib',
'C:\\Python33',
'C:\\Python33\\lib\\site-packages']

Python output
We use the print() function to output data to the standard output device (screen). We can also
output data to a file, but this will be discussed later.

An example of its use is given below.

print('This sentence is output to the screen')

Output

This sentence is output to the screen

Another example is given below:

a = 5
print('The value of a is', a)

Arithmetic operators
Arithmetic operators are used to perform mathematical operations like addition, subtraction, multiplication, etc.

Operator Meaning Example

Add two operands or


+ x + y+ 2
unary plus

- Subtract right operand x - y- 2


from the left or unary
minus

* Multiply two operands x*y

Divide left operand by


/ the right one (always x/y
results into float)

Modulus - remainder of x%y


% the division of left (remainder
operand by the right of x/y)

Floor division - division


that results into whole
// x // y
number adjusted to the
left in the number line

Exponent - left operand


x**y (x to
** raised to the power of
the power y)
right

Example 1: Arithmetic operators in Python

x = 15
y = 4

# Output: x + y = 19
print('x + y =',x+y)

# Output: x - y = 11
print('x - y =',x-y)

# Output: x * y = 60
print('x * y =',x*y)

# Output: x / y = 3.75
print('x / y =',x/y)
# Output: x // y = 3
print('x // y =',x//y)

# Output: x ** y = 50625
print('x ** y =',x**y)
Output

x + y = 19
x - y = 11
x * y = 60
x / y = 3.75
x // y = 3
x ** y = 50625

Comparison operators
Comparison operators are used to compare values. It returns either True or False according to the condition.

Operato
Meaning Example
r
Greater than - True if left
> operand is greater than0 x>y
th00.0e right
Less than - True if left
< operand is less than the x<y
right
Equal to - True if both
== x == y
operands are equal
Not equal to - True if
!= x != y
operands are not equal
Greater than or equal to -
True if left operand is
>= x >= y
greater than or equal to
the right
Less than or equal to -
<= True if left operand is less x <= y
than or equal to the right
Example 2: Comparison operators in Python

x = 10
y = 12

# Output: x > y is False


print('x > y is',x>y)

# Output: x < y is True


print('x < y is',x<y)
# Output: x == y is False
print('x == y is',x==y)

# Output: x != y is True
print('x != y is',x!=y)

# Output: x >= y is False


print('x >= y is',x>=y)

# Output: x <= y is True


print('x <= y is',x<=y)

Output

x > y is False
x < y is True
x == y is False
x != y is True
x >= y is False
x <= y is True

Logical operators
Logical operators are the and, or, not operators.

Operato
Meaning Example
r
True if both the operands
and x and y
are true
True if either of the
or x or y
operands is true
True if operand is false
not (complements the not x
operand)
xample 3: Logical Operators in Python

x = True
y = False

print('x and y is',x and y)

print('x or y is',x or y)

print('not x is',not x)

Output

x and y is False
x or y is True
not x is False

Bitwise operators
Bitwise operators act on operands as if they were strings of binary digits. They operate bit by bit, hence the name.

For example, 2 is 10 in binary and 7 is 111.


In the table below: Let x = 10 (0000 1010 in binary) and y = 4 (0000 0100 in binary)

Operato
Meaning Example
r
& Bitwise AND x&y=0( 0000 0000 )
| Bitwise OR x | y = 14 ( 0000 1110 )
~ Bitwise NOT ~x = -11 ( 1111 0101 )
^ Bitwise XOR x ^ y = 14 ( 0000 1110 )
Bitwise right
>> x >> 2 = 2 ( )
shift
0000 0010

x << 2 = 40 (
<< Bitwise left shift
0010

)
1000

Assignment operators
Assignment operators are used in Python to assign values to variables.
a = 5 is a simple assignment operator that assigns the value 5 on the right to the variable a on
the left.
There are various compound operators in Python like a += 5 that adds to the variable and later
assigns the same. It is equivalent to a = a + 5.
Operator Example Equivalent to
= x=5 x=5
+= x += 5 x=x+5
-= x -= 5 x=x-5
*= x *= 5 x=x*5
/= x /= 5 x=x/5
%= x %= 5 x=x%5
//= x //= 5 x = x // 5
**= x **= 5 x = x ** 5
&= x &= 5 x=x&5
|= x |= 5 x=x|5
^= x ^= 5 x=x^5
>>= x >>= 5 x = x >> 5
<<= x <<= 5 x = x << 5

Special operators
Python language offers some special types of operators like the identity operator
or the membership operator. They are described below with examples.
Identity operators
is and is not are the identity operators in Python. They are used to check if two
values (or variables) are located on the same part of the memory. Two variables
that are equal does not imply that they are identical.
Operato
Meaning Example
r

True if the
operands are
is x is True
identical (refer to
the same object)

True if the
operands are not
x is not
is not identical (do not
True
refer to the same
object)

Example 4: Identity operators in Python


x1 = 5
y1 = 5
x2 = 'Hello'
y2 = 'Hello'
x3 = [1,2,3]
y3 = [1,2,3]

# Output: False
print(x1 is not y1)

# Output: True
print(x2 is y2)

# Output: False
print(x3 is y3)
Output
False
True
False
Membership operators
in and not in are the membership operators in Python. They are used to test whether a value or
variable is found in a sequence (string, list, tuple, set and dictionary).
In a dictionary we can only test for presence of key, not the value.
Operato
Meaning Example
r

True if value/variable is
in 5 in x
found in the sequence

True if value/variable is
5 not in
not in not found in the
x
sequence

Example #5: Membership operators in Python


x = 'Hello world'
y = {1:'a',2:'b'}

# Output: True
print('H' in x)

# Output: True
print('hello' not in x)

# Output: True
print(1 in y)

# Output: False
print('a' in y)
Output
True
True
True
False

Python Namespace and Scope:


In this tutorial, you will learn about namespace, mapping from names to objects,
and scope of a variable.

What is Name in Python?


If you have ever read 'The Zen of Python' (type import this in the Python
interpreter), the last line states, Namespaces are one honking great idea -- let's
do more of those! So what are these mysterious namespaces? Let us first look at

what name is.


Name (also called identifier) is simply a name given to objects.
Everything in Python is an object. Name is a way to access the
underlying object.
For example, when we do the assignment a = 2, 
2 is an object stored in memory and a is the name we associate it with.
We can get the address (in RAM) of some object through the built-in function id().

# Note: You may get different values for the id

a=2
print('id(2) =', id(2))

print('id(a) =', id(a))


Output
id(2) = 9302208
id(a) = 9302208
Here, both refer to the same object 2, so they have the same id(). Let's make
things a little more interesting.
# Note: You may get different values for the id

a=2
print('id(a) =', id(a))

a = a+1
print('id(a) =', id(a))

print('id(3) =', id(3))

b=2
print('id(b) =', id(b))
print('id(2) =', id(2))
Output
id(a) = 9302208
id(a) = 9302240
id(3) = 9302240
id(b) = 9302208
id(2) = 9302208
What is happening in the above sequence of steps? Let's use a diagram to explain
this:

Memory diagram of variables in Python


Initially, an object  2  is created and the name  a  is associated with it, when we do  a = a+1 , a new object  3  is created and now  a  is associated with this object.
Note that  id(a)  and  id(3)  have the same values.
Furthermore, when  b = 2  is executed, the new name  b  gets associated with the previous object  2 .
This is efficient as Python does not have to create a new duplicate object. This dynamic nature of name binding makes Python powerful; a name could refer to any type of
object.

>>> a = 5
>>> a = 'Hello World!'
>>> a = [1,2,3]

All these are valid and  a  will refer to three different types of objects in different instances. Functions are objects too, so a name can refer to them as well.

def printHello():
print("Hello")

a = printHello

a()

Output
Hello

The same name  a  can refer to a function and we can call the function using this name.

What is a Namespace in Python?


Now that we understand what names are, we can move on to the concept of namespaces.
To simply put it, a namespace is a collection of names.
In Python, you can imagine a namespace as a mapping of every name you have defined to
corresponding objects.
Different namespaces can co-exist at a given time but are completely isolated.
A namespace containing all the built-in names is created when we start the Python interpreter
and exists as long as the interpreter runs.

This is the reason that built-in functions like id(), print() etc . are always available to us

from any part of the program. Each module creates its own global namespace.
These different namespaces are isolated. Hence, the same name that may exist in different modules do not collide.

Modules can have various functions and classes. A local namespace is created when a function is called, which has all the names defined in it. Similar, is the case with class.
Following diagram may help to clarify this concept.

Python Variable Scope


Although there are various unique namespaces defined, we may not be able to access all of them from every part of the program. The concept of scope comes into play.

A scope is the portion of a program from where a namespace can be accessed directly without any prefix.

At any given moment, there are at least three nested scopes.

1. Scope of the current function which has local names

2. Scope of the module which has global names

3. Outermost scope which has built-in names

When a reference is made inside a function, the name is searched in the local namespace, then in the global namespace and finally in the built-in namespace.

If there is a function inside another function, a new scope is nested inside the local scope.

Example of Scope and Namespace in Python


def outer_function():
b = 20
def inner_func():
c = 30

a = 10

Here, the variable a is in the global namespace. Variable b is in the local namespace of outer_function() and c is in the nested local namespace of inner_function().
When we are in inner_function(), c is local to us, b is nonlocal and a is global. We can read as well as assign new values to c but can only read b and a from inner_function().
If we try to assign as a value to b, a new variable b is created in the local namespace which is different than the nonlocal b. The same thing happens when we assign a value
to a.
However, if we declare a as global, all the reference and assignment go to the global a. Similarly, if we want to rebind the variable b, it must be declared as nonlocal. The
following example will further clarify this.
def outer_function():
a = 20

def inner_function():
a = 30
print('a =', a)

inner_function()
print('a =', a)

a = 10
outer_function()
print('a =', a)

As you can see, the output of this program is

a = 30
a = 20
a = 10

In this program, three different variables a are defined in separate namespaces and accessed accordingly. While in the following program,

def outer_function():
global a
a = 20

def inner_function():
global a
a = 30
print('a =', a)

inner_function()
print('a =', a)

a = 10
outer_function()
print('a =', a)

The output of the program is.

a = 30
a = 30
a = 30
2. Python Flow Control

Python

if...else Statement:

What is if...else statement in Python?

Decision making is required when we want to execute a code only if a certain condition is
satisfied.

Python if Statement Syntax


if test expression:
statement(s)

Here, the program evaluates the test expression and will execute statement(s) only if the test
expression is True.

If the test expression is False, the statement(s) is not executed.

In Python, the body of the if statement is indicated by the indentation. The body starts with an
indentation and the first unindented line marks the end.

Python interprets non-zero (1) values as True. None and (0) are interpreted as False.

Python if Statement Flowchart

Flowchart of if statement in Python programmin

Example: Python if Statement


# If the number is positive, we print an appropriate message
num = 3
if num > 0:
print(num, "is a positive number.")
print("This is always printed.")

num = -1
if num > 0:
print(num, "is a positive number.")
print("This is also always printed.")

When you run the program, the output will be:

3 is a positive number
This is always printed
This is also always printed.

Python if...else Statement


Syntax of if...else
if test expression:
Body of if
else:
Body of else

The if..else statement evaluates test expression and will execute the body of if only when
the test condition is True.

If the condition is False, the body of else is executed. Indentation is used to separate the
blocks.

Python if..else Flowchart

Flowchart of if...else statement in Python

Example of if...else
# Program checks if the number is positive or negative
# And displays an appropriate message

num = 3

# Try these two variations as well.


# num = -5
# num = 0

if num >= 0:
print("Positive or Zero")
else:
print("Negative number")

Output

Positive or Zero

Python if...elif...else Statement


Syntax of if...elif...else
if test expression:
Body of if
elif test expression:
Body of elif
else:
Body of else

The elif is short for else if. It allows us to check for multiple expressions.

If the condition for if is False, it checks the condition of the next elif block and so on.

If all the conditions are False, the body of else is executed.

Only one block among the several if...elif...else blocks is executed according to the
condition.

The if block can have only one else block. But it can have multiple elif blocks.
Flowchart of if...elif...else

Flowchart of if...elif....else
statement in Python

Example of if...elif...else
'''In this program,
we check if the number is positive or
negative or zero and
display an appropriate message'''

num = 3.4

# Try these two variations as well:


# num = 0
# num = -4.5

if num > 0:
print("Positive number")
elif num == 0:
print("Zero")
else:
print("Negative number")

When variable num is positive, Positive number is printed.

If num is equal to 0, Zero is printed.

If num is negative, Negative number is printed.


0.

Any number of these statements can be nested inside one another. Indentation is the only way to
figure out the level of nesting. They can get confusing, so they must be avoided unless necessary.

Python Nested if Example


'''In this program, we input a number
check if the number is positive or
negative or zero and display
an appropriate message
This time we use nested if statement'''

num = float(input("Enter a number: "))


if num >= 0:
if num == 0:
print("Zero")
else:
print("Positive number")
else:
print("Negative number")

Output 1

Enter a number: 5
Positive number

Output 2

Enter a number: -1
Negative number

Output 3

Enter a number: 0
Zero
What is for loop in Python?
The for loop in Python is used to iterate over a sequence (list, tuple, string) or other iterable
objects. Iterating over a sequence is called traversal.

1) for loop
range ( )

2) while Loop

3) break and continue

4) pass Statement

Syntax of for Loop:

for val in sequence:

Body of for

Here, val is the variable that takes the value of the item inside
the sequence on each iteration.

Loop continues until we reach the last item in the sequence.


The body of for loop is separated from the rest of the code
using indentation.
Flowchart of for Loop

Flowchart of for Loop in Python

Example: Python for Loop


# Program to find the sum of all numbers stored in a list

# List of numbers
numbers = [6, 5, 3, 8, 4, 2, 5, 4, 11]

# variable to store the sum


sum = 0

# iterate over the list


for val in numbers:
sum = sum+val

print("The sum is", sum)

When you run the program, the output will be:

The sum is 48
The range() function
We can generate a sequence of numbers using range() function.

range(10) will generate numbers from 0 to 9 (10 numbers).

We can also define the start, stop and step size as range(start, stop,step_size). step_size
defaults to 1 if not provided.

The range object is "lazy" in a sense because it doesn't generate every number that it "contains"
when we create it. However, it is not an iterator since it supports in, len and __getitem__
operations.

This function does not store all the values in memory; it would be inefficient. So it remembers
the start, stop, step size and generates the next number on the go.

To force this function to output all the items, we can use the function list().

The following example will clarify this.

print(range(10))

print(list(range(10)))

print(list(range(2, 8)))

print(list(range(2, 20, 3)))

Output

range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 3, 4, 5, 6, 7]
[2, 5, 8, 11, 14, 17]

range() function in for loops


We can use the range() function in for loops to iterate through a sequence of numbers.

It can be combined with the len() function to iterate through a sequence using indexing.

it is not an i
terator since it supports in, len and get item operations.

Here is an example.

# Program to iterate through a list using indexing

genre = ['pop', 'rock', 'jazz']

# iterate over the list using index


for i in range(len(genre)):
print("I like", genre[i])

Output

I like pop
I like rock
I like jazz

for loop with else:


A for loop can have an optional else block as well. The else part is executed if the items in the
sequence used in for loop exhausts.

The break keyword can be used to stop a for loop. In such cases, the else part is ignored.

Hence, a for loop's else part runs if no break occurs.

Here is an example to illustrate this.

digits = [0, 1, 5]

for i in digits:
print(i)
else:
print("No items left.")

When you run the program, the output will be:

0
1
5
No items left.
Here, the for loop prints items of the list until the loop exhausts. When the for loop exhausts, it
executes the block of code in the else and prints No items left.

This for...else statement can be used with the break keyword to run the else block only
when the break keyword was not executed. Let's take an example:

# program to display student's marks from record


student_name = 'Soyuj'

marks = {'James': 90, 'Jules': 55, 'Arthur': 77}

for student in marks:


if student == student_name:
print(marks[student])
break
else:
print('No entry with that name found.')

Output

No entry with that name found.

While loop :
The while loop in Python is used to iterate over a block of code as long as the test expression
(condition) is true.

We generally use this loop when we don't know the number of times to iterate beforehand.

Syntax of while Loop in Python

while test_expression:

Body of while

In the while loop, test expression is checked first. The body of the loop is entered only if the
test_expression evaluates to True. After one iteration, the test expression is checked again.
This process continues until the test_expression evaluates to False.

In Python, the body of the while loop is determined through indentation.

The body starts with indentation and the first unindented line marks the end.
Python interprets any non-zero value as True. None and 0 are interpreted as False.

Flowchart of while Loop

Flowchart for while loop in Python

Example: Python while Loop


# Program to add natural
# numbers up to
# sum = 1+2+3+...+n

# To take input from the user,


# n = int(input("Enter n: "))

n = 10

# initialize sum and counter


sum = 0
i = 1

while i <= n:
sum = sum + i
i = i+1 # update counter

# print the sum


print("The sum is", sum)

When you run the program, the output will be:

Enter n: 10
The sum is 55
While loop with else
Same as with for loops, while loops can also have an optional else block.

The else part is executed if the condition in the while loop evaluates to False.

The while loop can be terminated with a break statement. In such cases, the else part is ignored.
Hence, a while loop's else part runs if no break occurs and the condition is false.

Here is an example to illustrate this.

'''Example to illustrate
the use of else statement
with the while loop'''

counter = 0

while counter < 3:


print("Inside loop")
counter = counter + 1
else:
print("Inside else")

Output

Inside loop
Inside loop
Inside loop
Inside else

Python break statement


The break statement terminates the loop containing it. Control of the program flows to the
statement immediately after the body of the loop.

If the break statement is inside a nested loop (loop inside another loop), the break statement
will terminate the innermost loop.

Syntax of break
break
Flowchart of break

Flowchart of break statement in Python

The working of break statement in for loop and while loop is shown below.

Working of the break statement

Example: Python break


# Use of break statement inside the loop
for val in "string":
if val == "i":
break
print(val)

print("The end")

Output

s
t
r
The end

Python continue statement


The continue statement is used to skip the rest of the code inside a loop for the current iteration
only. Loop does not terminate but continues on with the next iteration.

Syntax of Continue
continue

Flowchart of continue 

Flowchart of continue statement in Python

The working of continue statement in for and while loop is shown below.
How continue statement works in python

Example: Python continue


# Program to show the use of continue statement inside loops

for val in "string":


if val == "i":
continue
print(val)

print("The end")

Output

s
t
r
n
g
The end

What is pass statement in Python?


In Python programming, the pass statement is a null statement. The difference between a
comment and a pass statement in Python is that while the interpreter ignores a comment entirely,
pass is not ignored.

However, nothing happens when the pass is executed. It results in no operation (NOP).

Syntax of pass
pass
We generally use it as a placeholder.

Suppose we have a loop or a function that is not implemented yet, but we want to implement it in
the future. They cannot have an empty body. The interpreter would give an error. So, we use the
pass statement to construct a body that does nothing.

Example: pass Statement


'''pass is just a placeholder for
functionality to be added later.'''
sequence = {'p', 'a', 's', 's'}
for val in sequence:
pass

We can do the same thing in an empty function or class as well.

def function(args):
pass
class Example:
pass
3.Python Functions

what a function is, the syntax, components, and types of functions.

Python Function
1) Default Arguments

2) Keyword Arguments

3) Arbitrary Arguments

4) Recursive Function

5) Anonymous/Lambda Function

filter(), map(),reduce() , Aliasing Function.

6) Python Global, Local and Nonlocal variables

7) Global Keyword

8) Python Modules

9) Python Package

What is a function in Python?


In Python, a function is a group of related statements that performs a
specific task.
Functions help break our program into smaller and modular chunks. As our program grows
larger and larger, functions make it more organized and manageable.

Furthermore, it avoids repetition and makes the code reusable.

Syntax of Function
def function_name(parameters):
"""docstring"""
statement(s)
Above shown is a function definition that consists of the following components.

1. Keyword def that marks the start of the function header.


2. A function name to uniquely identify the function. Function naming follows the same rules of
writing identifiers in Python.
3. Parameters (arguments) through which we pass values to a function. They are optional.
4. A colon (:) to mark the end of the function header.
5. Optional documentation string (docstring) to describe what the function does.
6. One or more valid python statements that make up the function body. Statements must have
the same indentation level (usually 4 spaces).
7. An optional return statement to return a value from the function.

Types of Functions
Basically, we can divide functions into the following two types:

1. Built-in functions - Functions that are built into Python.


2. User-defined functions - Functions defined by the users themselves.

Example of a function
def greet(name):
"""
This function greets to
the person passed in as
a parameter
"""
print("Hello, " + name + ". Good morning!")
How to call a function in python?

Once we have defined a function, we can call it from another function, program or even the
Python prompt. To call a function we simply type the function name with appropriate
parameters.

>>> greet('Paul')
Hello, Paul. Good morning!

Note: Try running the above code in the Python program with the function definition to see the
output.

def greet(name):
"""
This function greets to
the person passed in as
a parameter
"""
print("Hello, " + name + ". Good morning!")

greet('Paul')

Docstrings
The first string after the function header is called the docstring and is short for documentation
string. It is briefly used to explain what a function does.

Although optional, documentation is a good programming practice. Unless you can remember
what you had for dinner last week, always document your code.

In the above example, we have a docstring immediately below the function header. We generally
use triple quotes so that docstring can extend up to multiple lines. This string is available to us as
the __doc__ attribute of the function.

For example:

Try running the following into the Python shell to see the output.

>>> print(greet.__doc__)

This function greets to


the person passed in as
a parameter

To learn more about docstrings in Python, visit Python Docstrings.


The return statement
The return statement is used to exit a function and go back to the place from where it was
called.

Syntax of return
return [expression_list]
This statement can contain an expression that gets evaluated and the value is returned. If there is
no expression in the statement or the return statement itself is not present inside a function, then
the function will return the None object.
For example:

>>> print(greet("May"))
Hello, May. Good morning!
None

Here, None is the returned value since greet() directly prints the name and no return statement
is used.

Example of return
def absolute_value(num):
"""This function returns the absolute
value of the entered number"""

if num >= 0:
return num
else:
return -num

print(absolute_value(2))

print(absolute_value(-4))

Output

2
4

How Function works in Python?

Working of functions in Python

Scope and Lifetime of variables


Scope of a variable is the portion of a program where the variable is recognized. Parameters and
variables defined inside a function are not visible from outside the function. Hence, they have a
local scope.

The lifetime of a variable is the period throughout which the variable exits in the memory. The
lifetime of variables inside a function is as long as the function executes.

They are destroyed once we return from the function. Hence, a function does not remember the
value of a variable from its previous calls.

Here is an example to illustrate the scope of a variable inside a function.

def my_func():
x = 10
print("Value inside function:",x)

x = 20
my_func()
print("Value outside function:",x)

Output

Value inside function: 10


Value outside function: 20

Here, we can see that the value of x is 20 initially. Even though the function my_func() changed
the value of x to 10, it did not affect the value outside the function.

This is because the variable x inside the function is different (local to the function) from the one
outside. Although they have the same names, they are two different variables with different
scopes.

On the other hand, variables outside of the function are visible from inside. They have a global
scope.

We can read these values from inside the function but cannot change (write) them. In order to
modify the value of variables outside the function, they must be declared as global variables
using the keyword global.

Python Function Arguments

In Python, you can define a function that takes variable number of arguments. such functions
using default, keyword and arbitrary arguments.

Arguments:
In the user-defined function , we learned about defining a function and calling it. Otherwise, the
function call will result in an error.

Here is an example.

def greet(name, msg):


"""This function greets to
the person with the provided message"""
print("Hello", name + ', ' + msg)
greet("Monica", "Good morning!")

Output

Hello Monica, Good morning!

Here, the function greet() has two parameters.

Since we have called this function with two arguments, it runs smoothly and we do not get any
error.

If we call it with a different number of arguments, the interpreter will show an error message.
Below is a call to this function with one and no arguments along with their respective error
messages.

>>> greet("Monica") # only one argument


TypeError: greet() missing 1 required positional argument: 'msg'
>>> greet() # no arguments
TypeError: greet() missing 2 required positional arguments: 'name' and 'msg'

Variable Function Arguments:


In Python, there are other ways to define a function that can take variable number of arguments.

Three different forms of this type are described below.

1) Python Default Arguments:


2) Python Keyword Arguments:
3) Python Arbitrary Arguments:
Python Default Arguments
Function arguments can have default values in Python.

We can provide a default value to an argument by using the assignment operator (=). Here is an
example.

def greet(name, msg="Good morning!"):


"""
This function greets to
the person with the
provided message.

If the message is not provided,


it defaults to "Good
morning!"
"""

print("Hello", name + ', ' + msg)

greet("Kate")
greet("Bruce", "How do you do?")

Output

Hello Kate, Good morning!


Hello Bruce, How do you do?

In this function, the parameter name does not have a default value and is required (mandatory)
during a call.

On the other hand, the parameter msg has a default value of "Good morning!". So, it is optional
during a call. If a value is provided, it will overwrite the default value.

Any number of arguments in a function can have a default value. But once we have a default
argument, all the arguments to its right must also have default values.

This means to say, non-default arguments cannot follow default arguments. For example, if we
had defined the function header above as:

def greet(msg = "Good morning!", name):

We would get an error as:


SyntaxError: non-default argument follows default argument

Python Keyword Arguments


the arguments according to their position

For example, in the above function greet(), when we called it as greet("Bruce", "How do
you do?"), the value "Bruce" gets assigned to the argument name and similarly "How do you
do?" to msg.

Python allows functions to be called using keyword arguments. When we call functions in this
way, the order (position) of the arguments can be changed.

# 2 keyword arguments

greet(name = "Bruce",msg = "How do you do?")

# 2 keyword arguments (out of order)


greet(msg = "How do you do?",name = "Bruce")

1 positional, 1 keyword argument


greet("Bruce", msg = "How do you do?")

As we can see, we can mix positional arguments with keyword arguments during a function call.
But we must keep in mind that keyword arguments must follow positional arguments.

Having a positional argument after keyword arguments will result in errors. For example, the
function call as follows:

greet(name="Bruce","How do you do?")

Will result in an error:

SyntaxError: non-keyword arg after keyword arg

Python Arbitrary Arguments


Sometimes, we do not know in advance the number of arguments that will be passed into a
function.

Python allows us to handle this kind of situation through function calls with an arbitrary number
of arguments.
In the function definition, we use an asterisk (*) before the parameter name to denote this kind
of argument.

Here is an example.

def greet(*names):
"""This function greets all
the person in the names tuple."""

# names is a tuple with arguments


for name in names:
print("Hello", name)

greet("Monica", "Luke", "Steve", "John")

Output

Hello Monica
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
Hello Steve
Hello John

Here, we have called the function with multiple arguments. These arguments get wrapped up into
a tuple before being passed into the function. Inside the function, we use a for loop to retrieve
all the arguments back.

Python Recursion Function

What is recursion?
Recursion is the process of defining something in terms of itself.

A physical world example would be to place two parallel mirrors facing each other. Any object
in between them would be reflected recursively.

Python Recursive Function


In Python, we know that a function can call other functions. It is even possible for the function to
call itself. These types of construct are termed as recursive functions.

The following image shows the working of a recursive function called recurse.
Recursive Function in Python

Following is an example of a recursive function to find the factorial of an integer.

Factorial of a number is the product of all the integers from 1 to that number. For example, the
factorial of 6 (denoted as 6!) is 1*2*3*4*5*6 = 720.

Example of a recursive function


def factorial(x):
"""This is a recursive function
to find the factorial of an integer"""

if x == 1:
return 1
else:
return (x * factorial(x-1))

num = 3
print("The factorial of", num, "is", factorial(num))

Output

The factorial of 3 is 6

In the above example, factorial() is a recursive function as it calls itself.

When we call this function with a positive integer, it will recursively call itself by decreasing the
number.

Each function multiplies the number with the factorial of the number below it until it is equal to
one. This recursive call can be explained in the following steps.

factorial(3) # 1st call with 3


3 * factorial(2) # 2nd call with 2
3 * 2 * factorial(1) # 3rd call with 1
3 * 2 * 1 # return from 3rd call as number=1
3 * 2 # return from 2nd call
6 # return from 1st call

Let's look at an image that shows a step-by-step process of what is going on:
Working of a recursive factorial
function

Our recursion ends when the number reduces to 1. This is called the base condition.

Every recursive function must have a base condition that stops the recursion or else the function
calls itself infinitely.

The Python interpreter limits the depths of recursion to help avoid infinite recursions, resulting in
stack overflows.

By default, the maximum depth of recursion is 1000. If the limit is crossed, it results in
RecursionError. Let's look at one such condition.

def recursor():
recursor()
recursor()

Output

Traceback (most recent call last):


File "<string>", line 3, in <module>
File "<string>", line 2, in a
File "<string>", line 2, in a
File "<string>", line 2, in a
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded

Advantages of Recursion
1. Recursive functions make the code look clean and elegant.
2. A complex task can be broken down into simpler sub-problems using recursion.
3. Sequence generation is easier with recursion than using some nested iteration.

Disadvantages of Recursion
1. Sometimes the logic behind recursion is hard to follow through.
2. Recursive calls are expensive (inefficient) as they take up a lot of memory and time.
3. Recursive functions are hard to debug.

Python Anonymous/Lambda Function:

What are lambda functions in Python?


In Python, an anonymous function is a function that is defined without a name.

While normal functions are defined using the def keyword in Python, anonymous functions are
defined using the lambda keyword.

Hence, anonymous functions are also called lambda functions.

How to use lambda Functions in Python?


A lambda function in python has the following syntax.

Syntax of Lambda Function in python


lambda arguments: expression
1) filter()function in Python takes in a function and a list as arguments
2) map() function in Python takes in a function and a list.

Lambda functions can have any number of arguments but only one expression. The expression is
evaluated and returned. Lambda functions can be used wherever function objects are required.

Example of Lambda Function in python

Here is an example of lambda function that doubles the input value.

# Program to show the use of lambda functions


double = lambda x: x * 2

print(double(5))

Output

10

In the above program, lambda x: x * 2 is the lambda function. Here x is the argument and x *
2 is the expression that gets evaluated and returned.

This function has no name. It returns a function object which is assigned to the identifier double.
We can now call it as a normal function. The statement

double = lambda x: x * 2

is nearly the same as:

def double(x):
return x * 2

Use of Lambda Function in python


What is a lambda function in programming?
As there is a growing interest in dynamic languages, more people are running into a
programming concept called Lambdas (also called Closures, Anonymous Functions or
Blocks). ... Essentially a lambda is a block of code that can be passed as an argument to a
function call
We use lambda functions when we require a nameless function for a short period of time.

In Python, we generally use it as an argument to a higher-order


function (a function that takes in other functions as arguments).
Lambda functions are used along with built-in functions like
filter(), map() etc.
Example use with filter()The filter() function in Python takes in a function and a list as
arguments.

The function is called with all the items in the list and a new list is returned which contains items
for which the function evaluates to True.

Here is an example use of filter() function to filter out only even numbers from a list.

# Program to filter out only the even items from a list


my_list = [1, 5, 4, 6, 8, 11, 3, 12]

new_list = list(filter(lambda x: (x%2 == 0) , my_list))

print(new_list)

Output

[4, 6, 8, 12]

Example use with map()

The map() function in Python takes in a function and a list.


The function is called with all the items in the list and a new list is returned which contains items
returned by that function for each item.

Here is an example use of map() function to double all the items in a list.

# Program to double each item in a list using map()

my_list = [1, 5, 4, 6, 8, 11, 3, 12]

new_list = list(map(lambda x: x * 2 , my_list))

print(new_list)

Output

[2, 10, 8, 12, 16, 22, 6, 24]


Python - Reduce Function

The reduce() function is defined in the functools module. Like the map


and filter functions, the reduce() function receives two arguments, a
function and an iterable. However, it doesn't return another iterable,
instead it returns a single value.

Syntax:
functools.reduce(myfunction, iterable, initializer)

The argument function is applied cumulatively to arguments in the list


from left to right. The result of the function in the first call becomes
the first argument and the third item in list becomes second. This is
repeated until the list is exhausted.

In the example below, the mult() function is defined to return the


product of two numbers. This function is used in the reduce() function
along with a range of numbers between 1 and 4, which are 1,2 and 3.
The output is a factorial value of 3.

Example: reduce()

 Copy
import functools
def mult(x,y):
print("x=",x," y=",y)
return x*y

fact=functools.reduce(mult, range(1, 4))


print ('Factorial of 3: ', fact)
Result:

X=1 y=2
X=2 y=3
Factorial of 3: 6
E.g:
from functools import *
i= [10,20,30,40,50]
result = reduce (lambda x,y: x+y, i)
print(result) #150
E.g:
result=reduce(lambda x,y:x*y, i)
print(result)

ouput= 12000000

Aliasing in Python:

In python programming, the second name given to a piece of data is


known as an alias. Aliasing happens when the value of one variable is
assigned to another variable because variables are just names that store
references to actual value.
E.g

first_variable = "PYTHON"

print("Value of first:", first_variable)

print("Reference of first:", id(first_variable))

print("--------------")

second_variable = first_variable # making an alias

print("Value of second:", second_variable)

print("Reference of second:", id(second_variable))

print("--------------")
Python Global, Local and Nonlocal variables

Global Variables
In Python, a variable declared outside of the function or in global scope is known as a global
variable. This means that a global variable can be accessed inside or outside of the function.

Let's see an example of how a global variable is created in Python.

Example 1: Create a Global Variable


x = "global"

def foo():
print("x inside:", x)

Example 4: Using Global and Local variables in the same code


x = "global "

def foo():
global x
y = "local"
x = x * 2
print(x)
print(y)

foo()

Output

global global
local

we declare x as a global and y as a local variable in the foo().

Then, we use multiplication operator * to modify the global variable x and we print both x and y.

After calling the foo(), the value of x becomes global global because we used the x * 2 to
print two times global. After that, we print the value of local variable y i.e local.

Example 5: Global variable and Local variable with same name


x = 5

def foo():
x = 10
print("local x:", x)
foo()
print("global x:", x)

Output

local x: 10
global x: 5

In the above code, we used the same name x for both global variable and local variable. We get a
different result when we print the same variable because the variable is declared in both scopes,
i.e. the local scope inside foo() and global scope outside foo().

When we print the variable inside foo() it outputs local x: 10. This is called the local scope
of the variable.

Similarly, when we print the variable outside the foo(), it outputs global x: 5. This is
called the global scope of the variable.

foo()
print("x outside:", x)

Output

x inside: global
x outside: global

In the above code, we created x as a global variable and defined a foo() to print the global
variable x. Finally, we call the foo() which will print the value of x.

What if you want to change the value of x inside a function?

x = "global"

def foo():
x = x * 2
print(x)

foo()

Output

UnboundLocalError: local variable 'x' referenced before assignment

The output shows an error because Python treats x as a local variable and x is also not defined
inside foo().
To make this work, we use the global keyword. Visit Python Global Keyword to learn more.

Local Variables
A variable declared inside the function's body or in the local scope is known as a local variable.

Example 2: Accessing local variable outside the scope


def foo():
y = "local"

foo()
print(y)

Output

NameError: name 'y' is not defined

The output shows an error because we are trying to access a local variable y in a global scope
whereas the local variable only works inside foo() or local scope.

Let's see an example on how a local variable is created in Python.

Example 3: Create a Local Variable

Normally, we declare a variable inside the function to create a local variable.

def foo():
y = "local"
print(y)

foo()

Output

local

Nonlocal Variables
Nonlocal variables are used in nested functions whose local scope is not defined.

This means that the variable can be neither in the local nor the global scope.

Let's see an example of how a nonlocal variable is used in Python.

We use nonlocal keywords to create nonlocal variables.

Example 6: Create a nonlocal variable


def outer():
x = "local"

def inner():
nonlocal x
x = "nonlocal"
print("inner:", x)

inner()
print("outer:", x)

outer()

Output

inner: nonlocal
outer: nonlocal

Python Global Keyword

What is the global keyword


In Python, global keyword allows you to modify the variable outside of the current scope. It is
used to create a global variable and make changes to the variable in a local context.

Rules of global Keyword


The basic rules for global keyword in Python are:

 When we create a variable inside a function, it is local by default.


 When we define a variable outside of a function, it is global by default. You don't have to use
global keyword.
 We use global keyword to read and write a global variable inside a function.
 Use of global keyword outside a function has no effect.

Use of global Keyword


Let's take an example.

Example 1: Accessing global Variable From Inside a Function


c = 1 # global variable

def add():
print(c)

add()

When we run the above program, the output will be:

However, we may have some scenarios where we need to modify the global variable from inside
a function.

Example 2: Modifying Global Variable From Inside the Function


c = 1 # global variable

def add():
c = c + 2 # increment c by 2
print(c)

add()

When we run the above program, the output shows an error:

UnboundLocalError: local variable 'c' referenced before assignment

This is because we can only access the global variable but cannot modify it from inside the
function.

The solution for this is to use the global keyword.


Example 3: Changing Global Variable From Inside a Function using global
c = 0 # global variable

def add():
global c
c = c + 2 # increment by 2
print("Inside add():", c)

add()
print("In main:", c)

When we run the above program, the output will be:

Inside add(): 2
In main: 2

In the above program, we define c as a global keyword inside the add() function.

Then, we increment the variable c by 1, i.e c = c + 2. After that, we call the add() function.
Finally, we print the global variable c.

As we can see, change also occurred on the global variable outside the function, c = 2.

Global Variables Across Python Modules


In Python, we create a single module config.py to hold global variables and share information
across Python modules within the same program.

Here is how we can share global variables across the python modules.

Example 4: Share a global Variable Across Python Modules

Create a config.py file, to store global variables

a = 0
b = "empty"

Create a update.py file, to


import config change global variables

config.a = 10
config.b = "alphabet"

Create a main.py file, to test changes in value

import config
import update

print(config.a)
print(config.
01b
.)

When we run the main.py file, the output will be

10
alphabet

In the above, we have created three files: config.py, update.py, and main.py.

The module config.py stores global variables of a and b. In the update.py file, we import the
config.py module and modify the values of a and b. Similarly, in the main.py file, we import
both config.py and update.py module. Finally, we print and test the values

of global variables whether they are changed or not.

Global in Nested Functions


Here is how you can use a global variable in nested function.

Example 5: Using a Global Variable in Nested Function


def foo():
x = 20

def bar():
global x
x = 25

print("Before calling bar: ", x)


print("Calling bar now")
bar()
print("After calling bar: ", x)

foo()
print("x in main: ", x)
The output is :

Before calling bar: 20


Calling bar now
After calling bar: 20
x in main: 25

In the above program, we declared a global variable inside the nested function bar(). Inside
foo() function, x has no effect of the global keyword.

Before and after calling bar(), the variable x takes the value of local variable i.e x = 20.
Outside of the foo() function, the variable x will take value defined in the bar() function i.e x
= 25. This is because we have used global keyword in x to create global variable inside the
bar() function (local scope).

If we make any changes inside the bar() function, the changes appear outside the local scope,
i.e. foo().

"operator "Standard operators as functions:

The operator module exports a set of efficient functions corresponding to the


intrinsic operators of Python.

For example, operator.add(x, y) is equivalent to the expression x+y.

Many function names are those used for special methods, without the double
underscores. For backward compatibility, many of these have a variant with the
double underscores kept. The variants without the double underscores are preferred
for clarity.

The functions fall into categories that perform object comparisons, logical
operations, mathematical operations and sequence operations.

The object comparison functions are useful for all objects, and are named after the
rich comparison operators they support:
operator.lt(a, b)

operator.le(a, b)

operator.eq(a, b)¶

operator.ne(a, b)

operator.ge(a, b)

operator.gt(a, b)

operator.__lt__(a, b)

operator.__le__(a, b)

operator.__eq__(a, b)

operator.__ne__(a, b)

operator.__ge__(a, b)

operator.__gt__(a, b)

Operation Syntax Function


Addition a + b add(a, b)
Concatenation seq1 + seq2 concat (seq1, seq2)
Containment Test obj in seq contains(seq, obj)
Division a / b truediv(a, b)
Division a // b floordiv(a, b)
Bitwise And a & b and_(a, b)
Bitwise Exclusive Or a ^ b xor (a, b)
Bitwise Inversion ~ a Invert (a)
Bitwise Or a | b or_(a, b)
Exponentiation a ** b pow(a, b)
Operation Syntax Function
Identity a is b is_(a, b)
Identity a is not b is_not(a, b)
Indexed Assignment obj[k] = v setitem(obj, k, v)
Indexed Deletion del obj[k] delitem(obj, k)
Indexing obj[k] getitem(obj, k)
Left Shift a << b lshift(a, b)
Modulo a % b mod(a, b)
Multiplication a * b mul(a, b)
Matrix Multiplication a @ b matmul(a, b)
Negation
- a neg(a)
(Arithmetic)
Negation (Logical) not a not_(a)
Positive + a pos(a)
Right Shift a >> b rshift(a, b)
Slice Assignment seq[i:j] = values setitem(seq, slice(i, j), values)
Slice Deletion del seq[i:j] delitem(seq, slice(i, j))
Slicing seq[i:j] getitem(seq, slice(i, j))
String Formatting s % obj mod(s, obj)
Subtraction a - b sub(a, b)
Truth Test obj truth(obj)
Ordering a < b lt(a, b)
Ordering a <= b le(a, b)
Equality a == b eq(a, b)
Difference a != b ne(a, b)
Ordering a >= b ge(a, b)
Ordering a > b gt(a, b)
In-place Operators
Python Modules

What are modules in Python?


Modules refer to a file containing Python statements and definitions.

A file containing Python code, for example: example.py, is called a module, and its module
name would be example.

We use modules to break down large programs into small manageable and organized files.

We can define our most used functions in a module and import it, instead of copying their
definitions into different programs.

Let us create a module. Type the following and save it as example.py.

# Python Module example

def add(a, b):


"""This program adds two
numbers and return the result"""

result = a + b
return result

Here, we have defined a function add() inside a module named example. The function takes in
two numbers and returns their sum.

How to import modules in Python?


We can import the definitions inside a module to another module or the interactive interpreter in
Python.

We use the import keyword to do this. To import our previously defined module example, we
type the following in the Python prompt.

>>> import example

This does not import the names of the functions defined in example directly in the current
symbol table. It only imports the module name example there.

Using the module name we can access the function using the dot . operator. For example:
>>> example.add(4,5.5)
9.5

Python has tons of standard modules. You can check out the full list of Python standard modules
and their use cases. These files are in the Lib directory inside the location where you installed
Python.

Standard modules can be imported the same way as we import our user-defined modules.

There are various ways to import modules. They are listed below..

Python import statement

We can import a module using the import statement and access the definitions inside it using the
dot operator as described above. Here is an example.

# import statement example


# to import standard module math

import math
print("The value of pi is", math.pi)

When you run the program, the output will be:

The value of pi is 3.141592653589793

We can import a module by renaming it as follows:

# import module by renaming it

import math as m
print("The value of pi is", m.pi)

We have renamed the math module as m. This can save us typing time in some cases.

Note that the name math is not recognized in our scope. Hence, math.pi is invalid, and m.pi is
the correct implementation.

Python from...import statement

We can import specific names from a module without importing the module as a whole. Here is
an example.

# import only pi from math module


from math import pi
print("The value of pi is", pi)

Here, we imported only the pi attribute from the math module.

In such cases, we don't use the dot operator. We can also import multiple attributes as follows:

>>> from math import pi, e


>>> pi
3.141592653589793
>>> e
2.718281828459045

Import all names

We can import all names(definitions) from a module using the following construct:

# import all names from the standard module math

from math import *


print("The value of pi is", pi)

ere, we have imported all the definitions from the math module. This includes all names visible
in our scope except those beginning with an underscore(private definitions).

Importing everything with the asterisk (*) symbol is not a good programming practice. This can
lead to duplicate definitions for an identifier. It also hampers the readability of our code.
Python Module Search Path
While importing a module, Python looks at several places. Interpreter first looks for a built-in
module. Then(if built-in module not found), Python looks into a list of directories defined in
sys.path.

The search is in this order.

 The current directory.


 PYTHONPATH (an environment variable with a list of directories).
 The installation-dependent default directory.

>>> import sys


>>> sys.path
['',
'C:\\Python33\\Lib\\idlelib',
'C:\\Windows\\system32\\python33.zip',
'C:\\Python33\\DLLs',
'C:\\Python33\\lib',
'C:\\Python33',
'C:\\Python33\\lib\\site-packages']

We can add and modify this list to add our own path.

Reloading a module
The Python interpreter imports a module only once during a session. This makes things more
efficient. Here is an example to show how this works.

Suppose we have the following code in a module named my_module.

# This module shows the effect of


# multiple imports and reload

print("This code got executed")

Now we see the effect of multiple imports.

>>> import my_module


This code got executed
>>> import my_module
>>> import my_module
We can see that our code got executed only once. This goes to say that our module was imported
only once.

Now if our module changed during the course of the program, we would have to reload it.One
way to do this is to restart the interpreter. But this does not help much.

Python provides a more efficient way of doing this.

" We can use the reload() function inside the imp module to reload a module. "

We can do it in the following ways:

>>> import imp


>>> import my_module
This code got executed
>>> import my_module
>>> imp.reload(my_module)
This code got executed
<module 'my_module' from '.\\my_module.py'>

The dir() built-in function


We can use the dir() function to find out names that are defined inside a module.

For example, we have defined a function add() in the module example that we had in the
beginning.

We can use dir in example module in the following way:

>>> dir(example)
['__builtins__',
'__cached__',
'__doc__',
'__file__',
'__initializing__',
'__loader__',
'__name__',
'__package__',
'add']

Here, we can see a sorted list of names (along with add). All other names that begin with an
underscore are default Python attributes associated with the module (not user-defined).

For example, the __name__ attribute contains the name of the module.

>>> import example


>>> example.__name__
'example'
All the names defined in our current namespace can be found out using the dir() function
without any arguments.

>>> a = 1
>>> b = "hello"
>>> import math
>>> dir()
['__builtins__', '__doc__', '__name__', 'a', 'b', 'math', 'pyscripter']
Python Package:
What are packages?
We don't usually store all of our files on our computer in the same location.

We use a well-organized hierarchy of directories for easier access.

Similar files are kept in the same directory,

for example,

we may keep all the songs in the "music" directory. Analogous to this, Python has packages for
directories and modules for files.

As our application program grows larger in size with a lot of modules, we place similar modules
in one package and different modules in different packages. This makes a project (program) easy
to manage and conceptually clear.

Similarly, as a directory can contain subdirectories and files, a Python package can have sub-
packages and modules.

A directory must contain a

file named __init__.py

in order for Python to consider it as a package. This file can be left empty but we generally place
the initialization code for that package in this file.
Here is an example. Suppose we are developing a game

One possible organization of packages and modules could be as shown in the figure below.

Package Module Structure in Python Programming

Importing module from a package


We can import modules from packages using the

dot (.) operator.

For example, if we want to import the start module in the above example, it can be done as
follows:

import Game.Level.start

Now,

if this module contains a function named

select_difficulty(), we must use the full name to reference it.

Game.Level.start.select_difficulty(2)

If this construct seems lengthy, we can import the module without the package prefix as follows:

from Game.Level import start


We can now call the function simply as follows:

start.select_difficulty(2)

Another way of importing just the required function (or class or variable) from a module within a
package would be as follows:

from Game.Level.start import select_difficulty

Now we can directly call this function.

select_difficulty(2)

Although easier, this method is not recommended. Using the full namespace avoids confusion
and prevents two same identifier names from colliding.

While importing packages, Python looks in the list of directories defined in sys.path, similar as
for module search path.

Python Data types

Python Numbers, Type Conversion and Mathematics

Python supports integers, floating-point numbers and complex numbers. They are defined as int,
float, and complex classes in Python.

Integers and floating points are separated by the presence or absence of a decimal point. For
instance, 5 is an integer whereas 5.0 is a floating-point number.

Complex numbers are written in the form, x + yj, where x is the real part and y is the imaginary
part.

We can use the

type()
function to know which class a variable or a value belongs to and isinstance() function to
check if it belongs to a particular class
a = 5

print(type(a))

print(type(5.0))

c = 5 + 3j
print(c + 3)

print(isinstance(c, complex))

When we run the above program, we get the following output:

<class 'int'>
<class 'float'>
(8+3j)
True

While integers can be of any length, a floating-point number is accurate only up to 15 decimal
places (the 16th place is inaccurate).

The numbers we deal with every day are of the decimal (base 10) number system.

But computer programmers (generally embedded programmers) need to work with

binary (base 2),

hexadecimal (base 16) and

octal (base 8) number systems.

In Python, we can represent these numbers by appropriately placing a prefix before that number.
The following table lists these prefixes.

Number System Prefix


Binary '0b' or '0B'
Octal '0o' or '0O'
Hexadecimal '0x' or '0X'

Here are some examples

Binary----------------------- 0b

Octal------------------------ 0o

Hexadecimal-------------- 0x
e.g.------------

# Output: 107

print(0b1101011)

# Output: 253 (251 + 2)


print(0xFB + 0b10)

# Output: 13

print(0o15) When you run the program, the output will be:

107
253
13

Type Conversion
We can convert one type of number into another. This is also known as coercion.

Operations like addition, subtraction coerce integer to float implicitly (automatically), if one of
the operands is float.

>>> 1 + 2.0
3.0

We can see above that 1 (integer) is coerced into 1.0 (float) for addition and the result is also a
floating point number.

We can also use built-in functions like int(), float() and complex() to convert between types
explicitly. These functions can even convert from strings.

>>> int(2.3)
2
>>> int(-2.8)
-2
>>> float(5)
5.0
>>> complex('3+5j')
(3+5j)

When converting from float to integer, the number gets truncated (decimal parts are removed).
Python Decimal
Python built-in class float performs some calculations that might amaze us. We all know that the
sum of 1.1 and 2.2 is 3.3, but Python seems to disagree.

>>> (1.1 + 2.2) == 3.3


False

What is going on?

It turns out that floating-point numbers are implemented in computer hardware as binary
fractions as the computer only understands binary (0 and 1). Due to this reason, most of the
decimal fractions we know, cannot be accurately stored in our computer.

Let's take an example.

We cannot represent the fraction 1/3 as a decimal number.

This will give 0.33333333... which is infinitely long, and we can only approximate it.

It turns out that the decimal fraction 0.1 will result in an infinitely long binary fraction of
0.000110011001100110011... and our computer only stores a finite number of it.

This will only approximate 0.1 but never be equal. Hence, it is the limitation of our computer
hardware and not an error in Python.

>>> 1.1 + 2.2


3.3000000000000003

To overcome this issue, we can use the decimal module that comes with Python. While floating-
point numbers have precision up to 15 decimal places, the decimal module has user-settable
precision.

Let's see the difference:

import decimal

print(0.1)

print(decimal.Decimal(0.1))

Output

0.1
0.1000000000000000055511151231257827021181583404541015625

This module is used when we want to carry out decimal calculations as we learned in school.
It also preserves significance. We know 25.50 kg is more accurate than 25.5 kg as it has two
significant decimal places compared to one.

from decimal import Decimal as D

print(D('1.1') + D('2.2'))

print(D('1.2') * D('2.50'))

Output

3.3
3.000

Notice the trailing zeroes in the above example.

We might ask, why not implement Decimal every time, instead of float? The main reason is
efficiency. Floating point operations are carried out must faster than Decimal operations.

When to use Decimal instead of float?

We generally use Decimal in the following cases.

 When we are making financial applications that need exact decimal representation.
 When we want to control the level of precision required.
 When we want to implement the notion of significant decimal places.

Python Fractions
Python provides operations involving fractional numbers through its fractions module.

A fraction has a numerator and a denominator, both of which are integers. This module has
support for rational number arithmetic.

We can create Fraction objects in various ways. Let's have a look at them.

import fractions

print(fractions.Fraction(1.5))

print(fractions.Fraction(5))

print(fractions.Fraction(1,3))

 Output
 3/2
 5
 1/3

While creating Fraction from float, we might get some unusual results. This is due to the
imperfect binary floating point number representation as discussed in the previous section.

Fortunately, Fraction allows us to instantiate with string as well. This is the preferred
option when using decimal numbers.

 import fractions

# As float
# Output: 2476979795053773/2251799813685248
print(fractions.Fraction(1.1))

# As string
# Output: 11/10
print(fractions.Fraction('1.1'))

Output

2476979795053773/2251799813685248
11/10

This data type supports all basic operations. Here are a few examples.

from fractions import Fraction as F

print(F(1, 3) + F(1, 3))

print(1 / F(5, 6))

print(F(-3, 10) > 0)

print(F(-3, 10) < 0)

 Output
 2/3
 6/5
 False
 True
Python Mathematics

Python offers modules like math and random to carry out different mathematics like
trigonometry, logarithms, probability and statistics, etc.

import math

print(math.pi)

print(math.cos(math.pi))

print(math.exp(10))

print(math.log10(1000))
print(math.sinh(1))

print(math.factorial(6))

 Output
 3.141592653589793
 -1.0
 22026.465794806718
 3.0
 1.1752011936438014
 720

Here is the full list of functions and attributes available in the Python math module.

import random

print(random.randrange(10, 20))

x = ['a', 'b', 'c', 'd', 'e']

# Get random choice


print(random.choice(x))

# Shuffle x
random.shuffle(x)

# Print the shuffled x


print(x)

# Print random element


print(random.random())

When we run the above program we get the output as follows.(Values may be different due
to the random behavior)

18
e
['c', 'e', 'd', 'b', 'a']
0.5682821194654443

Here is the full list of functions and attributes available in the Python random module.

Python List
Python offers a range of compound data types often referred to as sequences. List is one of the most
frequently used and very versatile data types used in Python.

How to create a list?


In Python programming, a list is created by placing all the items (elements) inside square
brackets [], separated by commas.

It can have any number of items and they may be of different types (integer, float, string etc.).

# empty list
my_list = []

# list of integers
my_list = [1, 2, 3]

# list with mixed data types


my_list = [1, "Hello", 3.4]

A list can also have another list as an item. This is called a nested list.

# nested list
my_list = ["mouse", [8, 4, 6], ['a']]
Access List Elements:

There are various ways in which we can access the elements of a list.

List Index

We can use the index operator [] to access an item in a list. In Python, indices start at 0. So, a
list having 5 elements will have an index from 0 to 4.

Trying to access indexes other than these will raise an IndexError. The index must be an
integer. We can't use float or other types, this will result in TypeError.

Nested lists are accessed using nested indexing.

# List indexing

my_list = ['p', 'r', 'o', 'b', 'e']

# Output: p
print(my_list[0])

# Output: o
print(my_list[2])

# Output: e
print(my_list[4])

# Nested List
n_list = ["Happy", [2, 0, 1, 5]]

# Nested indexing
print(n_list[0][1])

print(n_list[1][3])

# Error! Only integer can be used for indexing


print(my_list[4.0])

Output

p
o
e
a
5
Traceback (most recent call last):
File "<string>", line 21, in <module>
TypeError: list indices must be integers or slices, not float
Negative indexing

Python allows negative indexing for its sequences. The index of -1 refers to the last item, -2 to
the second last item and so on.

# Negative indexing in lists


my_list = ['p','r','o','b','e']

print(my_list[-1])

print(my_list[-5])

When we run the above program, we will get the following output:

e
p

List indexing in Python

How to slice lists in Python?


We can access a range of items in a list by using the slicing operator :(colon).

# List slicing in Python

my_list = ['p','r','o','g','r','a','m','i','z']

# elements 3rd to 5th


print(my_list[2:5])

# elements beginning to 4th


print(my_list[:-5])

# elements 6th to end


print(my_list[5:])

# elements beginning to end


print(my_list[:])
Output

['o', 'g', 'r']


['p', 'r', 'o', 'g']
['a', 'm', 'i', 'z']
['p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z']

Slicing can be best visualized by considering the index to be between the elements as shown below. So if
we want to access a range, we need two indices that will slice that portion from the list.

Element Slicing from a Add/Change List Elements


Lists are mutable, meaning their elements can be changed unlike string or tuple.

We can use the assignment operator = to change an item or a range of items.

# Correcting mistake values in a list


odd = [2, 4, 6, 8]

# change the 1st item


odd[0] = 1

print(odd)

# change 2nd to 4th items


odd[1:4] = [3, 5, 7]

print(odd)

Output

[1, 4, 6, 8]
[1, 3, 5, 7]

list in Python
We can add one item to a list using the append() method or add several items using extend()
method.
# Appending and Extending lists in Python
odd = [1, 3, 5]

odd.append(7)

print(odd)

odd.extend([9, 11, 13])

print(odd)

Output

[1, 3, 5, 7]
[1, 3, 5, 7, 9, 11, 13]

We can also use + operator to combine two lists. This is also called concatenation.

The * operator repeats a list for the given number of times.

# Concatenating and repeating lists


odd = [1, 3, 5]

print(odd + [9, 7, 5])

print(["re"] * 3)

Output

[1, 3, 5, 9, 7, 5]
['re', 're', 're']

Furthermore, we can insert one item at a desired location by using the method insert() or insert
multiple items by squeezing it into an empty slice of a list.

#
[1, 3, 9]
[1, 3, 5, 7, 9]

Delete/Remove List Elements


We can delete one or more items from a list using the keyword del. It can even delete the list
entirely.

# Deleting list items


my_list = ['p', 'r', 'o', 'b', 'l', 'e', 'm']

# delete one item


del my_list[2]

print(my_list)

# delete multiple items


del my_list[1:5]

print(my_list)

# delete entire list


del my_list

# Error: List not defined


print(my_list)

Output

['p', 'r', 'b', 'l', 'e', 'm']


['p', 'm']
Traceback (most recent call last):
File "<string>", line 18, in <module>
NameError: name 'my_list' is not defined

We can use remove() method to remove the given item or pop() method to remove an item at
the given index.

The pop() method removes and returns the last item if the index is not provided. This helps us
implement lists as stacks (first in, last out data structure).

We can also use the clear() method to empty a list.

my_list = ['p','r','o','b','l','e','m']
my_list.remove('p')

# Output: ['r', 'o', 'b', 'l', 'e', 'm']


print(my_list)

# Output: 'o'
print(my_list.pop(1))

# Output: ['r', 'b', 'l', 'e', 'm']


print(my_list)

# Output: 'm'
print(my_list.pop())

# Output: ['r', 'b', 'l', 'e']


print(my_list)

my_list.clear()

# Output: []
print(my_list)
Output

['r', 'o', 'b', 'l', 'e', 'm']


o
['r', 'b', 'l', 'e', 'm']
m
['r', 'b', 'l', 'e']
[]

Finally, we can also delete items in a list by assigning an empty list to a slice of elements.

>>> my_list = ['p','r','o','b','l','e','m']


>>> my_list[2:3] = []
>>> my_list
['p', 'r', 'b', 'l', 'e', 'm']
>>> my_list[2:5] = []
>>> my_list
['p', 'r', 'm']

Python List Methods


Methods that are available with list objects in Python programming are tabulated below.

They are accessed as list.method(). Some of the methods have already been used above.

Python List Methods

append() - Add an element to the end of the list

extend() - Add all elements of a list to the another list

insert() - Insert an item at the defined index

remove() - Removes an item from the list

pop() - Removes and returns an element at the given index

clear() - Removes all items from the list

index() - Returns the index of the first matched item

count() - Returns the count of the number of items passed as an argument

sort() - Sort items in a list in ascending order

reverse() - Reverse the order of items in the list

copy() - Returns a shallow copy of the list


Some examples of Python list methods:

# Python list methods


my_list = [3, 8, 1, 6, 0, 8, 4]

# Output: 1
print(my_list.index(8))

# Output: 2
print(my_list.count(8))

my_list.sort()

# Output: [0, 1, 3, 4, 6, 8, 8]
print(my_list)

my_list.reverse()

# Output: [8, 8, 6, 4, 3, 1, 0]
print(my_list)

Output

1
2
[0, 1, 3, 4, 6, 8, 8]
[8, 8, 6, 4, 3, 1, 0]

List Comprehension: Elegant way to create Lists


List comprehension is an elegant and concise way to create a new list from an existing list in
Python.

A list comprehension consists of an expression followed by for statement inside square brackets.

Here is an example to make a list with each item being increasing power of 2.

pow2 = [2 ** x for x in range(10)]


print(pow2)

Output

[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

This code is equivalent to:

pow2 = []
for x in range(10):
pow2.append(2 ** x)
A list comprehension can optionally contain more for or if statements. An optional if statement
can filter out items for the new list. Here are some examples.

>>> pow2 = [2 ** x for x in range(10) if x > 5]


>>> pow2
[64, 128, 256, 512]
>>> odd = [x for x in range(20) if x % 2 == 1]
>>> odd
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
>>> [x+y for x in ['Python ','C '] for y in ['Language','Programming']]
['Python Language', 'Python Programming', 'C Language', 'C Programming']

Other List Operations in Python


List Membership Test

We can test if an item exists in a list or not, using the keyword in.

my_list = ['p', 'r', 'o', 'b', 'l', 'e', 'm']

# Output: True
print('p' in my_list)

# Output: False
print('a' in my_list)

# Output: True
print('c' not in my_list)

Output

True
False
True

Iterating Through a List

Using a for loop we can iterate through each item in a list.

for fruit in ['apple','banana','mango']:


print("I like",fruit)

Output

I like apple
I like banana
I like mango

Ngurnule
Python Tuple

A tuple in Python is similar to a list. The difference between the two is that we cannot change the
elements of a tuple once it is assigned whereas we can change the elements of a list.

Creating a Tuple
A tuple is created by placing all the items (elements) inside parentheses (), separated by
commas. The parentheses are optional, however, it is a good practice to use them.

A tuple can have any number of items and they may be of different types (integer, float, list,
string, etc.).

# Different types of tuples

# Empty tuple
my_tuple = ()
print(my_tuple)

# Tuple having integers


my_tuple = (1, 2, 3)
print(my_tuple)

# tuple with mixed datatypes


my_tuple = (1, "Hello", 3.4)
print(my_tuple)

# nested tuple
my_tuple = ("mouse", [8, 4, 6], (1, 2, 3))
print(my_tuple)

Output

()
(1, 2, 3)
(1, 'Hello', 3.4)
('mouse', [8, 4, 6], (1, 2, 3))

A tuple can also be created without using parentheses. This is known as tuple packing.

my_tuple = 3, 4.6, "dog"


print(my_tuple)

# tuple unpacking is also possible


a, b, c = my_tuple

print(a) # 3
print(b) # 4.6
print(c) # dog
Output

(3, 4.6, 'dog')


3
4.6
dog

Creating a tuple with one element is a bit tricky.

Having one element within parentheses is not enough. We will need a trailing comma to indicate
that it is, in fact, a tuple.

my_tuple = ("hello")
print(type(my_tuple)) # <class 'str'>

# Creating a tuple having one element


my_tuple = ("hello",)
print(type(my_tuple)) # <class 'tuple'>

# Parentheses is optional
my_tuple = "hello",
print(type(my_tuple)) # <class 'tuple'>

Output

<class 'str'>
<class 'tuple'>
<class 'tuple'>

Access Tuple Elements


There are various ways in which we can access the elements of a tuple.

1. Indexing

We can use the index operator [] to access an item in a tuple, where the index starts from 0.

So, a tuple having 6 elements will have indices from 0 to 5. Trying to access an index outside of
the tuple index range(6,7,... in this example) will raise an IndexError.

The index must be an integer, so we cannot use float or other types. This will result in
TypeError.

Likewise, nested tuples are accessed using nested indexing, as shown in the example below.

# Accessing tuple elements using indexing


my_tuple = ('p','e','r','m','i','t')

print(my_tuple[0]) # 'p'
print(my_tuple[5]) # 't'

# IndexError: list index out of range


# print(my_tuple[6])

# Index must be an integer


# TypeError: list indices must be integers, not float
# my_tuple[2.0]

# nested tuple
n_tuple = ("mouse", [8, 4, 6], (1, 2, 3))

# nested index
print(n_tuple[0][3]) # 's'
print(n_tuple[1][1]) # 4

Output

p
t
s
4

2. Negative Indexing

Python allows negative indexing for its sequences.

The index of -1 refers to the last item, -2 to the second last item and so on.

# Negative indexing for accessing tuple elements


my_tuple = ('p', 'e', 'r', 'm', 'i', 't')

# Output: 't'
print(my_tuple[-1])

# Output: 'p'
print(my_tuple[-6])

Output

t
p

3. Slicing

We can access a range of items in a tuple by using the slicing operator colon :.

# Accessing tuple elements using slicing


my_tuple = ('p','r','o','g','r','a','m','i','z')
# elements 2nd to 4th
# Output: ('r', 'o', 'g')
print(my_tuple[1:4])

# elements beginning to 2nd


# Output: ('p', 'r')
print(my_tuple[:-7])

# elements 8th to end


# Output: ('i', 'z')
print(my_tuple[7:])

# elements beginning to end


# Output: ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')
print(my_tuple[:])

Output

('r', 'o', 'g')


('p', 'r')
('i', 'z')
('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')

Slicing can be best visualized by considering the index to be between the elements as shown
below. So if we want to access a range, we need the index that will slice the portion from the
tuple.

Element Slicing in Python

Changing a Tuple
Unlike lists, tuples are immutable.

This means that elements of a tuple cannot be changed once they have been assigned. But, if the
element is itself a mutable data type like list, its nested items can be changed.

We can also assign a tuple to different values (reassignment).

# Changing tuple values


my_tuple = (4, 2, 3, [6, 5])
# TypeError: 'tuple' object does not support item assignment
# my_tuple[1] = 9

# However, item of mutable element can be changed


my_tuple[3][0] = 9 # Output: (4, 2, 3, [9, 5])
print(my_tuple)

# Tuples can be reassigned


my_tuple = ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')

# Output: ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')
print(my_tuple)

Output

(4, 2, 3, [9, 5])


('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')

We can use + operator to combine two tuples. This is called concatenation.

We can also repeat the elements in a tuple for a given number of times using the * operator.

Both + and * operations result in a new tuple.

# Concatenation
# Output: (1, 2, 3, 4, 5, 6)
print((1, 2, 3) + (4, 5, 6))

# Repeat
# Output: ('Repeat', 'Repeat', 'Repeat')
print(("Repeat",) * 3)

Output

(1, 2, 3, 4, 5, 6)
('Repeat', 'Repeat', 'Repeat')

Deleting a Tuple
As discussed above, we cannot change the elements in a tuple. It means that we cannot delete or
remove items from a tuple.

Deleting a tuple entirely, however, is possible using the keyword del.

# Deleting tuples
my_tuple = ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')

# can't delete items


# TypeError: 'tuple' object doesn't support item deletion
# del my_tuple[3]
# Can delete an entire tuple
del my_tuple

# NameError: name 'my_tuple' is not defined


print(my_tuple)

Output

Traceback (most recent call last):


File "<string>", line 12, in <module>
NameError: name 'my_tuple' is not defined

Tuple Methods
Methods that add items or remove items are not available with tuple. Only the following two
methods are available.

Some examples of Python tuple methods:

my_tuple = ('a', 'p', 'p', 'l', 'e',)

print(my_tuple.count('p')) # Output: 2
print(my_tuple.index('l')) # Output: 3

Output

2
3

Other Tuple Operations


1. Tuple Membership Test

We can test if an item exists in a tuple or not, using the keyword in.

# Membership test in tuple


my_tuple = ('a', 'p', 'p', 'l', 'e',)

# In operation
print('a' in my_tuple)
print('b' in my_tuple)

# Not in operation
print('g' not in my_tuple)

Output
True
False
True

2. Iterating Through a Tuple

We can use a for loop to iterate through each item in a tuple.

# Using a for loop to iterate through a tuple


for name in ('John', 'Kate'):
print("Hello", name)

Output

Hello John
Hello Kate

Advantages of Tuple over List

Since tuples are quite similar to lists, both of them are used in similar situations. However, there
are certain advantages of implementing a tuple over a list.

Below listed are some of the main advantages:

 We generally use tuples for heterogeneous (different) data types and lists for homogeneous
(similar) data types.
 Since tuples are immutable, iterating through a tuple is faster than with list. So there is a slight
performance boost.
 Tuples that contain immutable elements can be used as a key for a dictionary. With lists, this is
not possible.
 If you have data that doesn't change, implementing it as tuple will guarantee that it remains
write-protected.

Python Strings

What is String in Python?


A string is a sequence of characters.

A character is simply a symbol. For example, the English language has 26 characters.

Computers do not deal with characters, they deal with numbers (binary). Even though you may
see characters on your screen, internally it is stored and manipulated as a combination of 0s and
1s.

This conversion of character to a number is called encoding, and the reverse process is decoding.
ASCII and Unicode are some of the popular encodings used.

In Python, a string is a sequence of Unicode characters. Unicode was introduced to include every
character in all languages and bring uniformity in encoding. You can learn about Unicode from
Python Unicode.

How to create a string in Python?


Strings can be created by enclosing characters inside a single quote or double-quotes. Even triple
quotes can be used in Python but generally used to represent multiline strings and docstrings.

# defining strings in Python


# all of the following are equivalent
my_string = 'Hello'
print(my_string)

my_string = "Hello"
print(my_string)

my_string = '''Hello'''
print(my_string)

# triple quotes string can extend multiple lines


my_string = """Hello, welcome to
the world of Python"""
print(my_string)

When you run the program, the output will be:

Hello
Hello
Hello
Hello, welcome to
the world of Python

How to access characters in a string?


We can access individual characters using indexing and a range of characters using slicing. Index
starts from 0. Trying to access a character out of index range will raise an IndexError. The
index must be an integer. We can't use floats or other types, this will result into TypeError.

Python allows negative indexing for its sequences.

The index of -1 refers to the last item, -2 to the second last item and so on. We can access a
range of items in a string by using the slicing operator :(colon).

#Accessing string characters in Python


str = 'programiz'
print('str = ', str)

#first character
print('str[0] = ', str[0])

#last character
print('str[-1] = ', str[-1])

#slicing 2nd to 5th character


print('str[1:5] = ', str[1:5])

#slicing 6
th to 2nd last character
print('str[5:-2] = ', str[5:-2])

When we run the above program, we get the following output:

str = programiz
str[0] = p
str[-1] = z
str[1:5] = rogr
str[5:-2] = am

If we try to access an index out of the range or use numbers other than an integer, we will get
errors.

# index must be in range


>>> my_string[15]
...
IndexError: string index out of range

# index must be an integer


>>> my_string[1.5]
...
TypeError: string indices must be integers

Slicing can be best visualized by considering the index to be between the elements as shown
below.

f we want to access a range, we need the index that will slice the portion from the string.
String Slicing in Python

How to change or delete a string?


Strings are immutable. This means that elements of a string cannot be changed once they have
been assigned. We can simply reassign different strings to the same name.

>>> my_string = 'programiz'


>>> my_string[5] = 'a'
...
TypeError: 'str' object does not support item assignment
>>> my_string = 'Python'
>>> my_string
'Python'

We cannot delete or remove characters from a string. But deleting the string entirely is possible
using the del keyword.

>>> del my_string[1]


...
TypeError: 'str' object doesn't support item deletion
>>> del my_string
>>> my_string
...
NameError: name 'my_string' is not defined

Python String Operations


There are many operations that can be performed with strings which makes it one of the most
used data types in Python.

To learn more about the data types available in Python visit: Python Data Types
Concatenation of Two or More Strings

Joining of two or more strings into a single one is called concatenation.

The + operator does this in Python. Simply writing two string literals together also concatenates
them.

The * operator can be used to repeat the string for a given number of times.

# Python String Operations


str1 = 'Hello'
str2 ='World!'

# using +
print('str1 + str2 = ', str1 + str2)

# using *
print('str1 * 3 =', str1 * 3)

When we run the above program, we get the following output:

str1 + str2 = HelloWorld!


str1 * 3 = HelloHelloHello

Writing two string literals together also concatenates them like + operator.

If we want to concatenate strings in different lines, we can use parentheses.

>>> # two string literals together


>>> 'Hello ''World!'
'Hello World!'

>>> # using parentheses


>>> s = ('Hello '
... 'World')
>>> s
'Hello World'

Iterating Through a string

We can iterate through a string using a for loop. Here is an example to count the number of 'l's in
a string.

# Iterating through a string


count = 0
for letter in 'Hello World':
if(letter == 'l'):
count += 1
print(count,'letters found')

When we run the above program, we get the following output:


3 letters found

String Membership Test

We can test if a substring exists within a string or not, using the keyword in.

>>> 'a' in 'program'


True
>>> 'at' not in 'battle'
False

Built-in functions to Work with Python

Various built-in functions that work with sequence work with strings as well.

Some of the commonly used ones are enumerate() and len(). The enumerate()
function returns an enumerate object. It contains the index and value of all the items in the string
as pairs. This can be useful for iteration.

Similarly, len() returns the length (number of characters) of the string.

str = 'cold'

# enumerate()
list_enumerate = list(enumerate(str))
print('list(enumerate(str) = ', list_enumerate)

#character count
print('len(str) = ', len(str))

When we run the above program, we get the following output:

list(enumerate(str) = [(0, 'c'), (1, 'o'), (2, 'l'), (3, 'd')]


len(str) = 4

Python String Formatting


Escape Sequence

If we want to print a text like He said, "What's there?", we can neither use single
quotes nor double quotes. This will result in a SyntaxError as the text itself contains both single
and double quotes.

>>> print("He said, "What's there?"")


...
SyntaxError: invalid syntax
>>> print('He said, "What's there?"')
...
SyntaxError: invalid syntax
One way to get around this problem is to use triple quotes. Alternatively, we can use escape
sequences.

An escape sequence starts with a backslash and is interpreted differently. If we use a single quote
to represent a string, all the single quotes inside the string must be escaped. Similar is the case
with double quotes. Here is how it can be done to represent the above text.

# using triple quotes


print('''He said, "What's there?"''')

# escaping single quotes


print('He said, "What\'s there?"')

# escaping double quotes


print("He said, \"What's there?\"")

When we run the above program, we get the following output:

He said, "What's there?"


He said, "What's there?"
He said, "What's there?"

Here is a list of all the escape sequences supported by Python.

Escape Sequence Description

\newline Backslash and newline ignored

\\ Backslash

\' Single quote

\" Double quote

\a ASCII Bell

\b ASCII Backspace

\f ASCII Formfeed

\n ASCII Linefeed

\r ASCII Carriage Return

\t ASCII Horizontal Tab

\v ASCII Vertical Tab

\ooo Character with octal value ooo


\xHH Character with hexadecimal value HH

Here are some examples

>>> print("C:\\Python32\\Lib")
C:\Python32\Lib

>>> print("This is printed\nin two lines")


This is printed
in two lines

>>> print("This is \x48\x45\x58 representation")


This is HEX representation

Raw String to ignore escape sequence

Sometimes we may wish to ignore the escape sequences inside a string. To do this we can place
r or R in front of the string. This will imply that it is a raw string and any escape sequence inside
it will be ignored.

>>> print("This is \x61 \ngood example")


This is a
good example
>>> print(r"This is \x61 \ngood example")
This is \x61 \ngood example

The format() Method for Formatting Strings

The format() method that is available with the string object is very versatile and powerful in
formatting strings. Format strings contain curly braces {} as placeholders or replacement fields
which get replaced.

We can use positional arguments or keyword arguments to specify the order.

# Python string format() method

# default(implicit) order
default_order = "{}, {} and {}".format('John','Bill','Sean')
print('\n--- Default Order ---')
print(default_order)

# order using positional argument


positional_order = "{1}, {0} and {2}".format('John','Bill','Sean')
print('\n--- Positional Order ---')
print(positional_order)

# order using keyword argument


keyword_order = "{s}, {b} and {j}".format(j='John',b='Bill',s='Sean')
print('\n--- Keyword Order ---')
print(keyword_order)

When we run the above program, we get the following output:

--- Default Order ---


John, Bill and Sean

--- Positional Order ---


Bill, John and Sean

--- Keyword Order ---


Sean, Bill and John

The format() method can have optional format specifications. They are separated from the field
name using colon. For example, we can left-justify <, right-justify > or center ^ a string in the
given space.

We can also format integers as binary, hexadecimal, etc. and floats can be rounded or displayed
in the exponent format. There are tons of formatting you can use. Visit here for all the string
formatting available with the format() method.

>>> # formatting integers


>>> "Binary representation of {0} is {0:b}".format(12)
'Binary representation of 12 is 1100'

>>> # formatting floats


>>> "Exponent representation: {0:e}".format(1566.345)
'Exponent representation: 1.566345e+03'

>>> # round off


>>> "One third is: {0:.3f}".format(1/3)
'One third is: 0.333'

>>> # string alignment


>>> "|{:<10}|{:^10}|{:>10}|".format('butter','bread','ham')
'|butter | bread | ham|'

Old style formatting

We can even format strings like the old sprintf() style used in C programming language. We
use the % operator to accomplish this.

>>> x = 12.3456789
>>> print('The value of x is %3.2f' %x)
The value of x is 12.35
>>> print('The value of x is %3.4f' %x)
The value of x is 12.3457

Common Python String Methods


There are numerous methods available with the string object. The format() method that we
mentioned above is one of them. Some of the commonly used methods are lower(), upper(),
join(), split(), find(), replace() etc. Here is a complete list of all the built-in methods to
work with strings in Python.

>>> "PrOgRaMiZ".lower()
'programiz'
>>> "PrOgRaMiZ".upper()
'PROGRAMIZ'
>>> "This will split all words into a list".split()
['This', 'will', 'split', 'all', 'words', 'into', 'a', 'list']
>>> ' '.join(['This', 'will', 'join', 'all', 'words', 'into', 'a', 'string'])
'This will join all words into a string'
>>> 'Happy New Year'.find('ew')
7
>>> 'Happy New Year'.replace('Happy','Brilliant')
'Brilliant New Year'

Python Sets
A set is an unordered collection of items. Every set element is unique (no duplicates) and must
be immutable (cannot be changed).

However, a set itself is mutable. We can add or remove items from it.

Sets can also be used to perform mathematical set operations like union, intersection, symmetric
difference, etc.

Creating Python Sets


A set is created by placing all the items (elements) inside curly braces {}, separated by comma,
or by using the built-in set() function.
It can have any number of items and they may be of different types (integer, float, tuple, string
etc.). But a set cannot have mutable elements like lists, sets or dictionaries as its elements.

# Different types of sets in Python


# set of integers
my_set = {1, 2, 3}
print(my_set)

# set of mixed datatypes


my_set = {1.0, "Hello", (1, 2, 3)}
print(my_set)

Output

{1, 2, 3}
{1.0, (1, 2, 3), 'Hello'}

Try the following examples as well.

# set cannot have duplicates


# Output: {1, 2, 3, 4}
my_set = {1, 2, 3, 4, 3, 2}
print(my_set)

# we can make set from a list


# Output: {1, 2, 3}
my_set = set([1, 2, 3, 2])
print(my_set)

# set cannot have mutable items


# here [3, 4] is a mutable list
# this will cause an error.

my_set = {1, 2, [3, 4]}

Output

{1, 2, 3, 4}
{1, 2, 3}
Traceback (most recent call last):
File "<string>", line 15, in <module>
my_set = {1, 2, [3, 4]}
TypeError: unhashable type: 'list'

Creating an empty set is a bit tricky.


Empty curly braces {} will make an empty dictionary in Python. To make a set without any
elements, we use the set() function without any argument.

# Distinguish set and dictionary while creating empty set

# initialize a with {}
a = {}

# check data type of a


print(type(a))
# initialize a with set()
a = set()

# check data type of a


print(type(a))

Output

<class 'dict'>
<class 'set'>

Modifying a set in Python


Sets are mutable. However, since they are unordered, indexing has no meaning.

We cannot access or change an element of a set using indexing or slicing. Set data type does not
support it.

We can add a single element using the add() method, and multiple elements using the update()
method. The update() method can take tuples, lists, strings or other sets as its argument. In all
cases, duplicates are avoided.

# initialize my_set
my_set = {1, 3}
print(my_set)

# my_set[0]
# if you uncomment the above line
# you will get an error
# TypeError: 'set' object does not support indexing

# add an element
# Output: {1, 2, 3}
my_set.add(2)
print(my_set)

# add multiple elements


# Output: {1, 2, 3, 4}
my_set.update([2, 3, 4])
print(my_set)

# add list and set


# Output: {1, 2, 3, 4, 5, 6, 8}
my_set.update([4, 5], {1, 6, 8})
print(my_set)

Output

{1, 3}
{1, 2, 3}
{1, 2, 3, 4}
{1, 2, 3, 4, 5, 6, 8}

Removing elements from a set


A particular item can be removed from a set using the methods discard() and remove().

The only difference between the two is that the discard() function leaves a set
unchanged if the element is not present in the set. On the other hand, the remove()
function will raise an error in such a condition (if element is not present in the set).

The following example will illustrate this.

# Difference between discard() and remove()

# initialize my_set
my_set = {1, 3, 4, 5, 6}
print(my_set)

# discard an element
# Output: {1, 3, 5, 6}
my_set.discard(4)
print(my_set)

# remove an element
# Output: {1, 3, 5}
my_set.remove(6)
print(my_set)

# discard an element
# not present in my_set
# Output: {1, 3, 5}
my_set.discard(2)
print(my_set)

# remove an element
# not present in my_set
# you will get an error.
# Output: KeyError

my_set.remove(2)

Output

{1, 3, 4, 5, 6}
{1, 3, 5, 6}
{1, 3, 5}
{1, 3, 5}
Traceback (most recent call last):
File "<string>", line 28, in <module>
KeyError: 2
Similarly, we can remove and return an item using the pop() method.

Since set is an unordered data type, there is no way of determining which item will be popped. It
is completely arbitrary.

We can also remove all the items from a set using the clear() method.

# initialize my_set
# Output: set of unique elements
my_set = set("HelloWorld")
print(my_set)

# pop an element
# Output: random element
print(my_set.pop())

# pop another element


my_set.pop()
print(my_set)

# clear my_set
# Output: set()
my_set.clear()
print(my_set)

print(my_set)

Output

{'H', 'l', 'r', 'W', 'o', 'd', 'e'}


H
{'r', 'W', 'o', 'd', 'e'}
set()

Python Set Operations


Sets can be used to carry out mathematical set operations like union, intersection, difference and
symmetric difference. We can do this with operators or methods.

Let us consider the following two sets for the following operations.

>>> A = {1, 2, 3, 4, 5}
>>> B = {4, 5, 6, 7, 8}
Set Union

Set Union in Python

Union of A and B is a set of all elements from both sets.

Union is performed using | operator. Same can be accomplished using the union() method.

# Set union method


# initialize A and B
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# use | operator
# Output: {1, 2, 3, 4, 5, 6, 7, 8}
print(A | B)

Output

{1, 2, 3, 4, 5, 6, 7, 8}

Try the following examples on Python shell.

# use union function


>>> A.union(B)
{1, 2, 3, 4, 5, 6, 7, 8}

# use union function on B


>>> B.union(A)
{1, 2, 3, 4, 5, 6, 7, 8}
Set Intersection

Set Intersection in Python

Intersection of A and B is a set of elements that are common in both the sets.

Intersection is performed using & operator. Same can be accomplished using the
intersection() method.

# Intersection of sets
# initialize A and B
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# use & operator


# Output: {4, 5}
print(A & B)

Output

{4, 5}

Try the following examples on Python shell.

# use intersection function on A


>>> A.intersection(B)
{4, 5}

# use intersection function on B


>>> B.intersection(A)
{4, 5}
Set Difference

Set Difference in Python

Difference of the set B from set A(A - B) is a set of elements that are only in A but not in B.
Similarly, B - A is a set of elements in B but not in A.

Difference is performed using - operator. Same can be accomplished using the difference()
method.

# Difference of two sets


# initialize A and B
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# use - operator on A
# Output: {1, 2, 3}
print(A - B)

Output

{1, 2, 3}

Try the following examples on Python shell.

# use difference function on A


>>> A.difference(B)
{1, 2, 3}

# use - operator on B
>>> B - A
{8, 6, 7}
# use difference function on B
>>> B.difference(A)
{8, 6, 7}

Set Symmetric Difference

Set Symmetric Difference in Python

Symmetric Difference of A and B is a set of elements in A and B but not in both (excluding the
intersection).

Symmetric difference is performed using ^ operator. Same can be accomplished using the
method symmetric_difference().

# Symmetric difference of two sets


# initialize A and B
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}

# use ^ operator
# Output: {1, 2, 3, 6, 7, 8}
print(A ^ B)

Output

{1, 2, 3, 6, 7, 8}

Try the following examples on Python shell.

# use symmetric_difference function on A


>>> A.symmetric_difference(B)
{1, 2, 3, 6, 7, 8}

# use symmetric_difference function on B


>>> B.symmetric_difference(A)
{1, 2, 3, 6, 7, 8}

Other Python Set Methods


There are many set methods, some of which we have already used above. Here is a list of all the
methods that are available with the set objects:

Method Description

add() Adds an element to the set

clear() Removes all elements from the set

copy() Returns a copy of the set

difference() Returns the difference of two or more sets as a new set

difference_update() Removes all elements of another set from this set

Removes an element from the set if it is a member. (Do nothing if the


discard()
element is not in set)

intersection() Returns the intersection of two sets as a new set

intersection_update() Updates the set with the intersection of itself and another

isdisjoint() Returns True if two sets have a null intersection

issubset() Returns True if another set contains this set

issuperset() Returns True if this set contains another set

Removes and returns an arbitrary set element. Raises KeyError if the


pop()
set is empty

Removes an element from the set. If the element is not a member,


remove()
raises a KeyError

symmetric_difference() Returns the symmetric difference of two sets as a new set

symmetric_difference_update() Updates a set with the symmetric difference of itself and another

union() Returns the union of sets in a new set

update() Updates the set with the union of itself and others
Other Set Operations
Set Membership Test

We can test if an item exists in a set or not, using the in keyword.

# in keyword in a set
# initialize my_set
my_set = set("apple")

# check if 'a' is present


# Output: True
print('a' in my_set)

# check if 'p' is present


# Output: False
print('p' not in my_set)

Output

True
False

Iterating Through a Set

We can iterate through each item in a set using a for loop.

>>> for letter in set("apple"):


... print(letter)
...
a
p
e
l

Built-in Functions with Set

Built-in functions like all(), any(), enumerate(), len(), max(), min(), sorted(), sum() etc.
are commonly used with sets to perform different tasks.

Function Description
all() Returns True if all elements of the set are true (or if the set is empty).

any() Returns True if any element of the set is true. If the set is empty, returns False.

Returns an enumerate object. It contains the index and value for all the items of the set as a
enumerate()
pair.

len() Returns the length (the number of items) in the set.

max() Returns the largest item in the set.

min() Returns the smallest item in the set.

sorted() Returns a new sorted list from elements in the set(does not sort the set itself).

sum() Returns the sum of all elements in the set.

Python Frozenset
Frozenset is a new class that has the characteristics of a set, but its elements cannot be changed
once assigned. While tuples are immutable lists, frozensets are immutable sets.

Sets being mutable are unhashable, so they can't be used as dictionary keys. On the other hand,
frozensets are hashable and can be used as keys to a dictionary.

Frozensets can be created using the frozenset() function.

This data type supports methods like copy(), difference(), intersection(), isdisjoint(),
issubset(), issuperset(), symmetric_difference() and union(). Being immutable, it does
not have methods that add or remove elements.

# Frozensets
# initialize A and B
A = frozenset([1, 2, 3, 4])
B = frozenset([3, 4, 5, 6])

Try these examples on Python shell.


>>> A.isdisjoint(B)
False
>>> A.difference(B)
frozenset({1, 2})
>>> A | B
frozenset({1, 2, 3, 4, 5, 6})
>>> A.add(3)
...
AttributeError: 'frozenset' object has no attribute 'add'

Python Dictionary
Python dictionary is an unordered collection of items. Each item of a dictionary has a
key/value pair.
Dictionaries are optimized to retrieve values when the key is known.

Creating Python Dictionary


Creating a dictionary is as simple as placing items inside curly braces {} separated by
commas.

An item has a key and a corresponding value that is expressed as a pair (key: value).

While the values can be of any data type and can repeat, keys must be of immutable type (string,
number or tuple with immutable elements) and must be unique.

# empty dictionary
my_dict = {}

# dictionary with integer keys


my_dict = {1: 'apple', 2: 'ball'}

# dictionary with mixed keys


my_dict = {'name': 'John', 1: [2, 4, 3]}

# using dict()
my_dict = dict({1:'apple', 2:'ball'})

# from sequence having each item as a pair


my_dict = dict([(1,'apple'), (2,'ball')])

As you can see from above, we can also create a dictionary using the built-in dict()
function.
Accessing Elements from Dictionary
While indexing is used with other data types to access values, a dictionary uses keys. Keys can
be used either inside square brackets [] or with the get() method.

If we use the square brackets [], KeyError is raised in case a key is not found in the dictionary.
On the other hand, the get() method returns None if the key is not found.

# get vs [] for retrieving elements


my_dict = {'name': 'Jack', 'age': 26}

# Output: Jack
print(my_dict['name'])

# Output: 26
print(my_dict.get('age'))

# Trying to access keys which doesn't exist throws error


# Output None
print(my_dict.get('address'))

# KeyError
print(my_dict['address'])

Output

Jack
26
None
Traceback (most recent call last):
File "<string>", line 15, in <module>
print(my_dict['address'])
KeyError: 'address'

Changing and Adding Dictionary elements


Dictionaries are mutable. We can add new items or change the value of existing items using an
assignment operator.

If the key is already present, then the existing value gets updated. In case the key is not present, a
new (key: value) pair is added to the dictionary.

# Changing and adding Dictionary Elements


my_dict = {'name': 'Jack', 'age': 26}

# update value
my_dict['age'] = 27

#Output: {'age': 27, 'name': 'Jack'}


print(my_dict)

# add item
my_dict['address'] = 'Downtown'

# Output: {'address': 'Downtown', 'age': 27, 'name': 'Jack'}


print(my_dict)

Output

{'name': 'Jack', 'age': 27}


{'name': 'Jack', 'age': 27, 'address': 'Downtown'}

Removing elements from Dictionary


We can remove a particular item in a dictionary by using the pop() method. This method
removes an item with the provided key and returns the value.

The popitem() method can be used to remove and return an arbitrary (key, value)
item pair from the dictionary. All the items can be removed at once, using the clear() method.

We can also use the del keyword to remove individual items or the entire dictionary itself.

# Removing elements from a dictionary

# create a dictionary
squares = {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# remove a particular item, returns its value


# Output: 16
print(squares.pop(4))

# Output: {1: 1, 2: 4, 3: 9, 5: 25}


print(squares)

# remove an arbitrary item, return (key,value)


# Output: (5, 25)
print(squares.popitem())

# Output: {1: 1, 2: 4, 3: 9}
print(squares)

# remove all items


squares.clear()

# Output: {}
print(squares)

# delete the dictionary itself


del squares

# Throws Error
print(squares)

Output

16
{1: 1, 2: 4, 3: 9, 5: 25}
(5, 25)
{1: 1, 2: 4, 3: 9}
{}
Traceback (most recent call last):
File "<string>", line 30, in <module>
print(squares)
NameError: name 'squares' is not defined

Python Dictionary Methods


Methods that are available with a dictionary are tabulated below. Some of them have already
been used in the above examples.

Method Description

clear() Removes all items from the dictionary.

copy() Returns a shallow copy of the dictionary.

fromkeys(seq[, v]) Returns a new dictionary with keys from seq and value equal to v (defaults to None).

get(key[,d]) Returns the value of the key. If the key does not exist, returns d (defaults to None).

items() Return a new object of the dictionary's items in (key, value) format.

keys() Returns a new object of the dictionary's keys.

Removes the item with the key and returns its value or d if key is not found. If d is not
pop(key[,d])
provided and the key is not found, it raises KeyError.

Removes and returns an arbitrary item (key, value). Raises KeyError if the
popitem()
dictionary is empty.

Returns the corresponding value if the key is in the dictionary. If not, inserts the key
setdefault(key[,d])
with a value of d and returns d (defaults to None).

update([other]) Updates the dictionary with the key/value pairs from other, overwriting existing keys.

values() Returns a new object of the dictionary's values

Here are a few example use cases of these methods.


# Dictionary Methods
marks = {}.fromkeys(['Math', 'English', 'Science'], 0)

# Output: {'English': 0, 'Math': 0, 'Science': 0}


print(marks)

for item in marks.items():


print(item)

# Output: ['English', 'Math', 'Science']


print(list(sorted(marks.keys())))

Output

{'Math': 0, 'English': 0, 'Science': 0}


('Math', 0)
('English', 0)
('Science', 0)
['English', 'Math', 'Science']

Python Dictionary Comprehension


Dictionary comprehension is an elegant and concise way to create a new dictionary from an
iterable in Python.

Dictionary comprehension consists of an expression pair (key: value) followed by a for


statement inside curly braces {}.

Here is an example to make a dictionary with each item being a pair of a number and its square.

# Dictionary Comprehension
squares = {x: x*x for x in range(6)}

print(squares)

Output

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

This code is equivalent to

squares = {}
for x in range(6):
squares[x] = x*x
print(squares)

Output
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

A dictionary comprehension can optionally contain more for or if statements.

An optional if statement can filter out items to form the new dictionary.

Here are some examples to make a dictionary with only odd items.

# Dictionary Comprehension with if conditional


odd_squares = {x: x*x for x in range(11) if x % 2 == 1}

print(odd_squares)

Output

{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}

To learn more dictionary comprehensions, visit Python Dictionary Comprehension.

Other Dictionary Operations


Dictionary Membership Test

We can test if a key is in a dictionary or not using the keyword in. Notice that the membership
test is only for the keys and not for the values.

# Membership Test for Dictionary Keys


squares = {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}

# Output: True
print(1 in squares)

# Output: True
print(2 not in squares)

# membership tests for key only not value


# Output: False
print(49 in squares)

Output

True
True
False
Iterating Through a Dictionary

We can iterate through each key in a dictionary using a for loop.

# Iterating through a Dictionary


squares = {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
for i in squares:
print(squares[i])

Output

1
9
25
49
81

Dictionary Built-in Functions

Built-in functions like all(), any(), len(), cmp(), sorted(),


etc. are commonly used with dictionaries to perform different tasks.

Function Description

all() Return True if all keys of the dictionary are True (or if the dictionary is empty).

any() Return True if any key of the dictionary is true. If the dictionary is empty, return False.

len() Return the length (the number of items) in the dictionary.

cmp() Compares items of two dictionaries. (Not available in Python 3)

sorted() Return a new sorted list of keys in the dictionary.

Here are some examples that use built-in functions to work with a dictionary.

# Dictionary Built-in Functions


squares = {0: 0, 1: 1, 3: 9, 5: 25, 7: 49, 9: 81}

# Output: False
print(all(squares))

# Output: True
print(any(squares))

# Output: 6
print(len(squares))
# Output: [0, 1, 3, 5, 7, 9]
print(sorted(squares))

Output

False
True
6
[0, 1, 3, 5, 7, 9]

Python File I/O

Files
Files are named locations on disk to store related information. They are used to permanently
store data in a non-volatile memory (e.g. hard disk, usb drive. cd).

Since Random Access Memory (RAM) is volatile (which loses its data when the computer is
turned off), we use files for future use of the data by permanently storing them.
When we want to read from or write to a file, we need to open it first. When we are done, it
needs to be closed so that the resources that are tied with the file are freed.

Hence, in Python, a file operation takes place in the following order:

1. Open a file
2. Read or write (perform operation)
3. Close the file

Opening Files in Python


Python has a built-in open() function to open a file. This function returns a file object, also
called a handle, as it is used to read or modify the file accordingly.

>>> f = open("test.txt") # open file in current directory


>>> f = open("C:/Python38/README.txt") # specifying full path
>>> f = open("D:/Python38/README.txt") # specifying full path
>>> f = open("E:/Python38/README.txt") # specifying full path

We can specify the mode while opening a file. In mode, we specify whether we want to read r,
write w or append a to the file. We can also specify if we want to open the file in text mode or
binary mode.

The default is reading in text mode. In this mode, we get strings when reading from the file.

On the other hand, binary mode returns bytes and this is the mode to be used when dealing with
non-text files like images or executable files.

Description
Mode
r Opens a file for reading. (default)
w
Opens a file for writing. Creates a new file if it does not exist or truncates the file if it
exists.
x Opens a file for exclusive creation. If the file already exists, the operation fails.
a
Opens a file for appending at the end of the file without truncating it. Creates a new file if
it does not exist.
t Opens in text mode. (default)
b Opens in binary mode.
+ Opens a file for updating (reading and writing)
f = open("test.txt") # equivalent to 'r' or 'rt'
f = open("test.txt",'w') # write in text mode
f = open("img.bmp",'r+b') # read and write in binary mode

Unlike other languages, the character a does not imply the number 97 until it is encoded using
ASCII (or other equivalent encodings).

Moreover, the default encoding is platform dependent. In windows, it is cp1252 but utf-8 in
Linux.

So, we must not also rely on the default encoding or else our code will behave differently in
different platforms.

Hence, when working with files in text mode, it is highly recommended to specify the encoding
type.

f = open("test.txt", mode='r', encoding='utf-8

Closing Files in Python


When we are done with performing operations on the file, we need to properly close the file.

Closing a file will free up the resources that were tied with the file.
It is done using the close()

3method available in Python.

Python has a garbage collector to clean up unreferenced objects but we must not rely on it to
close the file.

f = open("test.txt", encoding = 'utf-8')


# perform file operations
f.close()

This method is not entirely safe. If an exception occurs when we are performing some operation
with the file, the code exits without closing the file.

A safer way is to use a try...finally block.

try:
f = open("test.txt", encoding = 'utf-8')
# perform file operations
finally:
f.close()

This way, we are guaranteeing that the file is properly closed even if an exception is raised that
causes program flow to stop.
The best way to close a file is by using the with statement. This ensures that the file is closed
when the block inside the with statement is exited.

We don't need to explicitly call the close() method. It is done internally.

with open("test.txt", encoding = 'utf-8') as f:


# perform file operations

Writing to Files in Python


In order to write into a file in Python, we need to open it in write w, append a or exclusive
creation x mode.

We need to be careful with the w mode, as it will overwrite into the file if it already exists. Due to
this, all the previous data are erased.

Writing a string or sequence of bytes (for binary files) is done using the write() method.
This method returns the number of characters written to the file.

with open("test.txt",'w',encoding = 'utf-8') as f:


f.write("my first file\n")
f.write("This file\n\n")
f.write("contains three lines\n")

This program will create a new file named test.txt in the current directory if it does not exist.
If it does exist, it is overwritten.

We must include the newline characters ourselves to distinguish the different lines.

Reading Files in Python


To read a file in Python, we must open the file in reading r mode.

There are various methods available for this purpose. We can use the read(size)
method to read in the size number of data. If the size parameter is not specified, it reads and
returns up to the end of the file.

We can read the text.txt file we wrote in the above section in the following way:

>>> f = open("test.txt",'r',encoding = 'utf-8')


>>> f.read(4) # read the first 4 data
'This'

>>> f.read(4) # read the next 4 data


' is '

>>> f.read() # read in the rest till end of file


'my first file\nThis file\ncontains three lines\n'

>>> f.read() # further reading returns empty sting


''

We can see that the read() method returns a newline as '\n'. Once the end of the file is
reached, we get an empty string on further reading.

We can change our current file cursor (position) using the seek() method. Similarly, the tell()
method returns our current position (in number of bytes).

>>> f.tell() # get the current file position


56

>>> f.seek(0) # bring file cursor to initial position


0

>>> print(f.read()) # read the entire file


This is my first file
This file
contains three lines

We can read a file line-by-line using a for loop. This is both efficient and fast.

>>> for line in f:


... print(line, end = '')
...
This is my first file
This file
contains three lines

In this program, the lines in the file itself include a newline character \n. So, we use the end
parameter of the print() function to avoid two newlines when printing.

Alternatively, we can use the readline() method to read individual lines of a file. This method
reads a file till the newline, including the newline character.

>>> f.readline()
'This is my first file\n'

>>> f.readline()
'This file\n'

>>> f.readline()
'contains three lines\n'

>>> f.readline()
''
Lastly, the readlines() method returns a list of remaining lines of the entire file. All these
reading methods return empty values when the end of file (EOF) is reached.

>>> f.readlines()
['This is my first file\n', 'This file\n', 'contains three lines\n']

Python File Methods


There are various methods available with the file object. Some of them have been used in the
above examples.

Here is the complete list of methods in text mode with a brief description:

Method Description
close() Closes an opened file. It has no effect if the file is already closed.
Separates the underlying binary buffer from the TextIOBase and
detach()
returns it.
fileno() Returns an integer number (file descriptor) of the file.
flush() Flushes the write buffer of the file stream.
isatty() Returns True if the file stream is interactive.
Reads at most n characters from the file. Reads till end of file if it is
read(n)
negative or None.
readable() Returns True if the file stream can be read from.
Reads and returns one line from the file. Reads in at most n bytes if
readline(n=-1)
specified.
Reads and returns a list of lines from the file. Reads in at most n
readlines(n=-1)
bytes/characters if specified.
Changes the file position to offset bytes, in reference to from (start,
seek(offset,from=SEEK_SET)
current, end).
seekable() Returns True if the file stream supports random access.
tell() Returns the current file location.
Resizes the file stream to size bytes. If size is not specified, resizes
truncate(size=None)
to current location.
writable() Returns True if the file stream can be written to.
Writes the string s to the file and returns the number of characters
write(s)
written.
writelines(lines) Writes a list of lines to the file.

Python Directory and Files Management


Python Directory
If there are a large number of files to handle in our Python program, we can arrange our code
within different directories to make things more manageable.

A directory or folder is a collection of files and subdirectories. Python has the os module that
provides us with many useful methods to work with directories (and files as well).

Get Current Directory


We can get the present working directory using the getcwd() method of the os module.

This method returns the current working directory in the form of a string. We can also use the
getcwdb() method to get it as bytes object.

>>> import os

>>> os.getcwd()
'C:\\Program Files\\PyScripter'

>>> os.getcwdb()
b'C:\\Program Files\\PyScripter'

The extra backslash implies an escape sequence. The print() function will render this properly.

>>> print(os.getcwd())
C:\Program Files\PyScripter

Changing Directory
We can change the current working directory by using the chdir() method.

The new path that we want to change into must be supplied as a string to this method. We can
use both the forward-slash / or the backward-slash \ to separate the path elements.

It is safer to use an escape sequence when using the backward slash.

>>> os.chdir('C:\\Python33')

>>> print(os.getcwd())
C:\Python33
List Directories and Files
All files and sub-directories inside a directory can be retrieved using the listdir()
method.

This method takes in a path and returns a list of subdirectories and files in that path. If no path is
specified, it returns the list of subdirectories and files from the current working directory.

>>> print(os.getcwd())
C:\Python33

>>> os.listdir()
['DLLs',
'Doc',
'include',
'Lib',
'libs',
'LICENSE.txt',
'NEWS.txt',
'python.exe',
'pythonw.exe',
'README.txt',
'Scripts',
'tcl',
'Tools']

>>> os.listdir('G:\\')
['$RECYCLE.BIN',
'Movies',
'Music',
'Photos',
'Series',
'System Volume Information']

Making a New Directory


We can make a new directory using the mkdir() method.

This method takes in the path of the new directory. If the full path is not specified, the new
directory is created in the current working directory.

>>> os.mkdir('test')

>>> os.listdir()
['test']
Renaming a Directory or a File
The rename() method can rename a directory or a file.

For renaming any directory or file, the rename() method takes in two basic arguments:
the old name as the first argument and the new name as the second argument.

>>> os.listdir()
['test']

>>> os.rename('test','new_one')

>>> os.listdir()
['new_one']

Removing Directory or File


A file can be removed (deleted) using the remove() method.

Similarly, the rmdir() method removes an empty directory.

>>> os.listdir()
['new_one', 'old.txt']

>>> os.remove('old.txt')
>>> os.listdir()
['new_one']

>>> os.rmdir('new_one')
>>> os.listdir()
[]

Note: The rmdir() method can only remove empty directories.

In order to remove a non-empty directory, we can use the rmtree() method


inside the shutil mo>>> os.listdir()
['test']

>>> os.rmdir('test')
Traceback (most recent call last):
...
OSError: [WinError 145] The directory is not empty: 'test'

>>> import shutil

>>> shutil.rmtree('test')
>>> os.listdir()
Python Errors and Built-in Exceptions:

We can make certain mistakes while writing a program that lead to errors when we try to run it.
A python program terminates as soon as it encounters an unhandled error. These errors can be
broadly classified into two classes:

1. Syntax errors
2. Logical errors (Exceptions)

Python Syntax Errors


Error caused by not following the proper structure (syntax) of the language is called syntax
error or parsing error.

Let's look at one example:

>>> if a < 3
File "<interactive input>", line 1
if a < 3
^
SyntaxError: invalid syntax

As shown in the example, an arrow indicates where the parser ran into the syntax error.

We can notice here that a colon : is missing in the if statement.

Python Logical Errors (Exceptions)


Errors that occur at runtime (after passing the syntax test) are called exceptions or logical
errors.

For instance, they occur when we try to open a file(for reading) that does not exist
(FileNotFoundError), try to divide a number by zero (ZeroDivisionError), or try to import a
module that does not exist (ImportError).

Whenever these types of runtime errors occur, Python creates an exception object. If not handled
properly, it prints a traceback to that error along with some details about why that error occurred.

Let's look at how Python treats these errors:

>>> 1 / 0

Traceback (most recent call last):


File "<string>", line 301, in runcode
File "<interactive input>", line 1, in <module>
ZeroDivisionError: division by zero

>>> open("imaginary.txt")
Traceback (most recent call last):
File "<string>", line 301, in runcode
File "<interactive input>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'imaginary.txt'

Python Built-in Exceptions


Illegal operations can raise exceptions. There are plenty of built-in exceptions in Python that are
raised when corresponding errors occur.

We can view all the built-in exceptions using the built-in local() function as follows:

print(dir(locals()['__builtins__']))

locals()['__builtins__'] will return a module of built-in exceptions, functions, and


attributes. dir allows us to list these attributes as strings.

Some of the common built-in exceptions in Python programming along with the error that cause
them are listed below:

Exception Cause of Error

AssertionError Raised when an assert statement fails.

AttributeError Raised when attribute assignment or reference fails.

EOFError Raised when the input() function hits end-of-file condition.

FloatingPointError Raised when a floating point operation fails.

GeneratorExit Raise when a generator's close() method is called.

ImportError Raised when the imported module is not found.

IndexError Raised when the index of a sequence is out of range.

KeyError Raised when a key is not found in a dictionary.

KeyboardInterrupt Raised when the user hits the interrupt key ( Ctrl+C or Delete).

MemoryError Raised when an operation runs out of memory.


NameError Raised when a variable is not found in local or global scope.

NotImplementedError Raised by abstract methods.

OSError Raised when system operation causes system related error.

Raised when the result of an arithmetic operation is too large to be


OverflowError
represented.

Raised when a weak reference proxy is used to access a garbage collected


ReferenceError
referent.

RuntimeError Raised when an error does not fall under any other category.

Raised by next() function to indicate that there is no further item to be


StopIteration
returned by iterator.

SyntaxError Raised by parser when syntax error is encountered.

IndentationError Raised when there is incorrect indentation.

TabError Raised when indentation consists of inconsistent tabs and spaces.

SystemError Raised when interpreter detects internal error.

SystemExit Raised by sys.exit() function.

Raised when a function or operation is applied to an object of incorrect


TypeError
type.

Raised when a reference is made to a local variable in a function or method,


UnboundLocalError
but no value has been bound to that variable.

UnicodeError Raised when a Unicode-related encoding or decoding error occurs.

UnicodeEncodeError Raised when a Unicode-related error occurs during encoding.

UnicodeDecodeError Raised when a Unicode-related error occurs during decoding.

UnicodeTranslateError Raised when a Unicode-related error occurs during translating.

Raised when a function gets an argument of correct type but improper


ValueError
value.

ZeroDivisionError Raised when the second operand of division or modulo operation is zero.
If required, we can also define our own exceptions in Python.

To learn more about them, visit Python User-defined Exceptions.

We can handle these built-in and user-defined exceptions in Python using try, except and
finally statements. To learn more about them, visit Python try, except and finally statements.
Python Exception Handling Using try, except and finally statement

Exceptions in Python:
Python has many built-in exceptions that are raised when your program encounters an error
(something in the program goes wrong).

When these exceptions occur, the Python interpreter stops the current process and passes it to the
calling process until it is handled. If not handled, the program will crash.

For example,

let us consider a program where we have a function A that calls function B, which in turn calls
function C.

If an exception occurs in function C but is not handled in C, the exception passes to B and then to
A.

If never handled, an error message is displayed and our program comes to a sudden unexpected
halt.

Catching Exceptions in Python


In Python, exceptions can be handled using a try statement.

The code that handles the exceptions is written in the except clause.
We can thus choose what operations to perform once we have caught the exception.

Here is a simple example.

# import module sys to get the type of exception


import sys

randomList = ['a', 0, 2]

for entry in randomList:


try:
print("The entry is", entry)
r = 1/int(entry)
break
except:
print("Oops!", sys.exc_info()[0], "occurred.")
print("Next entry.")
print()
print("The reciprocal of", entry, "is", r)

Output

The entry is a
Oops! <class 'ValueError'> occurred.
Next entry.

The entry is 0
Oops! <class 'ZeroDivisionError'> occured.
Next entry.

The entry is 2
The reciprocal of 2 is 0.5

In this program, we loop through the values of the randomList list. As previously mentioned, the
portion that can cause an exception is placed inside the try block.

If no exception occurs, the except block is skipped and normal flow continues(for last value).
But if any exception occurs, it is caught by the except block (first and second values).

Here, we print the name of the exception using the exc_info() function inside sys module. We
can see that a causes ValueError and 0 causes ZeroDivisionError.

Since every exception in Python inherits from the base Exception class, we can also perform the
above task in the following way:

# import module sys to get the type of exception


import sys
randomList = ['a', 0, 2]

for entry in randomList:


try:
print("The entry is", entry)
r = 1/int(entry)
break
except Exception as e:
print("Oops!", e.__class__, "occurred.")
print("Next entry.")
print()
print("The reciprocal of", entry, "is", r)

This program has the same output as the above program.

Catching Specific Exceptions in Python


In the above example, we did not mention any specific exception in the except clause.

This is not a good programming practice as it will catch all exceptions and handle every case in
the same way. We can specify which exceptions an except clause should catch.

A try clause can have any number of except clauses to handle different exceptions, however,
only one will be executed in case an exception occurs.

We can use a tuple of values to specify multiple exceptions in an except clause. Here is an
example pseudo code.

try:
# do something
pass

except ValueError:
# handle ValueError exception
pass

except (TypeError, ZeroDivisionError):


# handle multiple exceptions
# TypeError and ZeroDivisionError
pass

except:
# handle all other exceptions
pass
Raising Exceptions in Python
In Python programming, exceptions are raised when errors occur at runtime.

We can also manually raise exceptions using the raise keyword.

We can optionally pass values to the exception to clarify why that exception was raised.

>>> raise KeyboardInterrupt


Traceback (most recent call last):
...
KeyboardInterrupt

>>> raise MemoryError("This is an argument")


Traceback (most recent call last):
...
MemoryError: This is an argument

>>> try:
... a = int(input("Enter a positive integer: "))
... if a <= 0:
... raise ValueError("That is not a positive number!")
... except ValueError as ve:
... print(ve)
...
Enter a positive integer: -2
That is not a positive number!
Python try with else clause
In some situations, you might want to run a certain block of code if the code block inside try ran
without any errors.

For these cases, you can use the optional else keyword with the try statement.

Note: Exceptions in the else clause are not handled by the preceding except clauses.

Let's look at an example:

# program to print the reciprocal of even numbers

try:
num = int(input("Enter a number: "))
assert num % 2 == 0
except:
print("Not an even number!")
else:
reciprocal = 1/num
print(reciprocal)

Output

If we pass an odd number:

Enter a number: 1
Not an even number!

If we pass an even number, the reciprocal is computed and displayed.

Enter a number: 4
0.25

However, if we pass 0, we get ZeroDivisionError as the code block inside else is not handled
by preceding except.
Enter a number: 0
Traceback (most recent call last):
File "<string>", line 7, in <module>
reciprocal = 1/num
ZeroDivisionError: division by zero

Python try...finally
The try statement in Python can have an optional finally clause.

This clause is executed no matter what, and is generally used to release external resources.

try:
f = open("test.txt",encoding = 'utf-8')
# perform file operations
finally:
f.close()

For example, we may be connected to a remote data center through the network or working with
a file or a Graphical User Interface (GUI).

In all these circumstances, we must clean up the resource before the program comes to a halt
whether it successfully ran or not. These actions (closing a file, GUI or disconnecting from
network) are performed in the finally clause to guarantee the execution.

Here is an example of file operations to illustrate this.

try:
f = open("test.txt",encoding = 'utf-8')
# perform file operations
finally:
f.close()

This type of construct makes sure that the file is closed even if an exception occurs during the
program execution.

Python Custom Exceptions

Python has numerous built-in exceptions that force your program to output an error when
something in the program goes wrong.

However, sometimes you may need to create your own custom exceptions that serve your
purpose.

Creating Custom Exceptions


In Python, users can define custom exceptions by creating a new class. This exception class has
to be derived, either directly or indirectly, from the built-in Exception class. Most of the built-in
exceptions are also derived from this class.

>>> class CustomError(Exception):


... pass
...

>>> raise CustomError


Traceback (most recent call last):
...
__main__.CustomError

>>> raise CustomError("An error occurred")


Traceback (most recent call last):
...
__main__.CustomError: An error occurred

Here, we have created a user-defined exception called CustomError which inherits from the
Exception class. This new exception, like other exceptions, can be raised using the raise
statement with an optional error message.

When we are developing a large Python program, it is a good practice to place all the user-
defined exceptions that our program raises in a separate file. Many standard modules do this.
They define their exceptions separately as exceptions.py or errors.py (generally but not
always).

User-defined exception class can implement everything a normal class can do, but we generally
make them simple and concise. Most implementations declare a custom base class and derive
others exception classes from this base class. This concept is made clearer in the following
example.

Example: User-Defined Exception in Python


We will illustrate how user-defined exceptions can be used in a program to raise and catch
errors.

This program will ask the user to enter a number until they guess a stored number correctly. To
help them figure it out, a hint is provided whether their guess is greater than or less than the
stored number.
# define Python user-defined exceptions
class Error(Exception):
"""Base class for other exceptions"""
pass

class ValueTooSmallError(Error):
"""Raised when the input value is too small"""
pass

class ValueTooLargeError(Error):
"""Raised when the input value is too large"""
pass

# you need to guess this number


number = 10

# user guesses a number until he/she gets it right


while True:
try:
i_num = int(input("Enter a number: "))
if i_num < number:
raise ValueTooSmallError
elif i_num > number:
raise ValueTooLargeError
break
except ValueTooSmallError:
print("This value is too small, try again!")
print()
except ValueTooLargeError:
print("This value is too large, try again!")
print()

print("Congratulations! You guessed it correctly.")

Here is a sample run of this program.

Enter a number: 12
This value is too large, try again!

Enter a number: 0
This value is too small, try again!

Enter a number: 8
This value is too small, try again!

Enter a number: 10
Congratulations! You guessed it correctly.

We have defined a base class called Error.


The other two exceptions (ValueTooSmallError and ValueTooLargeError) that are actually
raised by our program are derived from this class. This is the standard way to define user-defined
exceptions in Python programming, but you are not limited to this way only.

Customizing Exception Classes


We can further customize this class to accept other arguments as per our needs.

To learn about customizing the Exception classes, you need to have the basic knowledge of
Object-Oriented programming.

Visit Python Object Oriented Programming to start learning about Object-Oriented programming
in PytLet's look at one example:

class SalaryNotInRangeError(Exception):
"""Exception raised for errors in the input salary.

Attributes:
salary -- input salary which caused the error
message -- explanation of the error
"""

def __init__(self, salary, message="Salary is not in (5000, 15000)


range"):
self.salary = salary
self.message = message
super().__init__(self.message)

salary = int(input("Enter salary amount: "))


if not 5000 < salary < 15000:
raise SalaryNotInRangeError(salary)

Output

Enter salary amount: 2000


Traceback (most recent call last):
File "<string>", line 17, in <module>
raise SalaryNotInRangeError(salary)
__main__.SalaryNotInRangeError: Salary is not in (5000, 15000) range
Here, we have overridden the constructor of the Exception class to accept our own custom
arguments salary and message. Then, the constructor of the parent Exception class is called
manually with the self.message argument using super().

The custom self.salary attribute is defined to be used later.

The inherited __str__ method of the Exception class is then used to display the corresponding
message when SalaryNotInRangeError is raised.

We can also customize the __str__ method itself by overriding it.

class SalaryNotInRangeError(Exception):
"""Exception raised for errors in the input salary.

Attributes:
salary -- input salary which caused the error
message -- explanation of the error
"""

def __init__(self, salary, message="Salary is not in (5000, 15000)


range"):
self.salary = salary
self.message = message
super().__init__(self.message)

def __str__(self):
return f'{self.salary} -> {self.message}'

salary = int(input("Enter salary amount: "))


if not 5000 < salary < 15000:
raise SalaryNotInRangeError(salary)

Output

Enter salary amount: 2000


Traceback (most recent call last):
File "/home/bsoyuj/Desktop/Untitled-1.py", line 20, in <module>
raise SalaryNotInRangeError(salary)
__main__.SalaryNotInRangeError: 2000 -> Salary is not in (5000, 15000) range
Python Object Oriented Programming

Object Oriented Programming


Python is a multi-paradigm programming language. It supports different programming
approaches.

One of the popular approaches to solve a programming problem is by creating objects. This is
known as Object-Oriented Programming (OOP).

An object has two characteristics:

 attributes
 behavior

Let's take an example:

A parrot is can be an object,as it has the following properties:

 name, age, color as attributes


 singing, dancing as behavior

The concept of OOP in Python focuses on creating reusable code. This concept is also known as
DRY (Don't Repeat Yourself).

In Python, the concept of OOP follows some basic principles:


Class
A class is a blueprint for the object.

We can think of class as a sketch of a parrot with labels. It contains all the details about the
name, colors, size etc. Based on these descriptions, we can study about the parrot. Here, a parrot
is an object.

The example for class of parrot can be :

class Parrot:
pass

Here, we use the class keyword to define an empty class Parrot. From class, we construct
instances. An instance is a specific object created from a particular class.

Object
An object (instance) is an instantiation of a class. When class is defined, only the description for
the object is defined. Therefore, no memory or storage is allocated.

The example for object of parrot class can be:

obj = Parrot()

Here, obj is an object of class Parrot.

Suppose we have details of parrots. Now, we are going to show how to build the class and
objects of parrots.

Example 1: Creating Class and Object in Python


class Parrot:

# class attribute
species = "bird"

# instance attribute
def __init__(self, name, age):
self.name = name
self.age = age

# instantiate the Parrot class


blu = Parrot("Blu", 10)
woo = Parrot("Woo", 15)

# access the class attributes


print("Blu is a {}".format(blu.__class__.species))
print("Woo is also a {}".format(woo.__class__.species))
# access the instance attributes
print("{} is {} years old".format( blu.name, blu.age))
print("{} is {} years old".format( woo.name, woo.age))

Output

Blu is a bird
Woo is also a bird
Blu is 10 years old
Woo is 15 years old

In the above program, we created a class with the name Parrot. Then, we define attributes. The
attributes are a characteristic of an object.

These attributes are defined inside the __init__ method of the class. It is the initializer method
that is first run as soon as the object is created.

Then, we create instances of the Parrot class. Here, blu and woo are references (value) to our
new objects.

We can access the class attribute using __class__.species. Class attributes are the same for all
instances of a class. Similarly, we access the instance attributes using blu.name and blu.age.
However, instance attributes are different for every instance of a class.

Methods
Methods are functions defined inside the body of a class. They are used to define the behaviors
of an object.

Example 2 : Creating Methods in Python

Methods
Methods are functions defined inside the body of a class. They are used to define the behaviors
of an object.

Example 2 : Creating Methods in Python


class Parrot:

# instance attributes
def __init__(self, name, age):
self.name = name
self.age = age

# instance method
def sing(self, song):
return "{} sings {}".format(self.name, song)
def dance(self):
return "{} is now dancing".format(self.name)

# instantiate the object


blu = Parrot("Blu", 10)

# call our instance methods


print(blu.sing("'Happy'"))
print(blu.dance())

Output

Blu sings 'Happy'


Blu is now dancing

In the above program, we define two methods i.e sing() and dance(). These are called instance
methods because they are called on an instance object i.e blu.

Inheritance
Inheritance is a way of creating a new class for using details of an existing class without
modifying it. The newly formed class is a derived class (or child class). Similarly, the existing
class is a base class (or parent class).

Example 3: Use of Inheritance in Python


# parent class
class Bird:

def __init__(self):
print("Bird is ready")

def whoisThis(self):
print("Bird")

def swim(self):
print("Swim faster")

# child class
class Penguin(Bird):

def __init__(self):
# call super() function
super().__init__()
print("Penguin is ready")

def whoisThis(self):
print("Penguin")

def run(self):
print("Run faster")

peggy = Penguin()
peggy.whoisThis()
peggy.swim()
peggy.run()

Output

Bird is ready
Penguin is ready
Penguin
Swim faster
Run faster

In the above program, we created two classes i.e. Bird (parent class) and Penguin (child class).
The child class inherits the functions of parent class. We can see this from the swim() method.

Again, the child class modified the behavior of the parent class. We can see this from the
whoisThis() method. Furthermore, we extend the functions of the parent class, by creating a
new run() method.

Additionally, we use the super() function inside the __init__() method. This allows us to run
the __init__() method of the parent class inside the child class.

Encapsulation
Using OOP in Python, we can restrict access to methods and variables. This prevents data from
direct modification which is called encapsulation. In Python, we denote private attributes using
underscore as the prefix i.e single _ or double __.

Example 4: Data Encapsulation in Python


class Computer:

def __init__(self):
self.__maxprice = 900

def sell(self):
print("Selling Price: {}".format(self.__maxprice))

def setMaxPrice(self, price):


self.__maxprice = price

c = Computer()
c.sell()

# change the price


c.__maxprice = 1000
c.sell()

# using setter function


c.setMaxPrice(1000)
c.sell()

Output
Selling Price: 900
Selling Price: 900
Selling Price: 1000

In the above program, we defined a Computer class.

We used __init__() method to store the maximum selling price of Computer. We tried to
modify the price. However, we can't change it because Python treats the __maxprice as private
attributes.

As shown, to change the value, we have to use a setter function i.e setMaxPrice() which takes
price as a parameter.

Polymorphism
Polymorphism is an ability (in OOP) to use a common interface for multiple forms (data types).

Suppose, we need to color a shape, there are multiple shape options (rectangle, square, circle).
However we could use the same method to color any shape. This concept is called
Polymorphism.

Example 5: Using Polymorphism in Python


class Parrot:

def fly(self):
print("Parrot can fly")

def swim(self):
print("Parrot can't swim")

class Penguin:

def fly(self):
print("Penguin can't fly")

def swim(self):
print("Penguin can swim")

# common interface
def flying_test(bird):
bird.fly()

#instantiate objects
blu = Parrot()
peggy = Penguin()

# passing the object


flying_test(blu)
flying_test(peggy)
Output

Parrot can fly


Penguin can't fly

In the above program, we defined two classes Parrot and Penguin. Each of them have a common
fly() method. However, their functions are different.

To use polymorphism, we created a common interface i.e flying_test() function that takes
any object and calls the object's fly() method. Thus, when we passed the blu and peggy objects
in the flying_test() function, it ran effectively.

Key Points to Remember:


 Object-Oriented Programming makes the program easy to understand as well as efficient.
 Since the class is sharable, the code can be reused.
 Data is safe and secure with data abstraction.
 Polymorphism allows the same interface for different objects, so programmers can write
efficient code.
Python Objects and Classes

Python Objects and Classes


Python is an object oriented programming language. Unlike procedure oriented programming,
where the main emphasis is on functions, object oriented programming stresses on objects.

An object is simply a collection of data (variables) and methods (functions) that act on those
data. Similarly, a class is a blueprint for that object.

We can think of class as a sketch (prototype) of a house. It contains all the details about the
floors, doors, windows etc. Based on these descriptions we build the house. House is the object.

As many houses can be made from a house's blueprint, we can create many objects from a class.
An object is also called an instance of a class and the process of creating this object is called
instantiation.

Defining a Class in Python


Like function definitions begin with the def keyword in Python, class definitions begin with a
class keyword.

The first string inside the class is called docstring and has a brief description about the class.
Although not mandatory, this is highly recommended.

Here is a simple class definition.

class MyNewClass:
'''This is a docstring. I have created a new class'''
pass

A class creates a new local namespace where all its attributes are defined. Attributes may be data
or functions.
There are also special attributes in it that begins with double underscores __. For example,
__doc__ gives us the docstring of that class.

As soon as we define a class, a new class object is created with the same name. This class object
allows us to access the different attributes as well as to instantiate new objects of that class.

class Person:
"This is a person class"
age = 10

def greet(self):
print('Hello')

# Output: 10
print(Person.age)

# Output: <function Person.greet>


print(Person.greet)

# Output: 'This is my second class'


print(Person.__doc__)

Output

10
<function Person.greet at 0x7fc78c6e8160>
This is a person class

Creating an Object in Python


We saw that the class object could be used to access different attributes.

It can also be used to create new object instances (instantiation) of that class. The procedure to
create an object is similar to a function call.

>>> harry = Person()

This will create a new object instance named harry. We can access the attributes of objects using
the object name prefix.

Attributes may be data or method. Methods of an object are corresponding functions of that
class.

This means to say, since Person.greet is a function object (attribute of class), Person.greet
will be a method object.

class Person:
"This is a person class"
age = 10

def greet(self):
print('Hello')

# create a new object of Person class


harry = Person()

# Output: <function Person.greet>


print(Person.greet)

# Output: <bound method Person.greet of <__main__.Person object>>


print(harry.greet)

# Calling object's greet() method


# Output: Hello
harry.greet()

Output

<function Person.greet at 0x7fd288e4e160>


<bound method Person.greet of <__main__.Person object at 0x7fd288e9fa30>>
Hello

You may have noticed the self parameter in function definition inside the class but we called
the method simply as harry.greet() without any arguments. It still worked.

This is because, whenever an object calls its method, the object itself is passed as the first
argument. So, harry.greet() translates into Person.greet(harry).

In general, calling a method with a list of n arguments is equivalent to calling the corresponding
function with an argument list that is created by inserting the method's object before the first
argument.

For these reasons, the first argument of the function in class must be the object itself. This is
conventionally called self. It can be named otherwise but we highly recommend to follow the
convention.

Now you must be familiar with class object, instance object, function object, method object and
their differences.

Constructors in Python
Class functions that begin with double underscore __ are called special functions as they have
special meaning.

Of one particular interest is the __init__() function. This special function gets called whenever
a new object of that class is instantiated.

This type of function is also called constructors in Object Oriented Programming (OOP). We
normally use it to initialize all the variables.

class ComplexNumber:
def __init__(self, r=0, i=0):
self.real = r
self.imag = i

def get_data(self):
print(f'{self.real}+{self.imag}j')

# Create a new ComplexNumber object


num1 = ComplexNumber(2, 3)

# Call get_data() method


# Output: 2+3j
num1.get_data()

# Create another ComplexNumber object


# and create a new attribute 'attr'
num2 = ComplexNumber(5)
num2.attr = 10

# Output: (5, 0, 10)


print((num2.real, num2.imag, num2.attr))

# but c1 object doesn't have attribute 'attr'


# AttributeError: 'ComplexNumber' object has no attribute 'attr'
print(num1.attr)

Output

2+3j
(5, 0, 10)
Traceback (most recent call last):
File "<string>", line 27, in <module>
print(num1.attr)
AttributeError: 'ComplexNumber' object has no attribute 'attr'

In the above example, we defined a new class to represent complex numbers. It has two
functions, __init__() to initialize the variables (defaults to zero) and get_data() to display the
number properly.
An interesting thing to note in the above step is that attributes of an object can be created on the
fly. We created a new attribute attr for object num2 and read it as well. But this does not create
that attribute for object num1.

Deleting Attributes and Objects


Any attribute of an object can be deleted anytime, using the del statement. Try the following on
the Python shell to see the output.

>>> num1 = ComplexNumber(2,3)


>>> del num1.imag
>>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'imag'

>>> del ComplexNumber.get_data


>>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'get_data'

We can even delete the object itself, using the del statement.

>>> c1 = ComplexNumber(1,3)
>>> del c1
>>> c1
Traceback (most recent call last):
...
NameError: name 'c1' is not defined

Actually, it is more complicated than that. When we do c1 = ComplexNumber(1,3), a new


instance object is created in memory and the name c1 binds with it.

On the command del c1, this binding is removed and the name c1 is deleted from the
corresponding namespace. The object however continues to exist in memory and if no other
name is bound to it, it is later automatically destroyed.

This automatic destruction of unreferenced objects in Python is also called garbage collection.
Deleting objects in Python removes the name binding

Python Inheritance

Inheritance enables us to define a class that takes all the functionality from a parent class and
allows us to add more.

Inheritance in Python
Inheritance is a powerful feature in object oriented programming.

It refers to defining a new class with little or no modification to an existing class. The new class
is called derived (or child) class and the one from which it inherits is called the base (or
parent) class.

Python Inheritance Syntax


class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class

Derived class inherits features from the base class where new features can be added to it. This
results in re-usability of code.

Example of Inheritance in Python

To demonstrate the use of inheritance, let us take an example.

A polygon is a closed figure with 3 or more sides. Say, we have a class called Polygon defined
as follows.
class Polygon:
def __init__(self, no_of_sides):
self.n = no_of_sides
self.sides = [0 for i in range(no_of_sides)]

def inputSides(self):
self.sides = [float(input("Enter side "+str(i+1)+" : ")) for i in
range(self.n)]

def dispSides(self):
for i in range(self.n):
print("Side",i+1,"is",self.sides[i])

This class has data attributes to store the number of sides n and magnitude of each side as a list
called sides.

The inputSides() method takes in the magnitude of each side and dispSides() displays these
side lengths.

A triangle is a polygon with 3 sides. So, we can create a class called Triangle which inherits
from Polygon. This makes all the attributes of Polygon class available to the Triangle class.

We don't need to define them again (code reusability). Triangle can be defined as follows.

class Triangle(Polygon):
def __init__(self):
Polygon.__init__(self,3)

def findArea(self):
a, b, c = self.sides
# calculate the semi-perimeter
s = (a + b + c) / 2
area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('The area of the triangle is %0.2f' %area)

However, class Triangle has a new method findArea() to find and print the area of the
triangle. Here is a sample run.

>>> t = Triangle()

>>> t.inputSides()
Enter side 1 : 3
Enter side 2 : 5
Enter side 3 : 4

>>> t.dispSides()
Side 1 is 3.0
Side 2 is 5.0
Side 3 is 4.0

>>> t.findArea()
The area of the triangle is 6.00
We can see that even though we did not define methods like inputSides() or dispSides() for
class Triangle separately, we were able to use them.

If an attribute is not found in the class itself, the search continues to the base class. This repeats
recursively, if the base class is itself derived from other classes.

Method Overriding in Python


In the above example, notice that __init__() method was defined in both classes, Triangle as
well Polygon. When this happens, the method in the derived class overrides that in the base
class. This is to say, __init__() in Triangle gets preference over the __init__ in Polygon.

Generally when overriding a base method, we tend to extend the definition rather than simply
replace it. The same is being done by calling the method in base class from the one in derived
class (calling Polygon.__init__() from __init__() in Triangle).

A better option would be to use the built-in function super(). So, super().__init__(3) is
equivalent to Polygon.__init__(self,3) and is preferred. To learn more about the super()
function in Python, visit Python super() function.

Two built-in functions isinstance() and issubclass() are used to check inheritances.

The function isinstance() returns True if the object is an instance of the class or other classes
derived from it. Each and every class in Python inherits from the base class object.

>>> isinstance(t,Triangle)
True

>>> isinstance(t,Polygon)
True

>>> isinstance(t,int)
False

>>> isinstance(t,object)
True

Similarly, issubclass() is used to check for class inheritance.

>>> issubclass(Polygon,Triangle)
False

>>> issubclass(Triangle,Polygon)
True

>>> issubclass(bool,int)
True
Python Multiple Inheritance
Python Multiple Inheritance

A class can be derived from more than one base class in Python, similar to C++. This is called
multiple inheritance.

In multiple inheritance, the features of all the base classes are inherited into the derived class.
The syntax for multiple inheritance is similar to single inheritance.

Example
class Base1:
pass

class Base2:
pass

class MultiDerived(Base1, Base2):


pass

Here, the MultiDerived class is derived from Base1 and Base2 classes.

Multiple Inheritance in Python

The MultiDerived class inherits from both Base1 and Base2 classes.

Python Multilevel Inheritance


We can also inherit from a derived class. This is called multilevel inheritance. It can be of any
depth in Python.

In multilevel inheritance, features of the base class and the derived class are inherited into the
new derived class.

An example with corresponding visualization is given below.

class Base:
pass

class Derived1(Base):
pass

class Derived2(Derived1):
pass

Here, the Derived1 class is derived from the Base class, and the Derived2 class is derived from
the Derived1 class.

Multilevel Inheritance in Python

Method Resolution Order in Python


Every class in Python is derived from the object class. It is the most base type in Python.

So technically, all other classes, either built-in or user-defined, are derived classes and all objects
are instances of the object class.

# Output: True
print(issubclass(list,object))

# Output: True
print(isinstance(5.5,object))

# Output: True
print(isinstance("Hello",object))

In the multiple inheritance scenario, any specified attribute is searched first in the current class.
If not found, the search continues into parent classes in depth-first, left-right fashion without
searching the same class twice.

So, in the above example of MultiDerived class the search order is [MultiDerived, Base1,
Base2, object]. This order is also called linearization of MultiDerived class and the set of rules
used to find this order is called Method Resolution Order (MRO).

MRO must prevent local precedence ordering and also provide monotonicity. It ensures that a
class always appears before its parents. In case of multiple parents, the order is the same as
tuples of base classes.

MRO of a class can be viewed as the __mro__ attribute or the mro() method. The former returns
a tuple while the latter returns a list.

>>> MultiDerived.__mro__
(<class '__main__.MultiDerived'>,
<class '__main__.Base1'>,
<class '__main__.Base2'>,
<class 'object'>)

>>> MultiDerived.mro()
[<class '__main__.MultiDerived'>,
<class '__main__.Base1'>,
<class '__main__.Base2'>,
<class 'object'>]

Here is a little more complex multiple inheritance example and its visualization along with the
MRO.
Visualizing Multiple Inheritance in Python

class X:
pass

class Y:
pass

class Z:
pass

class A(X, Y):


pass

class B(Y, Z):


pass

class M(B, A, Z):


pass

# Output:
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class '__main__.Z'>,
# <class 'object'>]
print(M.mro())

Output

[<class '__main__.M'>, <class '__main__.B'>, <class '__main__.A'>, <class


'__main__.X'>, <class '__main__.Y'>, <class '__main__.Z'>, <class 'object'>]

To know the actual algorithm on how MRO is calculated, visit Discussion on MRO.

Python Operator Overloading


You can change the meaning of an operator in Python depending upon the operands used. In this
tutorial, you will learn how to use operator overloading in Python Object Oriented Programming.

Python Operator Overloading


Python operators work for built-in classes. But the same operator behaves differently with
different types. For example, the + operator will perform arithmetic addition on two numbers,
merge two lists, or concatenate two strings.

This feature in Python that allows the same operator to have different meaning according to the
context is called operator overloading.

So what happens when we use them with objects of a user-defined class? Let us consider the
following class, which tries to simulate a point in 2-D coordinate system.

class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)

Output

Traceback (most recent call last):


File "<string>", line 9, in <module>
print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

Here, we can see that a TypeError was raised, since Python didn't know how to add two Point
objects together.
However, we can achieve this task in Python through operator overloading. But first, let's get a
notion about special functions.

Python Special Functions


Class functions that begin with double underscore __ are called special functions in Python.

These functions are not the typical functions that we define for a class. The __init__() function
we defined above is one of them. It gets called every time we create a new object of that class.

There are numerous other special functions in Python. Visit Python Special Functions to learn
more about them.

Using special functions, we can make our class compatible with built-in functions.

>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>

Suppose we want the print() function to print the coordinates of the Point object instead of
what we got. We can define a __str__() method in our class that controls how the object gets
printed. Let's look at how we can achieve this:

class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x,self.y)

Now let's try the print() function again.

class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __str__(self):
return "({0}, {1})".format(self.x, self.y)

p1 = Point(2, 3)
print(p1)

Output

(2, 3)
That's better. Turns out, that this same method is invoked when we use the built-in function
str() or format().

>>> str(p1)
'(2,3)'

>>> format(p1)
'(2,3)'

So, when you use str(p1) or format(p1), Python internally calls the p1.__str__() method.
Hence the name, special functions.

Now let's go back to operator overloading.

Overloading the + Operator


To overload the + operator, we will need to implement __add__() function in the class. With
great power comes great responsibility. We can do whatever we like, inside this function. But it
is more sensible to return a Point object of the coordinate sum.

class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x, self.y)

def __add__(self, other):


x = self.x + other.x
y = self.y + other.y
return Point(x, y)

Now let's try the addition operation again:

class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x, self.y)

def __add__(self, other):


x = self.x + other.x
y = self.y + other.y
return Point(x, y)

p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)

Output

(3,5)

What actually happens is that, when you use p1 + p2, Python calls p1.__add__(p2) which in
turn is Point.__add__(p1,p2). After this, the addition operation is carried out the way we
specified.

Similarly, we can overload other operators as well. The special function that we need to
implement is tabulated below.

Operator Expression Internally


Addition p1 + p2 p1.__add__(p2)
Subtraction p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2)
Power p1 ** p2 p1.__pow__(p2)
Division p1 / p2 p1.__truediv__(p2)
Floor Division p1 // p2 p1.__floordiv__(p2)
Remainder (modulo) p1 % p2 p1.__mod__(p2)
Bitwise Left Shift p1 << p2 p1.__lshift__(p2)
Bitwise Right Shift p1 >> p2 p1.__rshift__(p2)
Bitwise AND p1 & p2 p1.__and__(p2)
Bitwise OR p1 | p2 p1.__or__(p2)
Bitwise XOR p1 ^ p2 p1.__xor__(p2)
Bitwise NOT ~p1 p1.__invert__()

Overloading Comparison Operators


Python does not limit operator overloading to arithmetic operators only. We can overload
comparison operators as well.

Suppose we wanted to implement the less than symbol < symbol in our Point class.

Let us compare the magnitude of these points from the origin and return the result for this
purpose. It can be implemented as follows.

# overloading the less than operator


class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x, self.y)

def __lt__(self, other):


self_mag = (self.x ** 2) + (self.y ** 2)
other_mag = (other.x ** 2) + (other.y ** 2)
return self_mag < other_mag

p1 = Point(1,1)
p2 = Point(-2,-3)
p3 = Point(1,-1)

# use less than


print(p1<p2)
print(p2<p3)
print(p1<p3)

Output

True
False
False

Similarly, the special functions that we need to implement, to overload other comparison
operators are tabulated below.

Operator Expression Internally


Less than p1 < p2 p1.__lt__(p2)
Less than or equal to p1 <= p2 p1.__le__(p2)
Equal to p1 == p2 p1.__eq__(p2)
Not equal to p1 != p2 p1.__ne__(p2)
Greater than p1 > p2 p1.__gt__(p2)
Greater than or equal to p1 >= p2 p1.__ge__(p2)

Object-Oriented Programming (OOP):


Key Points to Remember :
 Object-Oriented Programming makes the program easy to understand as well as efficient.
 Since the class is sharable, the code can be reused.
 Data is safe and secure with data abstraction.
 Polymorphism allows the same interface for different objects, so programmers can write
efficient code.
What is def __ init __( self?

__init__ is the constructor for a class. The self parameter refers to the instance of the object (like this in
C++). class Point: def __init__(self, x, y): self._x = x self._y = y. The __init__ method gets called after
memory for the object is allocated: x = Point(1,2)09-Mar-2009

What is def __ init __( self?

What does __ init __ mean in Python?

constructor

"__init__" is a reseved method in python classes. It is called as a constructor in object oriented


terminology. This method is called when an object is created from a class and it allows the class to
initialize the attributes of the class

self represents the instance of the class. By using the “self” keyword we can access the attributes and
methods of the class in python. It binds the attributes with the given arguments. The reason you need to
use self. is because Python does not use the @ syntax to refer to instance attributes.

"One of the popular approaches to solve a programming problem is by creating objects. This is
known as Object-Oriented Programming (OOP)".

An object has two characteristics:

 attributes
 behavior

Let's take an example:

A parrot is an object, as it has the following properties:

 name, age, color as attributes


 singing, dancing as behavior

The concept of OOP in Python focuses on creating reusable code. This concept is also known as
DRY (Don't Repeat Yourself).
Class
A class is a blueprint for the object.

We can think of class as a sketch of a parrot with labels. It contains all the details about the
name, colors, size etc. Based on these descriptions, we can study about the parrot. Here, a parrot
is an object.

The example for class of parrot can be :

class Parrot:
pass

Here, we use the class keyword to define an empty class Parrot. From class, we construct
instances. An instance is a specific object created from a particular class.

Object
An object (instance) is an instantiation of a class. When class is defined, only the description for
the object is defined. Therefore, no memory or storage is allocated.

The example for object of parrot class can be:

obj = Parrot()

Here, obj is an object of class Parrot.

Suppose we have details of parrots. Now, we are going to show how to build the class and
objects of parrots.

Methods
Methods are functions defined inside the body of a class. They are used to define the behaviors
of an object.

Example 2 : Creating Methods in Python


class Parrot:

# instance attributes
def __init__(self, name, age):
self.name = name
self.age = age

# instance method
def sing(self, song):
return "{} sings {}".format(self.name, song)

def dance(self):
return "{} is now dancing".format(self.name)

# instantiate the object


blu = Parrot("Blu", 10)

# call our instance methods


print(blu.sing("'Happy'"))
print(blu.dance())

Output

Blu sings 'Happy'


Blu is now dancing

In the above program, we define two methods i.e sing() and dance(). These are called instance
methods because they are called on an instance object i.e blu.

Inheritance
Inheritance is a way of creating a new class for using details of an existing class without
modifying it. The newly formed class is a derived class (or child class). Similarly, the existing
class is a base class (or parent class).

Example 3: Use of Inheritance in Python


# parent class
class Bird:

def __init__(self):
print("Bird is ready")

def whoisThis(self):
print("Bird")

def swim(self):
print("Swim faster")

# child class
class Penguin(Bird):

def __init__(self):
# call super() function
super().__init__()
print("Penguin is ready")
def whoisThis(self):
print("Penguin")

def run(self):
print("Run faster")

peggy = Penguin()
peggy.whoisThis()
peggy.swim()
peggy.run()

Output

Bird is ready
Penguin is ready
Penguin
Swim faster
Run faster

Encapsulation
Using OOP in Python, we can restrict access to methods and variables. This prevents data from
direct modification which is called encapsulation. In Python, we denote private attributes using
underscore as the prefix i.e single _ or double __.

Example 4: Data Encapsulation in Python

Polymorphism
Polymorphism is an ability (in OOP) to use a common interface for multiple forms (data types).

Suppose, we need to color a shape, there are multiple shape options (rectangle, square, circle).
However we could use the same method to color any shape. This concept is called
Polymorphism.

Python Objects and Classes


An object is simply a collection of data (variables) and methods (functions) that act on those
data. Similarly, a class is a blueprint for that object.
Defining a Class in Python
Like function definitions begin with the def keyword in Python, class definitions begin with a
class keyword.

The first string inside the class is called docstring and has a brief description of the class.
Although not mandatory, this is highly recommended.

Here is a simple class definition.

class MyNewClass:
'''This is a docstring. I have created a new class'''
pass

e.g-----

class Person:
"This is a person class"
age = 10

def greet(self):
print('Hello')

# Output: 10
print(Person.age)

# Output: <function Person.greet>


print(Person.greet)

# Output: "This is a person class"


print(Person.__doc__)

Output

10
<function Person.greet at 0x7fc78c6e8160>
This is a person class

Creating an Object in Python


We saw that the class object could be used to access different attributes.

It can also be used to create new object instances (instantiation) of that class. The procedure to
create an object is similar to a function call.

>>> harry = Person()


e.g.---

lass Person:
"This is a person class"
age = 10

def greet(self):
print('Hello')

# create a new object of Person class


harry = Person()

# Output: <function Person.greet>


print(Person.greet)

# Output: <bound method Person.greet of <__main__.Person object>>


print(harry.greet)

# Calling object's greet() method


# Output: Hello
harry.greet()

Output

<function Person.greet at 0x7fd288e4e160>


<bound method Person.greet of <__main__.Person object at 0x7fd288e9fa30>>
Hello

Constructors in Python
Class functions that begin with double underscore __ are called special functions as they have
special meaning.

Of one particular interest is the __init__() function. This special function gets called whenever
a new object of that class is instantiated.

This type of function is also called constructors in Object Oriented Programming (OOP).

e.g---

class ComplexNumber:
def __init__(self, r=0, i=0):
self.real = r
self.imag = i

def get_data(self):
print(f'{self.real}+{self.imag}j')

# Create a new ComplexNumber object


num1 = ComplexNumber(2, 3)

# Call get_data() method


# Output: 2+3j
num1.get_data()

# Create another ComplexNumber object


# and create a new attribute 'attr'
num2 = ComplexNumber(5)
num2.attr = 10

# Output: (5, 0, 10)


print((num2.real, num2.imag, num2.attr))

# but c1 object doesn't have attribute 'attr'


# AttributeError: 'ComplexNumber' object has no attribute 'attr'
print(num1.attr)

Output

2+3j
(5, 0, 10)
Traceback (most recent call last):
File "<string>", line 27, in <module>
print(num1.attr)
AttributeError: 'ComplexNumber' object has no attribute 'attr'

Deleting Attributes and Objects


Any attribute of an object can be deleted anytime, using the del statement.

e.g---

>>> num1 = ComplexNumber(2,3)


>>> del num1.imag
>>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'imag'

>>> del ComplexNumber.get_data


>>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'get_data'

We can even delete the object itself, using the del statement.

>>> c1 = ComplexNumber(1,3)
>>> del c1
>>> c1
Traceback (most recent call last):
...
NameError: name 'c1' is not defined

Python Inheritance

Inheritance enables us to define a class that takes all the functionality from a parent class and
allows us to add more.

Python Inheritance Syntax


class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class

Derived class inherits features from the base class where new features can be added to it. This
results in re-usability of code.

Example of Inheritance in Python

To demonstrate the use of inheritance, let us take an example.

A polygon is a closed figure with 3 or more sides. Say, we have a class called Polygon defined
as follows.

class Polygon:
def __init__(self, no_of_sides):
self.n = no_of_sides
self.sides = [0 for i in range(no_of_sides)]

def inputSides(self):
self.sides = [float(input("Enter side "+str(i+1)+" : ")) for i in
range(self.n)]

def dispSides(self):
for i in range(self.n):
print("Side",i+1,"is",self.sides[i])
This class has data attributes to store the number of sides n and magnitude of each side as a list
called sides.

The inputSides() method takes in the magnitude of each side and dispSides() displays these
side lengths.

A triangle is a polygon with 3 sides. So, we can create a class called Triangle which inherits
from Polygon

class Triangle(Polygon):
def __init__(self):
Polygon.__init__(self,3)

def findArea(self):
a, b, c = self.sides
# calculate the semi-perimeter
s = (a + b + c) / 2
area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('The area of the triangle is %0.2f' %area)
>>> t = Triangle()

>>> t.inputSides()
Enter side 1 : 3
Enter side 2 : 5
Enter side 3 : 4

>>> t.dispSides()
Side 1 is 3.0
Side 2 is 5.0
Side 3 is 4.0

>>> t.findArea()
The area of the triangle is 6.00

Python super() function.

Two built-in functions isinstance() and issubclass() are used to check inheritances.

e.g-----------

>>> isinstance(t,Triangle)
True
>>> isinstance(t,Polygon)
True

>>> isinstance(t,int)
False

>>> isinstance(t,object)
True

Python Multiple Inheritance

A class can be derived from more than one base class in Python, similar to C++. This is called
multiple inheritance.

In multiple inheritance, the features of all the base classes are inherited into the derived class.
The syntax for multiple inheritance is similar to single inheritance.

e.g.-----------

class Base1:
pass

class Base2:
pass

class MultiDerived(Base1, Base2):


pass

Here, the MultiDerived class is derived from Base1 and Base2 classes.

e.g.-------

Python Operator Overloading


Python operators work for built-in classes. But the same operator behaves differently with
different types. For example, the + operator will perform arithmetic addition on two numbers,
merge two lists, or concatenate two strings.

This feature in Python that allows the same operator to have different meaning according to the
context is called operator overloading.

So what happens when we use them with objects of a user-defined class? Let us consider the
following class, which tries to simulate a point in 2-D coordinate system.

class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y

p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)

Output

Traceback (most recent call last):


File "<string>", line 9, in <module>
print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

Here, we can see that a TypeError was raised, since Python didn't know how to add two Point
objects together.

However, we can achieve this task in Python through operator overloading. But first, let's get a
notion about special functions.

Python Special Functions


Class functions that begin with double underscore __ are called special functions in Python.

These functions are not the typical functions that we define for a class. The __init__() function
we defined above is one of them. It gets called every time we create a new object of that class.

There are numerous other special functions in Python. Visit Python Special Functions to learn
more about them.

Using special functions, we can make our class compatible with built-in functions.

>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>

Suppose we want the print() function to print the coordinates of the Point object instead of
what we got. We can define a __str__() method in our class that controls how the object gets
printed. Let's look at how we can achieve this:

class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y

def __str__(self):
return "({0},{1})".format(self.x,self.y)

Python Advanced Topics

Python Iterators

Python Generators

Python Closures

Python Decorators

Python property (decorator)

Python RegEx (regular expressions)

Python Examples
How to Create Python Modules?
 module is a file that contains Python statements and definitions. A Python modules looks like this:e

example

calc.py
And this is what we put inside the module calc.py:

def add(a,b):

return a+b

def sub(a,b):

return a-b

def mul(a,b):

return a*b

def div(a,b):

return a/b

def exp(a,b):

return a**b

def floordiv(a,b):

return a//b

Also, calc is a package we create, and we place __init__.py

How can we Import Modules in Python?


Now, to import Python modules

>>> import calc

To find the name of this module, we can use the __name__ attribute.

>>> calc.__name__
Output
‘calc’
We can now use functions from this module:
We can also assign one of these functions a name:

>>> fd=calc.floordiv
>>> fd(5.5,4)

Output
1.0

https://data-flair.training/blogs/python-modules/

Default encoding is platform

windows................. is cp1252

Linux .....................is utf-8

when working with files in text mode, it is highly recommended to specify the encoding type.

f = open("test.txt", mode='r', encoding='utf-8')


what is the tkinter used in python programming:
Out of all the GUI methods, tkinter is the most commonly used method. It is a standard Python
interface to the Tk GUI toolkit shipped with Python. Python with tkinter is the fastest and
easiest way to create the GUI applications. Creating a GUI using tkinter is an easy task.

An iterable is an object that can return an iterator.

Any object with state that has an __iter__ method and returns
an iterator is an iterable. It may also be an object without state that implements a
__getitem__ method. - The
method can take indices (starting from zero) and raise an IndexError when the
indices are no longer valid.
Python's str class is an example of a __getitem__ iterable.
An Iterator is an object that produces the next value in a sequence when you call
next(*object*) on some object.
Moreover, any object with a __next__ method is an iterator. An iterator raises
StopIteration after exhausting the
iterator and cannot be re-used at this point.
Iterable classes:
Iterable classes define an __iter__ and a __next__ method. Example of an iterable
class :
class MyIterable:
def __iter__(self):
return self
def __next__(self):
#code
#Classic iterable object in older versions of python, __getitem__ is still
supported...
class MySequence:
def __getitem__(self, index):
if (condition):
raise IndexError
return (item)

Generators are simple ways to create iterators. A generator is an iterator


and an iterator is an iterable

Closure
Closures in Python are created by function calls. Here, the call to makeInc creates
a binding for x that is referenced inside the function inc.

Each call to makeInc creates a new instance of this function, but each instance has
a link to a
different binding of x.
def makeInc(x):
def inc(y):
Decorator
Decorator functions are software design patterns. They dynamically alter the
functionality of a function, method, or class without having to directly use
subclasses or change the source code of the decorated function.

When used correctly, decorators can become powerful tools in the development
process.

Decorator function
Decorators augment the behavior of other functions or methods. Any function
that takes a function as a parameter
and returns an augmented function can be used as a decorator

Regular Expressions (Regex)


Python makes regular expressions available through the re module.
Regular expressions are combinations of characters that are interpreted as rules
for matching substrings.

1) Matching the beginning of a string

2) Searching

3) Precompiled patterns

4) Flags

5) Replacing

6) Find All Non-Overlapping Matches

7) Checking for allowed characters

8) Splitting a string using regular expressions

9) Grouping

10) Escaping Special Characters

11) Match an expression only in specific locations


12) Iterating over matches using `re.finditer'

For
instance, the expression 'amount\D+\d+' will match any string composed by the
word amount plus an integral
number, separated by one or more non-digits, such as:amount=100, amount is 3,
amount is equal to: 33, etc.

first argument of re.match() is the regular expression, the second is the string to
match:

import re

import re
pattern = r"123"
string = "123zzb"
re.match(pattern, string)
# Out: <_sre.SRE_Match object; span=(0, 3), match='123'>
match = re.match(pattern, string)
match.group()
# Out: '123'
You may notice that the pattern variable is a string prefixed with r, which indicates that the string is a raw string
literal.

You might also like