Introduction of Python
Introduction of Python
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,
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.
Subtraction _ ,
Multiplication * ,
Division /,
Equal to =
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
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:
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.
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
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
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,
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
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.
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.
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 −
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 −
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,
Why Programming?
language, which was inspired by SETL, capable of exception handling and interfacing with
the Amoeba operating system. Its implementation began in December 1989.
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.”
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.
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.
global = 1
Output
a@ = 0
Output
6. Python Keywords
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.
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.
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>], ....
Python Statement
Instructions that a Python interpreter can execute are called statements.
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
a = (1 + 2 + 3 +
4 + 5 + 6 +
7 + 8 + 9)
Here, the surrounding parentheses ( ) do the line continuation implicitly. Same is the case
colors = ['red',
'blue',
'green']
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.
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.
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
def double(num):
"""Function to double the value"""
return 2*num
Output
https://www.programiz.com/python-programming/statement-indentation-comments
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
print (a)
print (b)
print (c)
x = y = z = "same"
print (x)
print (y)
print (z)
python variable x, y ,z
e.g
website = "apple.com"
print(website)
e.g next value
website = "apple.com"
print(website)
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.
PI = 3.14
GRAVITY = 9.8
import constant
print(constant.PI)
print(constant.GRAVITY)
Python............ *.py
C# (pronounced "C Sharp"), an object-oriented programming language created by Microsoft for use
with . NET Framework
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
For example:
PI
G
MASS
SPEED_OF_LIGHT
TEMP
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.
#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.
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.
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.
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,
4)Set literals.
print(fruits)
print(numbers)
print(alphabets)
print(vowels)
Output
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.
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.
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 [ ].
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])
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.
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])
# 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}
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))
Output
<class 'dict'>
d[1] = value
d['key'] = 2
Traceback (most recent call last):
File "<string>", line 9, in <module>
KeyError: 2
>>> float(5)
5.0
Output
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.
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.
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))
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.
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.
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 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])
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
Output
3.141592653589793
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.
Output
a = 5
print('The value of a is', a)
Arithmetic operators
Arithmetic operators are used to perform mathematical operations like addition, subtraction, multiplication, etc.
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 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 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.
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)
# 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
# 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
a=2
print('id(2) =', id(2))
a=2
print('id(a) =', id(a))
a = a+1
print('id(a) =', id(a))
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:
>>> 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.
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.
A scope is the portion of a program from where a namespace can be accessed directly without any prefix.
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.
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)
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)
a = 30
a = 30
a = 30
2. Python Flow Control
Python
if...else Statement:
Decision making is required when we want to execute a code only if a certain condition is
satisfied.
Here, the program evaluates the test expression and will execute statement(s) only if the test
expression is True.
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.
num = -1
if num > 0:
print(num, "is a positive number.")
print("This is also always printed.")
3 is a positive number
This is always printed
This is also always printed.
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.
Example of if...else
# Program checks if the number is positive or negative
# And displays an appropriate message
num = 3
if num >= 0:
print("Positive or Zero")
else:
print("Negative number")
Output
Positive or Zero
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.
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
if num > 0:
print("Positive number")
elif num == 0:
print("Zero")
else:
print("Negative number")
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.
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
4) pass Statement
Body of for
Here, val is the variable that takes the value of the item inside
the sequence on each iteration.
# List of numbers
numbers = [6, 5, 3, 8, 4, 2, 5, 4, 11]
The sum is 48
The range() function
We can generate a sequence of numbers using range() function.
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().
print(range(10))
print(list(range(10)))
print(list(range(2, 8)))
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]
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.
Output
I like pop
I like rock
I like jazz
The break keyword can be used to stop a for loop. In such cases, the else part is ignored.
digits = [0, 1, 5]
for i in digits:
print(i)
else:
print("No items left.")
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:
Output
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.
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.
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.
n = 10
while i <= n:
sum = sum + i
i = i+1 # update counter
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.
'''Example to illustrate
the use of else statement
with the while loop'''
counter = 0
Output
Inside loop
Inside loop
Inside loop
Inside else
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
The working of break statement in for loop and while loop is shown below.
print("The end")
Output
s
t
r
The end
Syntax of Continue
continue
Flowchart of continue
The working of continue statement in for and while loop is shown below.
How continue statement works in python
print("The end")
Output
s
t
r
n
g
The end
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.
def function(args):
pass
class Example:
pass
3.Python Functions
Python Function
1) Default Arguments
2) Keyword Arguments
3) Arbitrary Arguments
4) Recursive Function
5) Anonymous/Lambda Function
7) Global Keyword
8) Python Modules
9) Python Package
Syntax of Function
def function_name(parameters):
"""docstring"""
statement(s)
Above shown is a function definition that consists of the following components.
Types of Functions
Basically, we can divide functions into the following two types:
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__)
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
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.
def my_func():
x = 10
print("Value inside function:",x)
x = 20
my_func()
print("Value outside function:",x)
Output
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.
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.
Output
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.
We can provide a default value to an argument by using the assignment operator (=). Here is an
example.
greet("Kate")
greet("Bruce", "How do you do?")
Output
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:
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
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:
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."""
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.
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.
The following image shows the working of a recursive function called recurse.
Recursive Function in Python
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.
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
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.
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
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.
While normal functions are defined using the def keyword in Python, anonymous functions are
defined using the lambda keyword.
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.
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
def double(x):
return x * 2
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.
print(new_list)
Output
[4, 6, 8, 12]
Here is an example use of map() function to double all the items in a list.
print(new_list)
Output
Syntax:
functools.reduce(myfunction, iterable, initializer)
Example: reduce()
Copy
import functools
def mult(x,y):
print("x=",x," y=",y)
return x*y
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:
first_variable = "PYTHON"
print("--------------")
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.
def foo():
print("x inside:", x)
def foo():
global x
y = "local"
x = x * 2
print(x)
print(y)
foo()
Output
global global
local
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.
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.
x = "global"
def foo():
x = x * 2
print(x)
foo()
Output
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.
foo()
print(y)
Output
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.
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.
def inner():
nonlocal x
x = "nonlocal"
print("inner:", x)
inner()
print("outer:", x)
outer()
Output
inner: nonlocal
outer: nonlocal
def add():
print(c)
add()
However, we may have some scenarios where we need to modify the global variable from inside
a function.
def add():
c = c + 2 # increment c by 2
print(c)
add()
This is because we can only access the global variable but cannot modify it from inside the
function.
def add():
global c
c = c + 2 # increment by 2
print("Inside add():", c)
add()
print("In main:", c)
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.
Here is how we can share global variables across the python modules.
a = 0
b = "empty"
config.a = 10
config.b = "alphabet"
import config
import update
print(config.a)
print(config.
01b
.)
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
def bar():
global x
x = 25
foo()
print("x in main: ", x)
The output is :
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().
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)
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.
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.
We use the import keyword to do this. To import our previously defined module example, we
type the following in the Python prompt.
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..
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 math
print("The value of pi is", math.pi)
import math as m
print("The value of pi is", m.pi)
We have renamed the math module as m. This can save us typing time in some cases.
Note that the name math is not recognized in our scope. Hence, math.pi is invalid, and m.pi is
the correct implementation.
We can import specific names from a module without importing the module as a whole. Here is
an example.
In such cases, we don't use the dot operator. We can also import multiple attributes as follows:
We can import all names(definitions) from a module using the following construct:
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.
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.
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.
" We can use the reload() function inside the imp module to reload a module. "
For example, we have defined a function add() in the module example that we had in the
beginning.
>>> 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.
>>> 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.
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.
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.
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,
Game.Level.start.select_difficulty(2)
If this construct seems lengthy, we can import the module without the package prefix 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:
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 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.
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))
<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.
In Python, we can represent these numbers by appropriately placing a prefix before that number.
The following table lists these prefixes.
Binary----------------------- 0b
Octal------------------------ 0o
Hexadecimal-------------- 0x
e.g.------------
# Output: 107
print(0b1101011)
# 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.
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.
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.
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.
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.
print(D('1.1') + D('2.2'))
print(D('1.2') * D('2.50'))
Output
3.3
3.000
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 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.
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))
# Shuffle x
random.shuffle(x)
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.
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]
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.
# List indexing
# 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])
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.
print(my_list[-1])
print(my_list[-5])
When we run the above program, we will get the following output:
e
p
my_list = ['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.
print(odd)
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)
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.
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]
print(my_list)
print(my_list)
Output
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).
my_list = ['p','r','o','b','l','e','m']
my_list.remove('p')
# Output: 'o'
print(my_list.pop(1))
# Output: 'm'
print(my_list.pop())
my_list.clear()
# Output: []
print(my_list)
Output
Finally, we can also delete items in a list by assigning an empty list to a slice of elements.
They are accessed as list.method(). Some of the methods have already been used above.
# 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]
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.
Output
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.
We can test if an item exists in a list or not, using the keyword in.
# 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
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.).
# Empty tuple
my_tuple = ()
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.
print(a) # 3
print(b) # 4.6
print(c) # dog
Output
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'>
# Parentheses is optional
my_tuple = "hello",
print(type(my_tuple)) # <class 'tuple'>
Output
<class 'str'>
<class 'tuple'>
<class '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.
print(my_tuple[0]) # 'p'
print(my_tuple[5]) # 't'
# 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
The index of -1 refers to the last item, -2 to the second last item and so on.
# 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 :.
Output
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.
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.
# Output: ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')
print(my_tuple)
Output
We can also repeat the elements in a tuple for a given number of times using the * operator.
# 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 tuples
my_tuple = ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'i', 'z')
Output
Tuple Methods
Methods that add items or remove items are not available with tuple. Only the following two
methods are available.
print(my_tuple.count('p')) # Output: 2
print(my_tuple.index('l')) # Output: 3
Output
2
3
We can test if an item exists in a tuple or not, using the keyword in.
# 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
Output
Hello John
Hello Kate
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.
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
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.
my_string = "Hello"
print(my_string)
my_string = '''Hello'''
print(my_string)
Hello
Hello
Hello
Hello, welcome to
the world of Python
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).
#first character
print('str[0] = ', str[0])
#last character
print('str[-1] = ', str[-1])
#slicing 6
th to 2nd last character
print('str[5:-2] = ', str[5:-2])
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.
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
We cannot delete or remove characters from a string. But deleting the string entirely is possible
using the del keyword.
To learn more about the data types available in Python visit: Python Data Types
Concatenation of Two or More Strings
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.
# using +
print('str1 + str2 = ', str1 + str2)
# using *
print('str1 * 3 =', str1 * 3)
Writing two string literals together also concatenates them like + operator.
We can iterate through a string using a for loop. Here is an example to count the number of 'l's in
a string.
We can test if a substring exists within a string or not, using the keyword in.
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.
str = 'cold'
# enumerate()
list_enumerate = list(enumerate(str))
print('list(enumerate(str) = ', list_enumerate)
#character count
print('len(str) = ', len(str))
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.
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.
\\ Backslash
\a ASCII Bell
\b ASCII Backspace
\f ASCII Formfeed
\n ASCII Linefeed
>>> print("C:\\Python32\\Lib")
C:\Python32\Lib
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.
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.
# default(implicit) order
default_order = "{}, {} and {}".format('John','Bill','Sean')
print('\n--- Default Order ---')
print(default_order)
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.
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
>>> "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.
Output
{1, 2, 3}
{1.0, (1, 2, 3), 'Hello'}
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'
# initialize a with {}
a = {}
Output
<class 'dict'>
<class 'set'>
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)
Output
{1, 3}
{1, 2, 3}
{1, 2, 3, 4}
{1, 2, 3, 4, 5, 6, 8}
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).
# 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())
# clear my_set
# Output: set()
my_set.clear()
print(my_set)
print(my_set)
Output
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
Union is performed using | operator. Same can be accomplished using the union() method.
# use | operator
# Output: {1, 2, 3, 4, 5, 6, 7, 8}
print(A | B)
Output
{1, 2, 3, 4, 5, 6, 7, 8}
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}
Output
{4, 5}
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.
# use - operator on A
# Output: {1, 2, 3}
print(A - B)
Output
{1, 2, 3}
# use - operator on B
>>> B - A
{8, 6, 7}
# use difference function on B
>>> B.difference(A)
{8, 6, 7}
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().
# use ^ operator
# Output: {1, 2, 3, 6, 7, 8}
print(A ^ B)
Output
{1, 2, 3, 6, 7, 8}
Method Description
intersection_update() Updates the set with the intersection of itself and another
symmetric_difference_update() Updates a set with the symmetric difference of itself and another
update() Updates the set with the union of itself and others
Other Set Operations
Set Membership Test
# in keyword in a set
# initialize my_set
my_set = set("apple")
Output
True
False
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.
sorted() Returns a new sorted list from elements in the set(does not sort the set itself).
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.
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])
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.
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 = {}
# using dict()
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.
# Output: Jack
print(my_dict['name'])
# Output: 26
print(my_dict.get('age'))
# 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'
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.
# update value
my_dict['age'] = 27
# add item
my_dict['address'] = 'Downtown'
Output
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.
# create a dictionary
squares = {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Output: {1: 1, 2: 4, 3: 9}
print(squares)
# Output: {}
print(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
Method Description
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.
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.
Output
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
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}
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.
print(odd_squares)
Output
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.
# Output: True
print(1 in squares)
# Output: True
print(2 not in squares)
Output
True
True
False
Iterating Through a Dictionary
Output
1
9
25
49
81
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.
Here are some examples that use built-in functions to work with a dictionary.
# 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]
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.
1. Open a file
2. Read or write (perform operation)
3. Close the file
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.
Closing a file will free up the resources that were tied with the file.
It is done using the close()
Python has a garbage collector to clean up unreferenced objects but we must not rely on it to
close the file.
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.
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 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.
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.
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:
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).
We can read a file line-by-line using a for loop. This is both efficient and fast.
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']
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.
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).
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.
>>> 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']
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']
>>> os.listdir()
['new_one', 'old.txt']
>>> os.remove('old.txt')
>>> os.listdir()
['new_one']
>>> os.rmdir('new_one')
>>> os.listdir()
[]
>>> os.rmdir('test')
Traceback (most recent call last):
...
OSError: [WinError 145] The directory is not empty: 'test'
>>> 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)
>>> 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.
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.
>>> 1 / 0
>>> 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'
We can view all the built-in exceptions using the built-in local() function as follows:
print(dir(locals()['__builtins__']))
Some of the common built-in exceptions in Python programming along with the error that cause
them are listed below:
KeyboardInterrupt Raised when the user hits the interrupt key ( Ctrl+C or Delete).
RuntimeError Raised when an error does not fall under any other category.
ZeroDivisionError Raised when the second operand of division or modulo operation is zero.
If required, we can also define our own exceptions in Python.
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.
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.
randomList = ['a', 0, 2]
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:
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:
# handle all other exceptions
pass
Raising Exceptions in Python
In Python programming, exceptions are raised when errors occur at runtime.
We can optionally pass values to the exception to clarify why that exception was raised.
>>> 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.
try:
num = int(input("Enter a number: "))
assert num % 2 == 0
except:
print("Not an even number!")
else:
reciprocal = 1/num
print(reciprocal)
Output
Enter a number: 1
Not an even number!
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.
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 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.
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.
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
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.
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
"""
Output
The inherited __str__ method of the Exception class is then used to display the corresponding
message when SalaryNotInRangeError is raised.
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 __str__(self):
return f'{self.salary} -> {self.message}'
Output
One of the popular approaches to solve a programming problem is by creating objects. This is
known as Object-Oriented Programming (OOP).
attributes
behavior
The concept of OOP in Python focuses on creating reusable code. This concept is also known as
DRY (Don't Repeat Yourself).
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.
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.
obj = Parrot()
Suppose we have details of parrots. Now, we are going to show how to build the class and
objects of parrots.
# class attribute
species = "bird"
# instance attribute
def __init__(self, name, age):
self.name = name
self.age = 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.
Methods
Methods are functions defined inside the body of a class. They are used to define the behaviors
of an object.
# 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)
Output
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).
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 __.
def __init__(self):
self.__maxprice = 900
def sell(self):
print("Selling Price: {}".format(self.__maxprice))
c = Computer()
c.sell()
Output
Selling Price: 900
Selling Price: 900
Selling Price: 1000
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.
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()
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.
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.
The first string inside the class is called docstring and has a brief description about the class.
Although not mandatory, this is highly recommended.
class MyNewClass:
'''This is a docstring. I have created a new class'''
pass
A class creates a new local namespace where all its attributes are defined. Attributes may be data
or functions.
There are also special attributes in it that begins with double underscores __. For example,
__doc__ gives us the docstring of that class.
As soon as we define a class, a new class object is created with the same name. This class object
allows us to access the different attributes as well as to instantiate new objects of that class.
class Person:
"This is a person class"
age = 10
def greet(self):
print('Hello')
# Output: 10
print(Person.age)
Output
10
<function Person.greet at 0x7fc78c6e8160>
This is a person class
It can also be used to create new object instances (instantiation) of that class. The procedure to
create an object is similar to a function call.
This will create a new object instance named harry. We can access the attributes of objects using
the object name prefix.
Attributes may be data or method. Methods of an object are corresponding functions of that
class.
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')
Output
You may have noticed the self parameter in function definition inside the class but we called
the method simply as harry.greet() without any arguments. It still worked.
This is because, whenever an object calls its method, the object itself is passed as the first
argument. So, harry.greet() translates into Person.greet(harry).
In general, calling a method with a list of n arguments is equivalent to calling the corresponding
function with an argument list that is created by inserting the method's object before the first
argument.
For these reasons, the first argument of the function in class must be the object itself. This is
conventionally called self. It can be named otherwise but we highly recommend to follow the
convention.
Now you must be familiar with class object, instance object, function object, method object and
their differences.
Constructors in Python
Class functions that begin with double underscore __ are called special functions as they have
special meaning.
Of one particular interest is the __init__() function. This special function gets called whenever
a new object of that class is instantiated.
This type of function is also called constructors in Object Oriented Programming (OOP). We
normally use it to initialize all the variables.
class ComplexNumber:
def __init__(self, r=0, i=0):
self.real = r
self.imag = i
def get_data(self):
print(f'{self.real}+{self.imag}j')
Output
2+3j
(5, 0, 10)
Traceback (most recent call last):
File "<string>", line 27, in <module>
print(num1.attr)
AttributeError: 'ComplexNumber' object has no attribute 'attr'
In the above example, we defined a new class to represent complex numbers. It has two
functions, __init__() to initialize the variables (defaults to zero) and get_data() to display the
number properly.
An interesting thing to note in the above step is that attributes of an object can be created on the
fly. We created a new attribute attr for object num2 and read it as well. But this does not create
that attribute for object num1.
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
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.
Derived class inherits features from the base class where new features can be added to it. This
results in re-usability of code.
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.
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
>>> 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
Here, the MultiDerived class is derived from Base1 and Base2 classes.
The MultiDerived class inherits from both Base1 and Base2 classes.
In multilevel inheritance, features of the base class and the derived class are inherited into the
new derived class.
class Base:
pass
class Derived1(Base):
pass
class Derived2(Derived1):
pass
Here, the Derived1 class is derived from the Base class, and the Derived2 class is derived from
the Derived1 class.
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
# Output:
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class '__main__.Z'>,
# <class 'object'>]
print(M.mro())
Output
To know the actual algorithm on how MRO is calculated, visit Discussion on MRO.
This feature in Python that allows the same operator to have different meaning according to the
context is called operator overloading.
So what happens when we use them with objects of a user-defined class? Let us consider the
following class, which tries to simulate a point in 2-D coordinate system.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)
Output
Here, we can see that a TypeError was raised, since Python didn't know how to add two Point
objects together.
However, we can achieve this task in Python through operator overloading. But first, let's get a
notion about special functions.
These functions are not the typical functions that we define for a class. The __init__() function
we defined above is one of them. It gets called every time we create a new object of that class.
There are numerous other special functions in Python. Visit Python Special Functions to learn
more about them.
Using special functions, we can make our class compatible with built-in functions.
>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>
Suppose we want the print() function to print the coordinates of the Point object instead of
what we got. We can define a __str__() method in our class that controls how the object gets
printed. Let's look at how we can achieve this:
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0}, {1})".format(self.x, self.y)
p1 = Point(2, 3)
print(p1)
Output
(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.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x, self.y)
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x, self.y)
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)
Output
(3,5)
What actually happens is that, when you use p1 + p2, Python calls p1.__add__(p2) which in
turn is Point.__add__(p1,p2). After this, the addition operation is carried out the way we
specified.
Similarly, we can overload other operators as well. The special function that we need to
implement is tabulated below.
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.
def __str__(self):
return "({0},{1})".format(self.x, self.y)
p1 = Point(1,1)
p2 = Point(-2,-3)
p3 = Point(1,-1)
Output
True
False
False
Similarly, the special functions that we need to implement, to overload other comparison
operators are tabulated below.
__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
constructor
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)".
attributes
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.
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.
obj = 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.
# 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)
Output
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).
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 __.
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.
The first string inside the class is called docstring and has a brief description of the class.
Although not mandatory, this is highly recommended.
class MyNewClass:
'''This is a docstring. I have created a new class'''
pass
e.g-----
class Person:
"This is a person class"
age = 10
def greet(self):
print('Hello')
# Output: 10
print(Person.age)
Output
10
<function Person.greet at 0x7fc78c6e8160>
This is a person class
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.
lass Person:
"This is a person class"
age = 10
def greet(self):
print('Hello')
Output
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')
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'
e.g---
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.
Derived class inherits features from the base class where new features can be added to it. This
results in re-usability of code.
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
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
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
Here, the MultiDerived class is derived from Base1 and Base2 classes.
e.g.-------
This feature in Python that allows the same operator to have different meaning according to the
context is called operator overloading.
So what happens when we use them with objects of a user-defined class? Let us consider the
following class, which tries to simulate a point in 2-D coordinate system.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p1 = Point(1, 2)
p2 = Point(2, 3)
print(p1+p2)
Output
Here, we can see that a TypeError was raised, since Python didn't know how to add two Point
objects together.
However, we can achieve this task in Python through operator overloading. But first, let's get a
notion about special functions.
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 Iterators
Python Generators
Python Closures
Python Decorators
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
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/
windows................. is cp1252
when working with files in text mode, it is highly recommended to specify the encoding type.
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)
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
2) Searching
3) Precompiled patterns
4) Flags
5) Replacing
9) Grouping
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.