Nothing Special   »   [go: up one dir, main page]

Arun Teaches Python A Step by Step Guide

Download as pdf or txt
Download as pdf or txt
You are on page 1of 264
At a glance
Powered by AI
The key takeaways are about copyright, licensing, and permissions related to the content of the document.

Packages in Python allow organizing a collection of modules and subpackages hierarchically using dotted module names for structuring the namespace.

A package can contain submodules and subpackages. It also contains an __init__.py file to identify the directory as containing a package.

@Copyright 2015 - All rights reserved.

In no way is it legal to reproduce, duplicate, or transmit any part of this


document in either electronic means or in printed format. Recording
of this publication is strictly prohibited any storage of this document is
not allowed unless with written permission from the publisher. All rights
reserved.
The information provided herein is stated to be truthful and consistent,
in that any liability, in terms of inattention or otherwise, by any usage
or abuse of any policies, processes, or directions contained within is
the solitary and utter responsibility of the recipient reader. Under no
circumstances will any legal responsibility or blame be held against
the publisher for any reparation, damages, or monetary loss due to
the information herein, either directly or indirectly.
Respective authors own all copyrights not held by the publisher.
Legal Notice:

This book is copyright protected. This is only for personal use. You
cannot amend, distribute, sell, use, quote or paraphrase any part or
the content within this book without the consent of the author or
copyright owner. Legal action will be pursued if this is breached.
Disclaimer Notice:
Please note the information contained within this document is for
educational and entertainment purpose only. Every attempt has been
made to provide accurate, up to date and reliable complete
information. No warranties of any kind expressed or implied. Readers
acknowledge that the author is not engaging in the rendering of legal,
financial, medical or professional advice.
Please address comments and questions concerning this book to the
publisher/author at the email id:
arun.python.books@gmail.com
Dedication

This book is dedicated to my daughters Mainu and Shainu. I could not


able to spend much time with them. Mainu is just 3 years old at the
time of writing this book and she use to wait for me up to 2:00 AM to
go to bed with me. Shainu is just 9 month old baby.

Acknowledgments

My wife Arunima and daughters continue to remain my main source of


inspiration. Thanks to Arunima and Kids.
About the Author

Arun Baruah is currently working as a Senior Consultant – Big Data


and Advanced Analytics in an MNC Company in India. He is having
over 10 years of software development experience and about 5
years of prior teaching experience. He holds a PhD degree in
Computer Science & Engineering from Atlantic International
University (USA) and a Master Degree in Computer Application
(MCA) from IGNOU. His research interest includes High
Performance Computing, Deep Learning, Machine Learning and
emerging Big Data Technologies.
Introduction

First of all I would like to thank you for purchasing the book.
"Arun Teaches Python" is a beginner’s guide to Python Programming
which covers Python 2.x to 3.4 up to date. The level of the book is
Beginners to Intermediate. This book contains step by step
information right from downloading and installing Python to Object
Oriented Programming. Each and every topics are accompanied with
full practical examples along with the results. Thanks once again for
downloading this book. Happy learning!
Table of Contents
Introduction
Chapter 1: Getting Started
What is Python?
Versions of Python
Downloading and Installing Python
Install Python on Unix/Linux platforms
Install Python on Mac platforms
Downloading Eclipse IDE and setup PyDev
Chapter 2: How Python Runs Programs
How Python Executes Programs
Python Implementations
CPython Variants
Other Implementations
Working Implementations
Numerical Accelerators
Writing our first Python Program
Chapter Summary
Chapter 3: Variables, Data Types, Expressions and Statements
Variables
Multiple Assignment
Standard Data Types
Strings
Lists
Tuples
Dictionary
Keywords or reserved words
Reserved classes of identifiers
Data Type Conversion Function
Statements
Operators and operands
Delimiters
Escape Sequence
Expressions
Rules of precedence - Order of Evaluation
Modulus operator
String operations
Comments in Python
Control Instructions in Python
Chapter Summary
Chapter 4: The Decision Control Structure
Multiple Statements within if
The if-else Statement
The elif Statement
The nested IF statements
Chapter Summary
Chapter 5: Loop Control Statements
The while Loop
The for Loop
The range() built-in function
Python nested loops
The Loop Control Statements
Chapter Summary
Chapter 6: Functions
User-defined functions
Docstring of function
The return statement
Scope and Lifetime of variables
Pass by references
Flow of Execution
The Anonymous Functions
The map, filter, and reduce function
The map function
The filter function
The reduce function
List Comprehension
Filtered list comprehensions
Built-in functions
Chapter Summary
Chapter 7: File Input / Output and os.path
Python File Methods
Python File Modes
Creation of a new file
Creating Text Files
Creating text file in Append Mode
Creating Binary Files
Creating binary file in Append Mode
Opening an existing file
Moving to a specific location in a file (seeking)
Absolute and Relative file paths
Operating System Interfaces - os.path
Directories in Python
The mkdir() Method
The chdir() Method
The getcwd() Method
The rmdir() Method
List Directories and Files
Renaming a Directory or a File
Chapter Summary
Chapter 8: Regular Expressions
Basic Patterns
Performing Queries with Regular expression (Regex) in Python
Search method
Match method
Findall method
Repetition in the pattern
Leftmost & Largest match for the pattern
Escape character
Square Brackets
Chapter Summary
Chapter 9: Exception Handling
Raising exceptions
User-Defined Exceptions
Defining Clean-up Actions
Chapter Summary
Chapter 10: Object Oriented Programming
Object Oriented Paradigm
Basic Concepts of Object Oriented Programming
Classes
Objects
Data Abstraction and Encapsulation
Inheritance
Polymorphism
Dynamic Binding
Chapter Summary
Chapter 11: Classes and Objects
Creating Classes
Class Definition and Object Instantiation
Special Class Attributes in Python
Accessing Class Members
Private member variable example
Protected member variable
What is name mangling
Name mangling in Python
Why we have mentioned about name mangling?
Shall I use __ to make something private?
Property
Static vs. Instance Member Variable
Static vs. Instance Method
Id method
Chapter Summary
Chapter 12: Inheritance
Inheritance
Overriding Base-Class Members in a Derived Class
Overloading
Pythonic ways of writing function
Method Overloading in Python 3.4
Operator Overloading
Multiple inheritance
Chapter Summary
Chapter 13: Modules and Packages
Modules
More on Modules
Executing modules as scripts
Compiled Python files
The dir() Function
Packages
Chapter Summary
Chapter 1: Getting Started
What is Python?
Python is an interpreted, high-level programming language with Object-Oriented
programming capabilities. It is use as Rapid Application Development prototyping
as well as for use as a scripting or glue language to connect existing components
together. Python is a general-purpose computer programming language, ranked
among the top eight most popular programming languages in the world.
It can be used to create many things including web applications, desktop
applications as scripting interpreter and many more. Python is an open-source
language and it has a vast number of open-source communities. It is use by large
group of Scientific Community as well as Business Communities for Rapid
Prototyping. It is free, portable, and powerful and is relatively easy to learn.
Versions of Python
This edition has been brought up to date with Python releases 3.4.2 as well as 2.7.
Python 2.x is still using by vast majority of professionals for backward
compatibility. Python 3.0 was released in 2008. The final 2.x version 2.7 release
came out in mid-2010, with a statement of extended support for this end-of-life
release. The 2.x branch will see no new major releases after that. 3. x is under
active development and has already seen over five years of stable releases,
including version 3.3 in 2012 and 3.4 in 2014. This means that all recent standard
library improvements, for example, are only available by default in Python 3.x.
Guido van Rossum (the original creator of the Python language) decided to clean
up Python 2.x properly, with less regard for backwards compatibility than is the
case for new releases in the 2.x range. The most drastic improvement is the better
Unicode support (with all text strings being Unicode by default) as well as saner
bytes/Unicode separation.
Besides, several aspects of the core language (such as print and exec being
statements, integers using floor division) have been adjusted to be easier for
newcomers to learn and to be more consistent with the rest of the language, and
old cruft has been removed (for example, all classes are now new-style, "range()"
returns a memory efficient iterable, not a list as in 2.x). [1]
Downloading and Installing Python
Python could be downloaded from https://www.python.org/downloads or from
many other popular distribution like ActivePython, Anaconda, Canopy, WinPython
and many more. In this section we will download python 3.4.3 from python.org for
Windows.
Select
the

downloaded python windows installer and follow the simple click. The setup
wizard should launch. You should just click "Next" for every option in the setup
wizard (i.e. use the defaults), unless you have some specific reason not to.
After successful installation, select IDLE (Python 3.4 GUI) or Python 3.4 (Command
Line) to write ‘Hello Python!’
Install Python on Unix/Linux platforms

Python comes preinstalled on most Linux distributions, and is available as a


package on all others. In case your Linux version doesn't have Python 3.4.3, you
could download the source files from
https://www.python.org/downloads/source/and compile and update it to 3.4.2. In
the example below, we will show you to update to Python 3.4.3 for Ubuntu 14.04
LTS which has Python 2.7.6 pre-installed:
Most

distribution is pre-installed with 2.7.x version. In order to install 3.4.3, download


the source code from https://www.python.org/downloads/source/ (Gzipped
source tarball) and follow the following instruction step by step:
1) Download python source code version 3.4.3 from the above link.
2) Extract it to a temporary directory within your Downloads folder.
3) Open a terminal session and type the below command no#4.
4) sudo apt-get build-dep python3.4
5) Navigate to the folder with cd ~/Downloads/Python-3.4.3
6) Run the following commands from the terminal one by one:
a) ./configure
b) make
c) make test
d) sudo make install
Note: The above process would take at least 10-20 minutes depending upon the
speed of the computer. After successful installation open a terminal and type the
following:
It will lend you in python 2.7.x. In order to run python3, type $python3
In order
to make
python3
as
default
python

environment, edit the /.bashrc file and add alias

After saving the bashrc, type source ~/.bashrc and press enter, to start Python
3.4.3, type the below command as shown below:

Note: Both Python 2.7.x and Python 3.x would reside in their respective
directories. In order to use Python 2.7.x type python2 in the terminal to use
python2.7.x. In many scientific programming developers still prefer to use this
version because still many scientific libraries are not ported to Python3.x.
Install Python on Mac platforms
Download an OS X .dmg file called "python-3.4.1-macosx10.6.dmg" to the
download folder and follow instructions:

Open the DMG, following screen appears:


Click continue to install at your Mac.
Unlike Apple's default install of 2.x, the version 3.x that you're installing goes into
your own library folder. Using the symbol ~ as a shorthand for /Users/<your acct
name>, then we can write the location as:

The installer added the path for the above to your default path in .bashrc profile
so that when you type python3 in the command line, the system could find it. In
the command line type python3 to start the python interpreter:
Downloading Eclipse IDE and setup PyDev
Typing commands into the Python interpreter is a great way to experiment with
Pythons features, but it is not recommended for solving more complex problems.
When we want to write a program, we use a text editor or an IDE (Integrated
Development Environment) to write the Python instructions into a file. We can use
IDLE, Netbeans or Eclipse and many other IDEs. We will use Eclipse IDE which is
marvelous IDE and is freely available. Download Eclipse IDE from easyeclipse.org or
from eclipse.org for Windows, Mac or Linux. Ubuntu Linux users could also
download from Ubuntu Software Center. Unzip it and copy it into your home
directory.
Start Eclipse and follow the below mentioned steps:

When Eclipse comes up, select Help from the Menu Bar and select Install New
Software and follow next step as shown below:
Type PyDev and click Add button. Add Repository window pops up. Provide PyDev
in the Name and provide the location as shown below and click OK button. PyDev
starts downloading and will install. On successful installation, we could use Eclipse
IDE for professional python development.
Chapter Summary
This chapter concludes with what is python, versions of python and install
instruction to install python and Eclipse in Windows, Unix/Linux and Mac OS.
In next chapter, we will explore How Python Runs Programs.
Chapter 2: How Python Runs Programs
How Python Executes Programs
In this chapter we will explore Python program execution, how Python runs.
Python is an interpreted programming language. An interpreter executes programs
line by line and convert it into machine executable code so that the processor
could understand it and carried out the execution. Python is a scripting language,
you could write a Python script and save it with .py extension or you can also
directly write and execute individual statements in the Python shell.
Internally Python compiles your program i.e., your source code into an
intermediate code known as byte-code with .pyc extension like Java byte-code for
platform-independent execution and quick execution, so when you again try to
execute the program, it won’t compile it again and render it from this byte-code.
Python saves its .pyc byte code files in a subdirectory named __pycache__ located
in the directory where your source files resides. For example our helloworld.py is
converted into byte code with helloworld.pyc as shown below:

Wondering that python would create a __pycache__ directory inside pyout


directory. Normally, it should create automatically. But if it not created due to
some reason then we could create it with the module py_compile, either using the
interpreter shell or using the following command at the shell prompt shown
below:
a) Using Python interpreter shell: (In Linux environment, always make the .py file
executable before running using chmod +x helloworld.py )

b) Using command shell

But as we have said, you don't have to and shouldn't bother about compiling
Python code. The compilation is hidden from the user for a good reason. Some
newbies to Python wonder sometimes where these ominous files with the .pyc
suffix might come from. If Python has write-access for the directory where the
Python program resides, it will store the compiled byte code in a file that ends
with a .pyc suffix. If Python has no write access, the program will work anyway. The
byte code will be produced but discarded when the program exits.
Whenever a Python program is called, Python will check, if there exists a compiled
version with the .pyc suffix. This file has to be newer than the file with the .py
suffix. If such a file exists, Python will load the byte code, which will speed up the
start up time of the script. If there exists no byte code version, Python will create
the byte code before it starts the execution of the program. Execution of a Python
program means execution of the byte code on the Python Virtual Machine (PVM).

Every time a Python script is executed, byte code is created. If a Python script is
imported as a module, the byte code will be stored in the corresponding .pyc file.
The PVM is the runtime engine of Python; it’s always present as part of the Python
system, and it’s the component that truly runs your scripts.
Python Implementations
An "implementation" of Python should be taken to mean a program or
environment which provides support for the execution of programs written in the
Python language, as represented by the CPython reference implementation.
There have been and are several distinct software packages providing of what we
all recognize as Python, although some of those are more like distributions or
variants of some existing implementation than a completely new implementation
of the language.
CPython Variants
These are implementations based on the CPython runtime core (the de-facto
reference Python implementation), but with extended behavior or features in
some aspects.
1) CrossTwine Linker - a combination of CPython and an add-on library offering
improved performance (currently proprietary)
2) Stackless Python - CPython with an emphasis on concurrency using tasklets and
channels (used by dspython for the Nintendo DS)
3) wpython - is a re-implementation of (some parts of) Python, which drops
support for bytecode in favour of a wordcode-based model (where a is word is 16
bits wide). It also implements an hybrid stack-register virtual machine, and adds a
lot of other optimizations.
Other Implementations
These are re-implementations of the Python language that do not depend on (or
necessarily interact with) the CPython runtime core. Many of them reuse (a large
part of) the standard library implementation.
Note that most of these projects have not yet achieved language compliance.
However, many of these have goals and features or run in certain environments
that make them interesting in their own regard. The only implementations that
are known to be compatible with a given version of the language are IronPython,
Jython and PyPy.
Working Implementations
The following implementations may be comprehensive or even complete, but at
the very least can be said to be working in that you can run typical programs with
them already:
1) Brython - a way to run Python in the browser through translation to JavaScript
2) CLPython - Python in Common Lisp
3) HotPy - a virtual machine for Python supporting bytecode optimization and
translation (to native code) using type information gathered at run-time
4) IronPython - Python in C# for the Common Language Runtime (CLR/.NET) and
the FePy project's IronPython Community Edition (IPCE)
5) Jython - Python in Java for the Java platform
6) pyjs - (formally Pyjamas) a Python to JavaScript compiler plus Web/GUI
framework
7) PyMite - Python for embedded devices
8) PyPy - Python in Python, targeting several environments
9) pyvm - a Python-related virtual machine and software suite providing a nearly
self-contained "userspace" system
10) RapydScript - a Python-like language that compiles to JavaScript
11) SNAPpy - "a subset of the Python language that has been optimized for use in
low-power embedded devices" (apparently proprietary)
12) tinypy - a minimalist implementation of Python in 64K of code.
Numerical Accelerators
Copperhead - purely functional data-parallel Python, compiles to multi-core and
GPU backends.
Numba - NumPy-aware optimizing runtime compiler for Python.
CPython is the standard implementation, and the system that most programmers
will wish to use. We are using this version in this book presenting the core
language features. All other Python implementation have specific roles and
purposes. All implement the same Python language but defers in program
execution i.e., these executes programs in different ways.
For example, IronPython is an independent implementation of Python that
compiles Python code for a different runtime architectures i.e., Microsoft .NET and
Open Source Mono. Jython is also completely independent implementation of
Python that compiles source code for Java runtime architectures to provide direct
access to Java components.
The CPython is the original and standard implementation of Python. It is usually
called CPython because it is coded in portable ANSI C language. This version is
available from www.python.org. Most programmers like to use this version unless
they want to script Java or .NET applications with Python.
Writing our first Python Program

Let’s write our first Hello World Python program. Initially we will use Python shell
and Linux Command Shell or Dos Command prompt to test our program. In latter
chapters we will use Eclipse IDE when we write bigger programs.
Try this code in Python Shell interactively.
#!/usr/bin/env python
print ("Hello World!")
print( ‘Hello Python!.’)

Try the same code in a text editor in Windows and VI in Linux and save it as
helloworld.py. Windows user type the following in command prompt: python
helloworld.py and Unix/Mac/Linux users need to do one more step i.e., in the
command shell type:
$ chmod +x helloworld.py
$ python3 helloworld.py

Below screenshots shows using a vi editor.

Below is an example of using Python Shell interactively:


Note: #!/usr/bin/env python (Use this line for your reference in case you have
multiple copies of Python installed. This is to tell you that which python version
you are going to use, Python2 or Python3.
Chapter Summary
This chapter concludes with the execution model of Python - how Python runs
your programs and explored some common implementations, variations, the JIT
compilers and Python Virtual Machine (PVM).
In next chapter, we will explore Variables, Data types expressions and statements.
Chapter 3: Variables, Data Types, Expressions and
Statements
Variables
Variables are nothing but reserved memory locations to store values. When you
create a variable you reserve some space in memory. Based on the data type of a
variable, the interpreter allocates memory and decides what can be stored in the
reserved memory.
Assigning Values to Variables
A value is one of the basic things a program works with, for example 1, 2, 3, 3.14,
"Hello", "Hello world" etc. These values belong to different types: 1, 2, 3 are of
type integer, 3.14 is of type float and “Hello”’, “Hello World!” is are of type string.
Python variables do not need explicit declaration to reserve memory space. The
declaration happens automatically when you assign a value to a variable. The
equal sign (=) is used to assign values to variables.
Example 3.1
#!/usr/bin/python3
x = 10 # An integer assignment
y = 200 # An integer assignment
pi = 3.14 # A floating point assignment
empname = "Arun Baruah" # A string assignment
#This is comment line. Python 2 accept print without a parenthesis like print x but
Python 3 needs the #parenthesis as shown below.
print("x = %d" %x)
print("y = %d" %y)
print("pi =%f" %pi)
print("Employee Name is %s" %empname)

The output is shown below:


x = 10
y = 200
pi =3.140000
Employee Name is Arun Baruah
Multiple Assignment
Python allows you to assign a single value to several variables simultaneously.
Example 3.2
a=b=c=1
x, y, pi, empname = 10, 20, 3.14, "Mainu"
#Guess -- what is the output of the below code
aa = bb = cc= ename = 10, 20, 3.14, "Mainu"

In the first line of the above code a = b = c = 1, an integer object is created with the
value 1, and all the three variables are assigned to the same memory location.
You can also assign multiple objects with multiple variables, see the second line of
the above code, here 10, and 20 are assigned to x, and y respectively which is of
integer type, 3.14 is assigned to pi which is a float type and mainu is assigned to
empname which is a string type.
The third line of the above code will create a list of object, that we will discuss
latter in List chapter separately.
Standard Data Types
Python has various standard data types that are used to define the operations
possible on them and the storage method for each of them.
Python has five standard data types −
a) Numbers
b) String
c) List
d) Tuple
e) Dictionary
f) Numbers
Number data types store numeric values. Number objects are created when you
assign a value to them. Python supports four different numerical types −
a) int (signed integers)
b) long (long integers, they can also be represented in octal and hexadecimal)
c) float (floating point real values)
d) complex (complex numbers)
Here are some examples of numbers –
int long float complex
20 51924361L 3.14 3.15j
080 0xDEFABECBCDAECBFBAEA 32.3+e18 .656j
-0491 535433629833L -80.0 -.6545+0J
-0x260 -052315192735L - 3e+26J
32.34e100

Python allows you to use a lowercase l with long, but it is recommended that you
use only an uppercase L to avoid confusion with the number 1. Python displays
long integers with an uppercase L.
A complex number consists of an ordered pair of real floating-point numbers
denoted by x + yj, where x is the real part and y is the imaginary part of the
complex number.
Strings
Strings in Python are identified as a contiguous set of characters represented in
the quotation marks. Python allows for either pairs of single or double quotes. For
example emp=”Arun” or emp=’Arun’. Subsets of strings can be taken using the
slice operator ([ ] and [:] ) with indexes starting at 0 in the beginning of the string
and working their way from -1 at the end. The plus (+) sign is the string
concatenation operator and the asterisk (*) is the repetition operator in python if
used with strings.
Example 3.3 – Try the below example and see the results
#!/usr/bin/python3
str = 'Hello Python!'
print(str) # Prints complete string
print(str[0]) # Prints first character of the string
print(str[2:5]) # Prints characters starting from 3rd to 5th
print(str[2:]) # Prints string starting from 3rd character
print(str * 2) # Prints string two times
print(str + "Guys") # Prints concatenated string

The output will be as follows:


>>> str = 'Hello Python!'
>>>
>>> print(str) # Prints complete string
Hello Python!
>>> print(str[0]) # Prints first character of the string
H
>>> print(str[2:5]) # Prints characters starting from 3rd to 5th
llo
>>> print(str[2:]) # Prints string starting from 3rd character
llo Python!
>>> print(str * 2) # Prints string two times
Hello Python!Hello Python!
>>> print(str + "Guys") # Prints concatenated string
Hello Python!Guys
>>>
Lists
Lists are the most versatile of Python's compound data types. A list contains items
separated by commas and enclosed within square brackets ([]). To some extent,
lists are similar to arrays in C. One difference between them is that all the items
belonging to a list can be of different data type. In our example above in multiple
assignment example, we have shown one line of code i.e.,
#Guess -- what is the output of the below code
aa = bb = cc= ename = 10, 20, 3.14, "Mainu"

Here a list of aa, bb, cc, ename created with integers, float and string. In this
example line code, each of the variables are pointing to the same list.
The values stored in a list can be accessed using the slice operator ([ ] and [:]) with
indexes starting at 0 in the beginning of the list and working their way to end -1.
The plus (+) sign is the list concatenation operator, and the asterisk (*) is the
repetition operator. Below example shows more on list.
Example 3.4
#!/usr/bin/python3
list = [ 'mainu', 'shainu', 86 , 3.14, 50.2 ]
tinylist = [123, 'arun']
print(list) # Prints complete list
print(list[0]) # Prints first element of the list
print(list[1:3]) # Prints elements starting from 2nd till 3rd
print(list[2:]) # Prints elements starting from 3rd element
print(tinylist * 2) # Prints list two times
print(list + tinylist) # Prints concatenated lists

The output of the above example is shown below:


arun@ubuntu:~/Desktop/pyout$ vi ex1.py
arun@ubuntu:~/Desktop/pyout$ chmod +x ex1.py
arun@ubuntu:~/Desktop/pyout$ python3 ex1.py
['mainu', 'shainu', 86, 3.14, 50.2]
mainu
['shainu', 86]
[86, 3.14, 50.2]
[123, 'arun', 123, 'arun']
['mainu', 'shainu', 86, 3.14, 50.2, 123, 'arun']
arun@ubuntu:~/Desktop/pyout$
Tuples
A tuple is another sequence data type that is similar to the list. A tuple consists of
a number of values separated by commas. Tuples are enclosed within parentheses.
The main differences between lists and tuples are: Lists are enclosed in brackets ( [
] ) and their elements and size can be changed, while tuples are enclosed in
parentheses ( ( ) ) and cannot be updated. Tuples can be thought of as read-only
lists.
Tuple example 3.5
#!/usr/bin/python3
tuple = ( 'mainu', 'shainu', 86 , 3.14, 50.2 )
tinytuple = (123, 'arun')
print(tuple) # Prints complete tuple
print(tuple[0]) # Prints first element of the tuple
print(tuple[1:3]) # Prints elements starting from 2nd till 3rd
print(tuple[2:]) # Prints elements starting from 3rd element
print(tinytuple * 2) # Prints tuple two times
print(tuple + tinytuple) # Prints concatenated tuples

The output of the above example is shown below:


arun@ubuntu:~/Desktop/pyout$ vi tupleex.py
arun@ubuntu:~/Desktop/pyout$ chmod +x tupleex.py
arun@ubuntu:~/Desktop/pyout$ python3 tupleex.py
('mainu', 'shainu', 86, 3.14, 50.2)
mainu
('shainu', 86)
(86, 3.14, 50.2)
(123, 'arun', 123, 'arun')
('mainu', 'shainu', 86, 3.14, 50.2, 123, 'arun')
arun@ubuntu:~/Desktop/pyout$
The following code will throw error because we attempted to update a tuple. A
tuple is read-only. But update is possible with lists.
Example 3.6
arun@ubuntu:~/Desktop/pyout$ python3
Python 3.4.3 (default, May 25 2015, 18:46:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> tuple = ( 'mainu', 44 , 3.14, 'shainu', 33.33 )
>>> list = [ 'mainu', 44 , 3.14, 'shainu', 33.33 ]
>>> list[2] = 88 # Valid syntax with list
>>> tuple[2] = 88 # Invalid syntax with tuple
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>>
Dictionary
Dictionaries are kind of hash table type. They work like associative arrays or
hashes found in Perl or C# etc., and consist of key-value pairs. A dictionary key can
be almost any Python type, but are usually numbers or strings. Values, on the
other hand, can be any arbitrary Python object.
Dictionaries are enclosed by curly braces ({ }) and values can be assigned and
accessed using square braces ([]).
Example 3.7
#!/usr/bin/python3
#Dictionary stores key-value pair, later could be retrieved the values by keys
dict = {}
dict['mainu'] = "This is mainu"
dict[10] = "This is number 10"
empdict = {'name': 'arun','code':23, 'dept': 'IT'}

print(dict['mainu']) # Prints value for 'mainu' key


print(dict[10]) # Prints value for 10 key
print(empdict) # Prints complete dictionary
print(empdict.keys()) # Prints all the keys
print(empdict.values()) # Prints all the values

The output of the above program is as follows:


arun@ubuntu:~/Desktop/pyout$ python3 dictionary.py
This is mainu
This is number 10
{'name': 'arun', 'dept': 'IT', 'code': 23}
dict_keys(['name', 'dept', 'code'])
dict_values(['arun', 'IT', 23])
arun@ubuntu:~/Desktop/pyout$
Dictionary values are not stored in sorted order. Dictionaries have no concept of
order among elements. It is incorrect to say that the elements are "un ordered or
out of order"; they are simply unordered.
Keywords or reserved words
The following identifiers are used as reserved words, or keywords of the language,
and cannot be used as ordinary identifiers. There are 33 keywords in Python 3.4.3.
They must be spelled exactly as written here:
FALSE class finally is return
None continue for lambda try
TRUE def from nonlocal while
and del global not yield
as elif if or
assert else import pass
break except in raise

You might want to keep this list handy. If the interpreter complains about one of
your variable names and you don’t know why, you can refer it to see if it is in this
list.
Reserved classes of identifiers
Like the keywords, there are certain reserved classes of identifiers in Python which
have special meanings. These classes are identified by the patterns of leading and
trailing underscore characters:
_*
Not imported by from module import *. The special identifier _ is used in the
interactive interpreter to store the result of the last evaluation; it is stored in the
builtins module. When not in interactive mode, _ has no special meaning and is
not defined.
Note: The name _ is often used in conjunction with internationalization; refer to
the documentation for the gettext module for more information on this
convention.
__*__
System-defined names. These names are defined by the interpreter and its
implementation (including the standard library). Current system names are
discussed in the Special method names section and elsewhere. More will likely be
defined in future versions of Python. Any use of __*__ names, in any context, that
does not follow explicitly documented use, is subject to breakage without warning.
__*
Class-private names. Names in this category, when used within the context of a
class definition, are re-written to use a mangled form to help avoid name clashes
between “private” attributes of base and derived classes.
Data Type Conversion Function
You may need to perform conversions between the built-in types. To convert
between types, you simply use the type name as a function. There are several
built-in functions to perform conversion from one data type to another. These
functions return a new object representing the converted value.
Example 3.8
#!/usr/bin/python3
pi = 3.14
print("The value of pi is a floating point number : %f " %pi)
newpi = int(pi)
print("The converted value of pi which is stored in newpi : %d" %newpi)
x ="12345" #string type
y = int(x,10) #converted to int, providing optional base
z = int(x) #converted the string into an int omitting the base
print("The value of x = %s " %x)
print("The value of y = %d" %y)
print("The value of z= %d" %z)

The output is shown in the table below:


arun@ubuntu:~/Desktop/pyout$ python3 numconvert.py
The value of pi is a floating point number : 3.140000
The converted value of pi which is stored in newpi : 3
The value of x = 12345
The value of y = 12345
The value of z= 12345
arun@ubuntu:~/Desktop/pyout$

The following are the list of some built-in conversion functions:


Function Description
Converts x to an integer. base specifies the base if x is a
int(x [,base]) string.
Converts x to a long integer. base specifies the base if x is
long(x [,base] ) a string.
float(x) Converts x to a floating-point number.
complex(real
Creates a complex number.
[,imag])
str(x) Converts object x to a string representation.
repr(x) Converts object x to an expression string.
eval(str) Evaluates a string and returns an object.
tuple(s) Converts s to a tuple.
list(s) Converts s to a list.
set(s) Converts s to a set.
Creates a dictionary. d must be a sequence of (key,value)
dict(d) tuples.
frozenset(s) Converts s to a frozen set.
chr(x) Converts an integer to a character.
unichr(x) Converts an integer to a Unicode character.
ord(x) Converts a single character to its integer value.
hex(x) Converts an integer to a hexadecimal string.
oct(x) Converts an integer to an octal string.
Statements
Programs written in the Python language are composed of statements and
expressions. Expressions process objects and are embedded in statements. A
statement is a unit of code that the Python interpreter can execute. We have used
two kinds of statements: print and assignment so far.
We can write a Python statement or statements either in interactive mode in
Python Shell or write a Python script with .py extension. When we type a
statement in interactive mode, the interpreter executes it and also displays the
results. When there are many lines of code need to be written we prefer to write a
script which contains a sequence of statements.
Example 3.9
#All are statements
X = 56
Name=”Mainu”
Z = float(X)
print(X)
print(Name)
print(Z)
Operators and operands
Operators are special symbols that represent computations like addition,
subtraction, multiplication, division. The values the operator is applied to are
called operands.
The following tokens are operators:
+ - * ** / // %
<< >> & | ^ ~
< > <= >= == !=

The operators +, -, *, / and ** perform addition, subtraction, multiplication,


division and exponentiation, as in the following examples:
1 + 20 x-1 x * 10 + y y / b 5**2
Delimiters
The following tokens serve as delimiters in the grammar:
( ) [ ] { }
, : . ; @ = ->
+= -= *= /= //= %=
&= |= ^= >>= <<= **=
Escape Sequence
An escape sequence is a sequence of characters that does not represent itself
when used inside a character or string literal, but is translated into another
character or a sequence of characters that may be difficult or impossible to
represent directly. Escape sequences that begin with a \ sign. List of Python Escape
sequences are given below:
Escape Sequence Meaning
\newline Backslash and newline ignored
\\ Backslash (\)
\' Single quote (')
\" Double quote (")
\a ASCII Bell (BEL)
\b ASCII Backspace (BS)
\f ASCII Formfeed (FF)
\n ASCII Linefeed (LF)
\r ASCII Carriage Return (CR)
\v ASCII Vertical Tab (VT)
\ooo Character with octal value ooo
\xhh Character with hex value hh

Examples 3.10
#!/usr/bin/python3
totalmarks = 500
percentage = 70.5
print("The first line below this line displays without escape sequences")
print("Marks obtained =", totalmarks, "and Percentage = ", percentage)
print("\nNow we will use the escape sequence newline and tab sequence below")
print("\nMarks obtained =\t", totalmarks, "\tand Percentage = ", percentage)

The output is as follows:


arun@ubuntu:~/Desktop/pyout$ python3 escape.py
The first line below this line displays without escape sequences
Marks obtained = 500 and Percentage = 70.5
Now we will use the escape sequence newline and tab sequence below
Marks obtained = 500 and Percentage = 70.5
arun@ubuntu:~/Desktop/pyout$

We have seen in the above example how the \n prints in next line and \t is use for
tab spaces.
Expressions
An expression is a combination of values, variables, and operators. A value all by
itself is considered an expression, and so is a variable, so the following are all legal
expressions.
name='Mainu'
pi = 3.14
x = 10
y = x+pi
z = **x
Rules of precedence - Order of Evaluation
When more than one operator appears in an expression, the order of evaluation
depends on the rules of precedence. For mathematical operators, Python follows
mathematical convention. The acronym PEMDAS (Parenthesis, Exponentiation,
Multiplication, Division, Addition, and Subtraction) is a useful way to remember
the rules:
1) Parentheses have the highest precedence and can be used to force an
expression to evaluate in the order you want. For example 2 * (4-1) is 6 because
we are forcing (4-1) to evaluate first and then the result is multiplied by 2.
2) Exponentiation has the next highest precedence. In the expression 3 ** 2 + 1 is
10 and 3 ** 2 * 6 is 54.
3) Multiplication and Division have the same precedence, which is higher than
Addition and Subtraction, which also have the same precedence. So 2 * 3 - 1 is 5,
not 4, and 6 + 4 / 2 is 8, not 5.
4) Operators with the same precedence are evaluated from left to right.
Below table lists the order of operation (precedence rules) for Python operators.
All operators except the power (**) operator are evaluated from left to right and
are listed in the table from highest to lowest precedence. That is, operators listed
first in the table are evaluated before operators listed later. (Note that operators
included together within subsections, such as x * y, x / y, x // y, and x % y, have
equal precedence.)
Operator Name
(...), [...], {...} Tuple, list, and dictionary creation
´...´ String conversion
s[i], s[i:j] Indexing and slicing
s.attr Attributes
f(...) Function calls
+x, -x, ~x Unary operators
x ** y Power (right associative)
Multiplication, division, floor division,
x * y, x / y, x // y, x % y modulo
x + y, x - y Addition, subtraction
x << y, x >> y Bit-shifting
x&y Bitwise and
x^y Bitwise exclusive or
x|y Bitwise or
Comparison, identity, and sequence
x < y, x <= y, x > y, x >= y, membership tests
x == y, x != y
x <> y
x is y, x is not y
x in s, x not in s
not x Logical negation
x and y Logical and
x or y Logical or
lambda args: expr Anonymous function
Modulus operator
The modulus operator works on integers and yields the remainder when the first
operand is divided by the second. For example remainder =7 % 3. The modulus
operator is very useful, for example we can check whether a number is divisible by
another -- if x % y is zero, then x is divisible by y.
String operations
We can use the + operator with strings to concatenate two strings, means joining
the strings.
Example 3.11
>>> strName ="Arun"
>>> strLname ="Baruah"
>>> FullName = strName + strLname
>>> print(FullName)

The output of the above program is as follows:


ArunBaruah
Comments in Python
In Python, # symbol is use to add a comment. It is always good to add a comment
before a function so that other developers could easily understand what could be
in the function before looking into it. In all the examples shown above in chapter
2, you might have seen a comment #! /usr/bin/python3 at the beginning of the
scripts. This line is a comment because it starts with a # symbol and the line
suggest that this program will be using python 3.x as in the development
environment there could be other versions also installed.
Control Instructions in Python

The ‘Control Instructions’ enable us to specify the order in which the various
instructions in a program are to be executed by the computer. In other words the
control instructions determine the ‘flow of control’ in a program. There are mainly
three types of control instructions in Python as it excluded the switch-case
statements, but I will add an alternative to switch-case statement for the
programmers from C, C++, Java and other programming world who is so use to
switch-case statement. We will use a dictionary of function to use as an alternative
to switch statement.
So the three control types are as follows:
a) Sequence Control Instruction
b) Selection or Decision Control Instruction
c) Repetition or Loop Control Instruction
And the Alternative to switch-case which we will propose is:
e) Alternative to switch-case i.e., the dictionary of functions
The Sequence control instruction ensures that the instructions are executed in the
same order in which they appear in the program. Decision and Alternative to
switch-case control instructions allow the computer to take a decision as to which
instruction is to be executed next. The Loop control instruction helps computer to
execute a group of statements repeatedly. In the following chapters we are going
to learn these instructions in detail.
Chapter Summary
In this chapter we have learned about variables, assigning values to variables
including multiple assignments, standard data types, keywords or reserved words,
reserved classes of identifiers, data type conversion functions, statements,
operators and operands, delimiters, escape sequence, expressions, rules of
precedence - order of evaluation, modulus operator, string operations,
introduction to control instruction and how to comments. In the next chapter we
will learn about the decision control structure.
Chapter 4: The Decision Control Structure
We all need to alter our actions in the face of changing circumstances. If
the weather is fine, then I will go for a walk. If the highway is busy I would
take a diversion. If the price of a mobile phone is very high, we would look
elsewhere. You can notice that all these decisions depend on some
condition being met.
Python language too must be able to perform different sets of actions depending
on the circumstances.
Decision structures evaluate multiple expressions which produce TRUE or FALSE as
outcome. You need to determine which action to take and which statements to
execute if outcome is TRUE or FALSE otherwise.

Python programming language assumes any non-zero and non-null values as TRUE,
and if it is either zero or null, then it is assumed as FALSE value. Python
programming language provides following types of decision making statements.
Statement Description
if statements if statement consists of a Boolean expression
followed by one or more statements.
if...else statements An if statement can be followed by an
optional else statement, which executes when
the Boolean expression is FALSE.
nested if statements You can use one if or else if statement inside
another if or else if statement(s).
We will explore each of the above in the examples shown below:
Syntax:
if expression:
statement(s)

Example 4.1
#!/usr/bin/python3
age = 23
if ( age == 23 ) :
print("The age is 23")
print("Have a good day!")

When the above code is executed, it produces the following output –


The age is 23
Have a good day!

The keyword if tells the compiler that what follows is a decision control
instruction. The condition following the keyword if is always enclosed within a pair
of parentheses. If the condition, whatever it is, is true, then the statement is
executed. If the condition is not true then the statement is not executed; instead
the program skips past it. But how do we express the condition itself in Python?
And how do we evaluate its truth or falsity? As a general rule, we express a
condition using Python’s ‘relational’ operators. The relational operators allow us
to compare two values to see whether they are equal to each other, unequal, or
whether one is greater than the other. Here’s how they look and how they are
evaluated in Python.
This expression is true if
x == y x is equal to y
x != y x is not equal to y
x<y x is less than y
x>y x is greater than y
x <= y x is less than or equal to y
x >= y x is greater than or equal to y

The relational operators should be familiar to you except for the equality operator
== and the inequality operator !=. Note that = is used for assignment, whereas, ==
is used for comparison of two quantities. Here is a simple program, which
demonstrates the use of if and the relational operators.
Example 4.2
# !/usr/bin/python3
age =int(input("Enter your age :"))
if (age <= 18):
print("You are not eligible for voting, try in next election!")
print("Program ends")

The output of the above program is as shown below:


Enter your age :18
You are not eligible for voting, try in next election!
Program ends
Enter your age :41
Program ends

When we enter the input value up to 18, then the if condition checks if age <= 18
i.e., the expression is evaluated and return TRUE value so the next statement of
the if block runs and print the results. Similarly when we enter a value higher than
the range i.e., greater then 18, then the expression evaluates and return FALSE so
the Python interpreter do not execute the if block at all and so come out of it. The
next statement which is not a part of the if block will execute.
Note: In python there is no brackets {} as there in C or C++ or Java to control block
of code. In Python the block of code will be treated as one block as per the
indentation, after the conditional statement followed by a colon as shown in the
above examples.
Example 4.3
A Supermarket offers you, a discount of 10% if the quantity purchased is more
than 2000. Write a program to calculate the total expenses and enter the quantity
and price per item as input through the keyboard.
# !/usr/bin/python3
#input = quantity and rate
quantity = int(input("Enter quantity :"))
priceperitem = float(input("Enter rate :"))
discount=0.0
if(quantity >2000):
discount = 0.10
total=(quantity * priceperitem) -(quantity * priceperitem * discount)
print("Discount =%.2f" %discount)
print("Total expenses = %.2f" %total)

The output is shown below:


Enter quantity :1000
Enter rate :10.5
Discount =0.00
Total expenses = 10500.00
Enter quantity :2500
Enter rate :10.5
Discount =0.10
Total expenses = 23625.00

When we entered quantity as 1000, the if condition returns FALSE so no discount


was given but when we entered quantity greater than 2000, the condition returns
TRUE so 10% discount was given.
Multiple Statements within if
It is common in many programs to have more than one statement to be executed
if the expression following if is satisfied. If such multiple statements are to be
executed then they must be properly indented, as illustrated in the following
example.
Example 4.4
In the below program the current year and the year in which the employee joined
the organization are entered through the keyboard using input() function. If the
number of years for which the employee has served the organization is greater
than 2 then a bonus of USD 1500/- is given to the employee. If the years of service
are not greater than 2, then the program should do nothing.
# !/usr/bin/python3
bonus = 0.0
currentyear = int(input("Enter current year :"))
yearofjoining = int(input("Enter year of joining :"))
yearofservice = currentyear - yearofjoining
if(yearofservice >2):
bonus = 1500
print("Bonus =%d" %bonus)
print("Congratulation! We are happy to provide you a bonus of %d" %bonus)
print("We appreciate your long term association with us!")
print("\nThis statement is not part of the above if condition because it is not
indented as a part of the if statement")

The output of the above program is as follows:


Enter current year :2015
Enter year of joining :2000
Bonus =1500
Congratulation! We are happy to provide you a bonus of 1500
We appreciate your long term association with us!
This statement is not part of the above if condition because it is not indented as a
part of the if statement
Enter current year :2015
Enter year of joining :2014
This statement is not part of the above if condition because it is not indented as a
part of the if statement
The if-else Statement
The if statement by itself will execute a single statement, or a group of statements,
when the expression following if evaluates to true. It does nothing when the
expression evaluates to false. We can execute one group of statements if the
expression evaluates to true and another group of statements if the expression
evaluates to false. This could be done with the help of else statement.
Example 4.5
In a xyz company, an employee is paid his remuneration under these condition: If
his basic salary is less than USD. 2000, then HRA = 10% of basic salary and DA =
90% of basic salary. If his salary is either equal to or above USD. 2000, then HRA =
5% and DA = 80% of basic salary. We will write a program to find his gross salary.
# !/usr/bin/python3
#Gross salary calculation program
from itertools import repeat
basicsalary = int(input("Enter Basic Salary :"))
if(basicsalary < 2000):
hra = basicsalary * 10/100
da = basicsalary * 90/100
else:
hra = basicsalary * 5/100
da = basicsalary * 80/100
grosssalary = basicsalary + hra + da
print("Salary Slip :")
print("-" *50)
print("Your Basic Salary is %d" %basicsalary)
print("Your hra is calculated as %.2f" %hra)
print("Your da is calculated as %.2f" %da)
print("-" *50)
print("Gross salary is %.2f" %grosssalary)

The output of the above program is as follows:


Enter Basic Salary :1800
Salary Slip :
--------------------------------------------------
Your Basic Salary is 1800
Your hra is calculated as 180.00
Your da is calculated as 1620.00
--------------------------------------------------
Gross salary is 3600.00
Enter Basic Salary :3000
Salary Slip :
--------------------------------------------------
Your Basic Salary is 3000
Your hra is calculated as 150.00
Your da is calculated as 2400.00
--------------------------------------------------
Gross salary is 5550.00
The elif Statement
The elif statement allows you to check multiple expressions for TRUE and execute
a block of code as soon as one of the conditions evaluates to TRUE.
Similar to the else, the elif statement is optional. However, unlike else, for which
there can be at most one statement, there can be an arbitrary number of elif
statements following an if.
Syntax:
if expression1:
statement(s)
elif expression2:
statement(s)
elif expression3:
statement(s)
else:
statement(s)

Example 4.6
x = int(input("Please enter an integer: "))
if x < 0:
print('Negative number')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('Bigger number .....')

The output is as follows:


Please enter an integer: -1
Negative number
Please enter an integer: 0
Zero
Please enter an integer: 1
Single
Please enter an integer: 100
Bigger number .....

Core Python does not provide switch or case statements as in other languages, but
we can use if..elif...statements to simulate switch case as follows:
Example 4.7
Pizza choice example: Suppose you have visited a Pizza restaurant and you want to
order a pizza of your choice. Select Pizza from the menu.
print("Let's enjoy a Pizza, okay let's go inside the Pizzahut!")
print("Waiter, Please select Pizza of your choice from the menu")
pizzachoice = int(input("Please enter your choice of Pizza: "))
if pizzachoice == 1:
print('I want to enjoy a pizza napoletana')
elif pizzachoice == 2:
print('I want to enjoy a pizza rustica')
elif pizzachoice == 3:
print('I want to enjoy a pizza capricciosa')
else:
print("Sorry I do not want any of the listed Pizza's, please bring a Coca Cola for
me")

The output is as follows:


Let's enjoy a Pizza, okay let's go inside the Pizzahut!
Waiter, Please select Pizza of your choice from the menu
Please enter your choice of Pizza: 1
I want to enjoy a pizza napoletana
Let's enjoy a Pizza, okay let's go inside the Pizzahut!
Waiter, Please select Pizza of your choice from the menu
Please enter your choice of Pizza: 2
I want to enjoy a pizza rustica

Let's enjoy a Pizza, okay let's go inside the Pizzahut!


Waiter, Please select Pizza of your choice from the menu
Please enter your choice of Pizza: 3
I want to enjoy a pizza capricciosa

Let's enjoy a Pizza, okay let's go inside the Pizzahut!


Waiter, Please select Pizza of your choice from the menu
Please enter your choice of Pizza: 10
Sorry I do not want any of the listed Pizza's, please bring a Coca Cola for me

For those developers who have come from C, C++ or Java world, an
alternative to switch case statement is to either use a if..elif construct or to use
a self-made switch case statement i.e., first create function and assigned the
function to a Dictionary as shown in the below example:
Example 4.8
# this is the default function
def errorMessage():
print ("Incorrect input. Please enter a number between 0 and 3: ")
def function0():
print ("This is function 0")
def function1():
print ("This is function 1")
def function2():
print ("This is function 2")
def function3():
print ("This is function 3")
#create a dictionary {key:value} pairs
fnctDictionary = {'0': function0, '1': function1, '2': function2, '3': function3}
num = raw_input("Enter a number between 0 and 3 : ")
# if number is found as a key in the dictionary fnctDictionary, then
corresponding function
# is called, else the function errorMessage is called. So we can use this as
switch-case
fnctDictionary.get(num, errorMessage)()

The output is as follows:


Enter a number between 0 and 3 : 0
This is function 0
Enter a number between 0 and 3 : 1
This is function 1
Enter a number between 0 and 3 : 2
This is function 2
Enter a number between 0 and 3 : 3
This is function 3
Enter a number between 0 and 3 : 99
Incorrect input. Please enter a number between 0 and 3:
The nested IF statements
There may be a situation when you want to check for another condition after a
condition resolves to true. In such a situation, you can use the nested if construct.
In a nested if construct, you can have an if...elif...else construct inside another
if...elif...else construct. It is perfectly all right if we write an entire if-else construct
within either the body of the if statement or the body of an else statement. This is
called ‘nesting’of ifs.
Syntax
The syntax of the nested if...elif...else construct may be:
if expression1:
statement(s)
if expression2:
statement(s)
elif expression3:
statement(s)
else
statement(s)
elif expression4:
statement(s)
else:
statement(s)

This is shown in the following example program.


Example 4.9
#!/usr/bin/python3
var = 1000
if var < 2000:
print ("Expression value is less than 2000")
if var == 1500:
print ("Which is 1500")
elif var == 1000:
print ("Which is 1000")
elif var == 500:
print ("Which is 500")
elif var < 500:
print ("Expression value is less than 50")
else:
print ("Could not find true expression")

print "Good bye! Will enjoy Python Programming again!"

The output is as follows:


Expression value is less than 2000
Which is 1000
Good bye! Will enjoy Python Programming again!

In the above example, the variable var is assigned the value 1000 and the first if
statement checks if the var has less than 2000, the answer is yes, the print
statement is executed and the below if condition is false, so the elif statement
executed, it’s value is 1000 which is equal to the value in var so this is printed.
After that the rest statement is false so did not executed. Finally the print
statement which is outside of the if-elif-else construct is executed.
Chapter Summary
In this chapter we have learned about the decision control structure. In the next
chapter we will discuss the Loop construct.
Chapter 5: Loop Control Statements
The programs that we have developed so far used either a sequential or a
decision control instruction. In the first one, the calculations were carried
out in a fixed order, while in the second, an appropriate set of instructions
were executed depending upon the outcome of the condition being tested.
These programs were of limited nature, because when executed, they
always performed the same series of actions, in the same way, exactly
once.
Python programming language provide various control structures that allow for
more complicated execution paths.
A loop statement allows us to execute a statement or group of statements
multiple times. The following diagram illustrates a loop statement –

Python programming language provides following types of loops to handle looping


requirements. There are three methods by way of which we can repeat a part of a
program. They are as follows:
a) Using a while loop
b) Using a for loop
c) Nesting loops
We will discuss each of these methods in the following pages.
The while Loop
It is often the case in programming that you want to do something a fixed number
of times. For example you want to calculate simple interest for 5 sets of principal,
rate and number of years or calculate gross salary of 5 employees or as many
employees you have. Let us take the example of calculation of simple interest in
the below example:

Example 5.1
#!/usr/bin/python3
#calculation of simple interest. Ask user to input principal, rate of interest, number
of years
counter = 1
while(counter <= 3):
principal = int(input("Enter the principal amount :"))
numberofyears = int(input("Enter the number of years :"))
rateofinterest = float(input("Enter the rate of interest :"))
simpleinterest = principal * numberofyears * rateofinterest/100
print("Simple interest =%.2f" %simpleinterest)
#increase the counter by 1
counter = counter + 1
print("You have calculated simple interest for 3 time!")

The output is as follows:


Enter the principal amount :1000
Enter the number of years :5
Enter the rate of interest :10
Simple interest =500.00
Enter the principal amount :1000
Enter the number of years :5
Enter the rate of interest :13.5
Simple interest =675.00
Enter the principal amount :2500
Enter the number of years :2
Enter the rate of interest :10
Simple interest =500.00
You have calculated simple interest for 3 time!

The program executes all statements after the while 3 time. The logic for
calculating the simple interest is written within the while block followed by the
colon [while(counter <= 3):] which is properly indented. So whatever lines were
indented makes the block of statements of the while loop. The last print
statement which is not indented was not part of the while loop. Most important
point to note is to increment the counter, otherwise the program will enter into
an indefinite loop which will never end.
We could use relational or logical operators in the while loop for example:
Example 5.2
while(i<=10)
while(i>=10 and j <=20)
while(j > 10 and (b<15) or c<20))

Example 5.3
i=10
j=15
while(i>=10 and j <=20):
print("Its working!")
break

Example 5.4
b=10
c=15
j=15
while(j > 10 and (b<15) or (c<20)):
print("Its working!")
break

Note: If we do not provide a break statement in the above example then the loop
will continue forever.
The for Loop
For loops are traditionally used when you have a piece of code which you want to
repeat n number of times.
Example 5.5
for x in range(0, 3):
print "We're in %d position" % (x)

The output is as follows:


We're in 0 position
We're in 1 position
We're in 2 position

The for loop statement in Python differs a bit from what you may be used to in C
or C++. Rather than giving the user the ability to define both the iteration step and
halting condition (as C or C++), Python’s for statement iterates over the items of
any sequence (a list or a string), in the order that they appear in the sequence.
Another example follows:
Example 5.6
# Measure some strings:
words = ['apple', 'mango', 'banana', 'orange']
for w in words:
print( w, len(w))

The output is as follows:


('apple', 5)
('mango', 5)
('banana', 6)
('orange', 6)
The range() built-in function

If you do need to iterate over a sequence of numbers, the built-in function range()
comes in handy. It generates lists containing arithmetic progressions:
Example 5.7 (we are showing this example directly writing in Python interactive
shell)
# in IPython 2.2.0 -- An enhanced Interactive Python.
>>>range(10)
Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>range(5,10)
Out[2]: [5, 6, 7, 8, 9]
>>>range(0, 10, 3)
Out[3]: [0, 3, 6, 9]
>>>range(-10, -100, -30)
Out[5]: [-10, -40, -70]
#However in python 3 it displays slightly differently but concept is same
#Python 3.4.3 written in interactive Python shell
>>> range(10)
range(0, 10)
>>> range(5,10)
range(5, 10)
>>> print(range(10))
range(0, 10)
>>> range(-10, -100, -30)
range(-10, -100, -30)
>>>
#To iterate over the indices of a sequence, you can combine range() and len() as
follows:
>>>a = ['Mary', 'had', 'a', 'little', 'lamb']
>>>for i in range(len(a)):
... print i, a[i]

...
0 Mary
1 had
2a
3 little
4 lamb
Python nested loops
Python programming language allows to use nested loops i.e., one loop inside
another loop. We will explore more in the following examples:
Example 5.8 (nested for loop example)
#write a multiplication table from 1 to 10
for x in xrange(1, 11):
for y in xrange(1, 11):
print '%d * %d = %d' % (x, y, x*y)

The output of the above program would looks like the below partial output.
1*1=1
1*2=2
1*3=3
1*4=4
1*5=5
1*6=6
1*7=7
1*8=8
1*9=9
1 * 10 = 10
2*1=2
and so on up to
10 * 10 = 100
Example 5.8 (nested while loop example)
#!/usr/bin/python3
#find prime number within 30 integer numbers from 1 - 30
i=2
while(i <= 30):
j=2
while(j <= (i/j)):
if not(i%j): break
j=j+1
if (j > i/j) : print i, " is prime"
i=i+1
print "Good work!"

The output of the above program is as follows:


2 is prime
3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime
23 is prime
29 is prime
Good work!
The Loop Control Statements

Loop control statements change execution from its normal sequence. Python
supports the following control statements:
a) break statement
b) continue
The break statement terminates the current loop and resume execution at the
next statements. We have seen break statement in the above examples. Another
example is follows:
Example 5.9
# !/usr/bin/python3
# demo of a break statement. We will try to find a whether a number is prime or
not.
# All we have to do to test whether a number is prime or not, is to divide it
successively
# by all numbers from 2 to one less than itself. If remainder of any of these
divisions is zero,
# the number is not a prime. If no division yields a zero then the number is a prime
number.
#This is just a toy example just to demonstrate the break statement. As an exercise
try to #print all numbers which are prime and not prime by yourself
ctr = 2
num = int(input("Enter a Number :"))
while(ctr <= num -1):
if(num % ctr == 0):
print("Number is not prime!")
break;
ctr = ctr + 1
print("End of the program")

The output is as follows:


Enter a Number :9
Number is not prime!
End of the program

Enter a Number :3
End of the program

Enter a Number :4
Number is not prime!
End of the program

The continue statement returns the control to the beginning of the while loop. In
some programming situations we want to take the control to the beginning of the
loop, bypassing the statements inside the loop, which have not yet been executed.
The keyword continue allows us to do this.
Example of continue statement is as follows:
Example 5.10
#!/usr/bin/python3
x=5
while x > 0:
x = x -1
if x == 3:
continue
print 'Current value =', x

The output is the above program is as follows:


Current value = 4
Current value = 2
Current value = 1
Current value = 0
Chapter Summary
In this chapter we have learned about the loop control statement. In the next
chapter we will discuss about functions.
Chapter 6: Functions
A function is a self-contained block of reusable code that perform a
coherent task of some kind. When you define a function, you specify the
name and the sequence of statements. Later, you can “call” the function
by its name.
In Python, functions could be categorized as – the User-defined functions that we
the developers define while writing Programs for better modularity and code
reusability and the other type is the build-in functions which the Python language
provides us.
User-defined functions
The syntax for defining a function is as follows:
def functionname( arg1, arg2, arg3 ):
‘’’docstring of the function i.e., a brief introduction about the function’’’
#code inside the function
return [value]
#a function may not have any arguments or parameters like
def functionname():
#code inside the function

The keyword for defining a function in Python is the def keyword.


The rules for naming a function is same as for variable names. Letters, numbers
and underscore character are okay, but the first character can’t be a number. You
can’t use a keyword as the name of a function, and you should avoid having a
variable and a function with the same name. The empty parentheses after the
name indicate that this function doesn’t take any arguments. The first line of the
function definition is called the header; the rest is called the body. The header has
to end with a colon and the body has to be indented.
Example 6.1
Let’s define a function which displays Employee details in the computer console or
the GUI.
#!/usr/bin/python3
#user-defined function to print the Employee details
def displayEmployees(empCode, fName, lName, phone):
“This function displays the employee details”
print("Employee Code :%s" %empCode )
print("Employee name is :%s" %fName)
print("Employee title is :%s" %lName)
print("Employee's Contact number is %s" %phone)
return
#let's write the program to take data from keyboard and call the function
eCode =str(input("Enter Employee Code :"))
eFName =str(input("Enter Employee First Name :"))
eLName =str(input("Enter Employee Last Name :"))
ePhone =str(input("Enter Employee Phone Number with Country Code :"))
print("\nWelcome to Employee Management System Menu ")
print("-" * 50)
# call the user-defined function to display the Details
displayEmployees(eCode,eFName,eLName,ePhone)
print("-" * 50)

The output of the above program is as follows:


>>>
Enter Employee Code :100
Enter Employee First Name :arun
Enter Employee Last Name :baruah
Enter Employee Phone Number with Country Code :+91-837983
Welcome to Employee Management System Menu
--------------------------------------------------
Employee Code :100
Employee name is :arun
Employee title is :baruah
Employee's Contact number is +91-837983
--------------------------------------------------
>>>

Example 6.2
Let’s write a no argument function or functions with a parenthesis().
#!/usr/bin/python3
#user-defined function to print the Employee details
def welcomeMessage():
print("Welcome to the Hackers computer!")
print("Wanna Hack?")
return

print("I will call the function to display welcome message")


#call the function
welcomeMessage()

The output of the above program is as follows:


>>>
I will call the function to display welcome message
Welcome to the Hackers computer!
Wanna Hack?
>>>

In the above program we simply called the function and the function displayed
whatever was defined into the function.
Function parameters can be of any valid Python data type - int, float, list, tuple,
dictionary or user-defined classes.
Docstring of function
The first string after the function header is called the docstring and is short for
documentation string. It is used to explain in brief, what a function does. Although
optional, documentation is a good programming practice. In the above example i.e
5.6, we have a docstring immediately below the function header. We have used a
double quotes because it is just one line of strings but generally use triple quotes
so that docstring can extend up to multiple lines. This string is available to us as
__doc__ attribute of the function. If we type the following line in the command
shell we can see the output:
>>> print(displayEmployees.__doc__)
This function displays the employee details
>>>
The return statement
Function always returns a value. The return statement is used to exit a function
and go back to the place from where it was called. This statement can contain
expression which 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. If we see our above
examples, the function displayEmployee simply prints the employee details in the
GUI or the console. Actually there is nothing in that function to return. Python
internally returns a none object in such cases. In the below example we will create
a function that would return a value.
Example 6.3
#!/usr/bin/python3
def multiplyFunction(num1, num2):
'''This function multiply the parameters and return the result'''
result = num1 * num2
return result
#let's write the program to take data from keyboard and call the function
value1 = int(input("Enter a value :"))
value2 = int(input("Enter a value :"))
res = multiplyFunction(value1, value2)
#call the function to display the result
print("The result is %d" %res)

The output of the above program is as follows:


>>>
Enter a value :99
Enter a value :9
The result is 891
>>>

In the above program we are performing a multiplication and returning the result
using the return statement as return result.
Scope and Lifetime of variables
Scope of a variable is the part of a program where the variable is visible or
recognized. Parameters and variables defined inside a function is not visible from
outside. They have a local scope.
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. After the function return the value, they are destroyed. Let’s look at the
below example.
Example 6.4
#!/usr/bin/python3

def myFunc():
val = 5
print("Value inside myFunc is:",val)

#declare a var with the same name as in myFunc


val = 50
myFunc()
print("Value outside the function:",val)
myFunc()
print("Value outside the function:",val)

The output of the above program is as follows:


>>>
Value inside myFunc is: 5
Value outside the function: 50
Value inside myFunc is: 5
Value outside the function: 50
>>>
Here, we can see that the value of val is 50 initially. Even though the function
myFunc () changed the value of x to 5, it did not affect the value outside the
function. This is because the variable val inside the function is different (local to
the function) from the one outside. Although they have same names, they are two
different variables with different scope.
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 them or cannot overwrite them. In order to modify the value of variables
outside the function, they must be declared as global variables using the keyword
global.
Pass by references
In Python, all parameters are passed by reference. It means the address of the
physical memory location is passed or the reference to the memory location is
passed. So if you change what a parameter refers to within a function, the
change also reflects back in the calling function.
Example 6.5
#!/usr/bin/python3
# let's modify values from a user-defined function
def changeValue( fruitList ):
"This changes a passed list into this function"
fruitList.append(["Orange","Mango"]);
print ("Modified list from changeValue function: ", fruitList)
return

fruit_List = ["Apple", "Banana"];


print("Original list", fruit_List)
#now call the function
changeValue( fruit_List );
print ("Testing the original list after the function call: ", fruit_List)

The output is the above program is as follows:


>>>
Original list ['Apple', 'Banana']
Modified list from changeValue function: ['Apple', 'Banana', ['Orange', 'Mango']]
Testing the original list after the function call: ['Apple', 'Banana', ['Orange',
'Mango']]
>>>
Flow of Execution
Execution always begins at the first statement of the program. Statements are
executed one at a time, in order from top to bottom. So we have to define the
function before calling them.
The Anonymous Functions
Python supports the creation of anonymous functions. Anonymous functions are
not bound to a name at runtime, they are created using a construct called
"lambda". The lambda operator or lambda function is a way to create small
anonymous functions, i.e. functions without a name. These functions are throw-
away functions, i.e. they are just needed where they have been created. Lambda
functions are mainly used in combination with the functions filter(), map() and
reduce().
The general syntax of a lambda function is as follows:
lambda argument_list: expression
While the argument list consists of a comma separated list of arguments and the
expression is an arithmetic expression using these arguments. In the below
example we will use a lamda function to return the product.
Example 6.6
#!/usr/bin/python3
print("Lamda example.....")
val1 = int(input("Enter a number in val1 :"))
val2 = int(input("Enter a number in val2 :"))
#use a lamda function to multiply val1 and val2
result = lambda x, y : x * y
print(result(val1, val2))
The output of the above program is as follows:
>>>
Lamda example.....
Enter a number in val1 :90
Enter a number in val2 :9
810
>>>
The map, filter, and reduce function
Python provides several functions which enable a functional approach to
programming. Functional programming is all about expressions. We may say that
the Functional programming is an expression oriented programming. Python
provides the following:
1) lambda (discussed above)
2) map(aFunction, aSequence)
3) filter(aFunction, aSequence)
4) reduce(aFunction, aSequence)
5) list comprehension
The map function
The map() function applies a function to every member of an iterable (e.g.,a list)
and returns the result. Typically, one would use an anonymous inline function as
defined by lambda, but it is possible to use any function.
Example 6.7
#!/usr/bin/python2
#let's first demonstrate a map() with a user-definied function
#define a function which takes an input and return the squares
def square(x):
return x**2

#list of numbers
numbers =[1,2,3,4,5,6,7,8,9,10]

#use map() and pass the square() and the list


results = map(square, numbers)
print results

The output of the above program is as follows:


runfile('C:/Users/ABaruah/Documents/Python Scripts/tt1.py',
wdir='C:/Users/ABaruah/Documents/Python Scripts')

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Please note that the above program is compiled in Python 2.7.8. There is a little
change in the syntax in Python 3.x. i.e if we compile the above program while using
a print() then also we won’t get the result. We have to use an additional list().
Let’s re-write the above program so that we could see the exact result in Python
3.x.x (Here I am using Python 3.4.3)
Example 6.7
#!/usr/bin/python3
#let's first demonstrate a map() with a user-definied function
#define a function which takes an input and return the squares
def square(x):
return x**2

#list of numbers
numbers =[1,2,3,4,5,6,7,8,9,10]

#use map() and pass the square() and the list


results = list(map(square, numbers))
print (results)

The output of the above program is as follows:


Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit
(Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ========== RESTART ==========
>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>>

The above two programs are same but in the latter case we have use a list
function -
results = list(map(square, numbers)). So if we need to compile with Python 3.x.x we
need to use a list to output the list. If we compile without list() we will get the
output shown below:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit
(Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ========== RESTART ==========
>>>
<map object at 0x02E75C70>
>>>

Okay, another alternative program you could write to get the output from the list.
Let’s see that in the below example:
Example 6.7
#!/usr/bin/python3
#let's first demonstrate a map() with a user-definied function
#define a function which takes an input and return the squares
def square(x):
return x**2
#list of numbers
numbers =[1,2,3,4,5,6,7,8,9,10]
#use map() and pass the square() and the list
results = map(square, numbers)
print(list(results))

In the above example, instead of using a list() with map() we have used the list()
function with the print() function. The result is shown below:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit
(Intel)] on
>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>>

In the above examples, we have created a user-defined function square and using
a map function. That is one way of doing. In the below program we will use a
lamda function with the map() function.
Example 6.8
#!/usr/bin/python3
#list of numbers
numbers =[1,2,3,4,5,6,7,8,9,10]

#use map() and use lamda


results = map(lambda x: x**2, numbers)
print(list(results))

The output of the above program is as follows:


>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>>
The filter function
As the name suggests filter extracts each element in the sequence for which the
function returns True. Filter takes a function returning True or False and applies it
to a sequence, returning a list of only those members of the sequence for which
the function returned True. In the above examples we have use a map function
and lamda function to square a list of numbers. Let’s modify that program and
partially display squared results using a filter function.
Example 6.9
#!/usr/bin/python3
#list of numbers
numbers =[1,2,3,4,5,6,7,8,9,10]
#use map() with lamda
results =list(map(lambda x: x**2, numbers))
partial_squares = list(filter(lambda x: x > 5 and x < 50, results))
print(results)
print(partial _squares)

The output of the above program is shown below:


>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[9, 16, 25, 36, 49]
>>>
The reduce function
The reduce function continually applies the function to the sequence and returns
a single value. For example if we need to add a sequence of numbers say 1,2,3,4. It
would look like the below diagram:

Example 6.10
#!/usr/bin/python3
from functools import reduce
result = reduce( (lambda x, y: x + y), [1, 2, 3, 4] )
print(result)

The reduce function is in the functools in Python 3.x.x, so we have imported it in


the above example.
The output of the above program is as follows:
>>>
10
>>>

At each step, reduce passes the current addition, along with the next item from
the list, to the passed-in lambda function. By default, the first item in the
sequence initialized the starting value.
List Comprehension
List comprehensions provide a concise way to create lists. Common applications
are to make new lists where each element is the result of some operations applied
to each member of another sequence or iterable, or to create a subsequence of
those elements that satisfy a certain condition. The creator of Python, Guido van
Rossum prefers list comprehensions to constructs using map, filter, reduce and
lambda.
List comprehension is a complete substitute for the lambda function as well as the
functions map(), filter() and reduce(). The syntax of list comprehension is easier to
be grasped.
The simplest form of a list comprehension is as follows:
[expression-involving-loop-variable for loop-variable in sequence ]

This will step over every element of sequence, successively setting loop-variable
equal to every element one at a time, and will then build up a list by evaluating
expression-involving-loop-variable for each one. This eliminates the need to use
lambda forms, and thus generally produces a much more readable code than using
map() and a more compact code than using a for-loop. In the example below we
will write a program to square a list using list comprehension. We will modify the
same example where we have previously used lamda function.
Example 6.10
#!/usr/bin/python3
#example using a list comprehension
item =[1,2,3,4,5,6,7,8,9,10]
#list comprehension
squares = [ x**2 for x in item ]
print(squares)

The output is as follows:


>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>>
Example 6.11
#!/usr/bin/python3
#print the length of each word in the list
names=['Hello','I','love','Python']
print([len(nm)for nm in names ])
The output is as follows:
>>>
[5, 1, 4, 6]
>>>

In the above example we have constructed a list comprehension to count the


length of word present in a list called names. We have used len() built-function to
return the length.
Filtered list comprehensions
The final form of list comprehension involves creating a list and filtering it similarly
to using filter(). The filtering form of list comprehension takes the following form:
[ expression-involving-loop-variable for loop-variable in sequence if boolean-
expression-involving-loop-variable ]

This form is similar to the simple form of list comprehension, but it evaluates
boolean-expression-involving-loop-variable for every item and keeps only those
members for which the boolean expression is True. Let’s re-write our previous
example i.e., squaring the list of numbers and only display a partial elements
based on a condition.
Example 6.12
#!/usr/bin/python3
#example using a list comprehension
item =[1,2,3,4,5,6,7,8,9,10]
#list comprehension
squares = [ x**2 for x in item ]
#filtered list comprehension
partial_squares = [ x**2 for x in item if x**2 > 5 and x**2 < 50 ]
print(squares)
print(partial_squares)

The output is as follows:


>>>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[9, 16, 25, 36, 49]
>>>
Built-in functions
The Python interpreter has a number of functions built into it that are always
available. They are listed here in alphabetical order.
Built-in Description
Functions
abs() Return the absolute value of a number. The argument may
be a plain or long integer or a floating point number. If the
argument is a complex number, its magnitude is returned.
all() all(iterable): Return True if all elements of the iterable are
true (or if the iterable is empty). Equivalent to: def
all(iterable):
for element in iterable:
if not element:
return False
return True
any() any(iterable): Return True if any element of the iterable is
true. If the iterable is empty, return False. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
basestring() This abstract type is the superclass for str and unicode. It
cannot be called or instantiated, but it can be used to test
whether an object is an instance of str or unicode.
isinstance(obj, basestring) is equivalent to isinstance(obj,
(str, unicode)).
bin() Convert an integer number to a binary string. The result is a
valid Python expression. If x is not a Python int object, it
has to define an __index__() method that returns an
integer.
bool() Return a Boolean value, i.e. one of True or False. x is
converted using the standard truth testing procedure. If x is
false or omitted, this returns False; otherwise it returns
True. bool is also a class, which is a subclass of int. Class
bool cannot be subclassed further. Its only instances are
False and True.
bytearray() Return a new array of bytes. The bytearray class is a
mutable sequence of integers in the range 0 <= x < 256. It
has most of the usual methods of mutable sequences,
described in Mutable Sequence Types, as well as most
methods that the str type.
callable() Return True if the object argument appears callable, False if
not. If this returns true, it is still possible that a call fails, but
if it is false, calling object will never succeed. Note that
classes are callable (calling a class returns a new instance);
class instances are callable if they have a __call__()
method.
chr() chr(i): Return a string of one character whose ASCII code is
the integer i. For example, chr(97) returns the string 'a'. This
is the inverse of ord().
classmethod() Return a class method for function.
cmp() cmp(x, y): Compare the two objects x and y and return an
integer according to the outcome. The return value is
negative if x < y, zero if x == y and strictly positive if x > y.
compile() Compile the source into a code or AST object. Code objects
can be executed by an exec statement or evaluated by a
call to eval().
complex() class complex([real[, imag]]): Return a complex number
with the value real + imag*1j or convert a string or number
to a complex number. If the first parameter is a string, it
will be interpreted as a complex number and the function
must be called without a second parameter. The second
parameter can never be a string. Each argument may be
any numeric type (including complex). If imag is omitted, it
defaults to zero and the function serves as a numeric
conversion function like int(), long() and float(). If both
arguments are omitted, returns 0j.
delattr() delattr(object, name): This is a relative of setattr(). The
arguments are an object and a string. The string must be
the name of one of the object’s attributes. The function
deletes the named attribute, provided the object allows it.
For example, delattr(x, 'foobar') is equivalent to del
x.foobar.
dict() Create a new dictionary. The dict object is the dictionary
class.
dir() Without arguments, return the list of names in the current
local scope. With an argument, attempt to return a list of
valid attributes for that object.
divmod() divmod(a, b): Take two (non complex) numbers as
arguments and return a pair of numbers consisting of their
quotient and remainder when using long division. With
mixed operand types, the rules for binary arithmetic
operators apply. For plain and long integers, the result is
the same as (a // b, a % b). For floating point numbers the
result is (q, a % b), where q is usually math.floor(a / b) but
may be 1 less than that. In any case q * b + a % b is very
close to a, if a % b is non-zero it has the same sign as b, and
0 <= abs(a % b) < abs(b).
enumerate() enumerate(sequence, start=0): Return an enumerate
object. sequence must be a sequence, an iterator, or some
other object which supports iteration. The next() method
of the iterator returned by enumerate() returns a tuple
containing a count (from start which defaults to 0) and the
values obtained from iterating over sequence: >>> seasons
= ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

Equivalent to:

def enumerate(sequence, start=0):


n = start
for elem in sequence:
yield n, elem
n += 1
eval() The expression argument is parsed and evaluated as a
Python expression (technically speaking, a condition list)
using the globals and locals dictionaries as global and local
namespace. Example:
>>> x = 1
>>> print eval('x+1')
2
execfile() execfile(filename[, globals[, locals]]) : This function is
similar to the exec statement, but parses a file instead of a
string. It is different from the import statement in that it
does not use the module administration — it reads the file
unconditionally and does not create a new module.
file() file(name[, mode[, buffering]]): Constructor function for
the file type, described further in section File Objects. The
constructor’s arguments are the same as those of the
open() built-in function described below. When opening a
file, it’s preferable to use open() instead of invoking this
constructor directly. file is more suited to type testing (for
example, writing isinstance(f, file)).
filter() filter(function, iterable): Construct a list from those
elements of iterable for which function returns true.
iterable may be either a sequence, a container which
supports iteration, or an iterator. If iterable is a string or a
tuple, the result also has that type; otherwise it is always a
list. If function is None, the identity function is assumed,
that is, all elements of iterable that are false are removed.
float() class float([x]): Return a floating point number constructed
from a number or string x. If the argument is a string, it
must contain a possibly signed decimal or floating point
number, possibly embedded in whitespace. The argument
may also be [+|-]nan or [+|-]inf. Otherwise, the argument
may be a plain or long integer or a floating point number,
and a floating point number with the same value (within
Python’s floating point precision) is returned. If no
argument is given, returns 0.0.
format() format(value[, format_spec]): Convert a value to a
“formatted” representation, as controlled by format_spec.
The interpretation of format_spec will depend on the type
of the value argument, however there is a standard
formatting syntax that is used by most built-in types:
Format Specification Mini-Language.
frozenset() class frozenset([iterable]): Return a new frozenset object,
optionally with elements taken from iterable. frozenset is a
built-in class. Return a new set or frozenset object whose
elements are taken from iterable. The elements of a set
must be hashable. To represent sets of sets, the inner sets
must be frozenset objects. If iterable is not specified, a new
empty set is returned. (For more informattion visit -
https://docs.python.org/2/library/stdtypes.html#frozenset
)
getattr() getattr(object, name[, default]): Return the value of the
named attribute of object. name must be a string. If the
string is the name of one of the object’s attributes, the
result is the value of that attribute. For example, getattr(x,
'foobar') is equivalent to x.foobar. If the named attribute
does not exist, default is returned if provided, otherwise
AttributeError is raised.
globals() Return a dictionary representing the current global symbol
table. This is always the dictionary of the current module
(inside a function or method, this is the module where it is
defined, not the module from which it is called).
hasattr() hasattr(object, name): The arguments are an object and a
string. The result is True if the string is the name of one of
the object’s attributes, False if not. (This is implemented by
calling getattr(object, name) and seeing whether it raises an
exception or not.)
hash() hash(object): Return the hash value of the object (if it has
one). Hash values are integers. They are used to quickly
compare dictionary keys during a dictionary lookup.
Numeric values that compare equal have the same hash
value (even if they are of different types, as is the case for
1 and 1.0).
help() help([object]): Invoke the built-in help system. (This
function is intended for interactive use.)
hex() hex(x): Convert an integer number (of any size) to a
lowercase hexadecimal string prefixed with “0x”, for
example: >>> hex(255)
'0xff'
>>> hex(-42)
'-0x2a'
>>> hex(1L)
'0x1L'
id() id(object): Return the “identity” of an object. This is an
integer (or long integer) which is guaranteed to be unique
and constant for this object during its lifetime. Two objects
with non-overlapping lifetimes may have the same id()
value.
input() Equivalent to eval(raw_input(prompt)).This function does
not catch user errors. If the input is not syntactically valid,
a SyntaxError will be raised. Other exceptions may be
raised if there is an error during evaluation.
int() Return an integer object constructed from a number or
string x, or return 0 if no arguments are given.
isinstance() isinstance(object, classinfo): Return true if the object
argument is an instance of the classinfo argument, or of a
(direct, indirect or virtual) subclass thereof.
issubclass() issubclass(class, classinfo): Return true if class is a subclass
(direct, indirect or virtual) of classinfo. A class is considered
a subclass of itself.

iter() Return an iterator object.


len() Return the length (the number of items) of an object.
list() Return a list whose items are the same and in the same
order as iterable‘s items.
locals() Update and return a dictionary representing the current
local symbol table. Free variables are returned by locals()
when it is called in function blocks, but not in class blocks.
long() Return a long integer object constructed from a string or
number x.
map() Apply function to every item of iterable and return a list of
the results.
max() Return the largest item in an iterable or the largest of two
or more arguments.
memoryview() Return a “memory view” object created from the given
argument.
min() Return the smallest item in an iterable or the smallest of
two or more arguments.
next() Retrieve the next item from the iterator by calling its next()
method.
object() Return a new featureless object. object is a base for all
new style classes. It has the methods that are common to
all instances of new style classes.
oct() Convert an integer number (of any size) to an octal string.
open() Open a file, returning an object of the file type described in
section File Objects. If the file cannot be opened, IOError is
raised.
ord() ord(c): Given a string of length one, return an integer
representing the Unicode code point of the character when
the argument is a unicode object, or the value of the byte
when the argument is an 8-bit string. For example, ord('a')
returns the integer 97, ord(u'\u2020') returns 8224.
pow() Return x to the power y; if z is present, return x to the
power y, modulo z (computed more efficiently than pow(x,
y) % z). The two-argument form pow(x, y) is equivalent to
using the power operator: x**y.
print() Print objects to the stream file, separated by sep and
followed by end. sep, end and file, if present, must be given
as keyword arguments.

property() Return a property attribute for new-style classes (classes


that derive from object).
range() This is a versatile function to create lists containing
arithmetic progressions. It is most often used in for loops.
For example range(10)
raw_input() raw_input([prompt])If the prompt argument is present, it is
written to standard output without a trailing newline. This
is deprecicated and replace by input() in Python 3.x
reduce() Apply function of two arguments cumulatively to the items
of iterable, from left to right, so as to reduce the iterable to
a single value.
reload() Reload a previously imported module.
repr() repr(object): Return a string containing a printable
representation of an object.
reversed() Return a reverse iterator. seq must be an object which has
a __reversed__() method or supports the sequence
protocol (the __len__() method and the __getitem__()
method with integer arguments starting at 0).
round() round(number[, ndigits]): Return the floating point value
number rounded to ndigits digits after the decimal point. If
ndigits is omitted, it defaults to zero. The result is a floating
point number. Values are rounded to the closest multiple
of 10 to the power minus ndigits; if two multiples are
equally close, rounding is done away from 0 (so, for
example, round(0.5) is 1.0 and round(-0.5) is -1.0).
set() class set([iterable]): Return a new set object, optionally
with elements taken from iterable. set is a built-in class.
See set and Set Types — set, frozenset for documentation
about this class.
setattr() setattr(object, name, value): This is the counterpart of
getattr(). The arguments are an object, a string and an
arbitrary value. The string may name an existing attribute
or a new attribute. The function assigns the value to the
attribute, provided the object allows it. For example,
setattr(x, 'foobar', 123) is equivalent to x.foobar = 123.
slice() Return a slice object representing the set of indices
specified by range(start, stop, step).
sorted() Return a new sorted list from the items in iterable.
staticmethod() Return a static method for function.
str() Return a string containing a nicely printable representation
of an object. For strings, this returns the string itself.
sum() Sums start and the items of an iterable from left to right
and returns the total. start defaults to 0.
super() Return a proxy object that delegates method calls to a
parent or sibling class of type. This is useful for accessing
inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except
that the type itself is skipped.
tuple() Return a tuple whose items are the same and in the same
order as iterable‘s items.
type() With one argument, return the type of an object. The
return value is a type object. The isinstance() built-in
function is recommended for testing the type of an object.
unichr() unichr(i): Return the Unicode string of one character whose
Unicode code is the integer i. For example, unichr(97)
returns the string u'a'. This is the inverse of ord() for
Unicode strings. The valid range for the argument depends
how Python was configured – it may be either UCS2
[0..0xFFFF] or UCS4 [0..0x10FFFF]. ValueError is raised
otherwise. For ASCII and 8-bit strings see chr().
unicode() Return the Unicode string version of object
vars() vars([object]): Return the __dict__ attribute for a module,
class, instance, or any other object with a __dict__
attribute.
xrange() This function is very similar to range(), but returns an
xrange object instead of a list.
zip() This function returns a list of tuples, where the i-th tuple
contains the i-th element from each of the argument
sequences or iterables. The returned list is truncated in
length to the length of the shortest argument sequence.
__import__() __import__(name[, globals[, locals[, fromlist[, level]]]]):
This function is invoked by the import statement. It can be
replaced (by importing the __builtin__ module and
assigning to __builtin__.__import__) in order to change
semantics of the import statement, but nowadays it is
usually simpler to use import hooks (see PEP 302). Direct
use of __import__() is rare, except in cases where you want
to import a module whose name is only known at runtime.
Chapter Summary
In this chapter we have learned about the various functions, map, filter, reduce,
list comprehension. In the next chapter we will discuss about files.
Chapter 7: File Input / Output and os.path
Often it is not enough to just display the data on the screen, it becomes
necessary to store the data in a manner that can be later retrieved and
displayed either in part or in whole. This medium is usually a ‘file’ on the
disk. This chapter discusses how file I/O operations can be performed.
Python File Methods

Python File Methods


Methods Description
Close an open file. It has no effect if the file is
close() already closed.
Separate the underlying binary buffer from
detach() the TextIOBase and return it.
Return an integer number (file descriptor) of the
fileno() file.
isatty() Return True if the file stream is interactive.
Read atmost n characters form the file. Reads
read(n) till end of file if it is negative or None.
readable() Returns True if the file stream can be read from.
Read and return one line from the file. Reads in
readline(n=-1) at most n bytes if specified.
Read and return a list of lines from the file.
readlines(n=-1) Reads in at most nbytes/characters if specified.
Change the file position to offsetbytes, in
seek(offset,from=SEEK_SET) reference to from (start, current, end).
Returns True if the file stream supports random
seekable() access.
tell() Returns the current file location.
Resize the file stream to size bytes. If size is not
truncate(size=None) specified, resize to current location.
writable() Returns True if the file stream can be written to.
Write string s to the file and return the number
write(s) of characters written.
writelines(lines) Write a list of lines to the file.
Python File Modes

Python File Modes


Mode Description
r Open a file for reading. (default)
Open a file for writing. Creates a new file if it
w does not exist or overwrite the file if it exists.
Open a file for exclusive creation. If the file
x already exists, the operation fails.
Open for appending at the end of the file
without truncating it. Creates a new file if it
a does not exist.
t Open in text mode. (default)
b Open in binary mode.
t Open a file for updating (reading and writing)

There are different file operations that can be carried out on a file. These are:
1) Creation of a new file
2) Opening / Reading an existing file
3) Writing to a file
4) Moving to a specific location in a file (seeking)
5) Closing a file
Creation of a new file
In order to write into a file we need to open it in write 'w', append 'a' or exclusive
creation 'x' mode. If the given filename already exist then with the 'w' mode as it
will overwrite into the file.
Writing a string or sequence of bytes (for binary files) is done using write()
method. This method returns the number of characters written to the file. Let us
now write a program to write a file in hard disk.
Creating Text Files
Example 7.1
#file handling operations
#writing to a new file hello.txt
f = open('hello.txt', 'w', encoding = 'utf-8')
f.write("Hello Python Developers!")
f.write("Welcome to Python World")
f.flush()
f.close()

The file is created in the current directory because we have not specified the
directory, so it has created the file hello.txt in the current directory. If we open
that file we can see the below output:
Hello Python Developers!Welcome to Python World

Let’s now overwrite the same file and modify our program with writelines()
function and see the output.
Example 7.2
#file handling operations
#writing to a new file hello.txt
f = open('hello.txt', 'w', encoding = 'utf-8')
f.write("Hello Python Developers!")
f.write("Welcome to Python World")
mylist =["Apple", "Orange", "Banana"]
#writelines() is use to write multiple lines in to the file
f.writelines(mylist)
f.flush()
f.close()
The file is written into the disk with the following:
Hello Python Developers!Welcome to Python WorldAppleOrangeBanana

You might be wondering why the writelines() function doesn’t written line by line.
Well, unlike other languages like C# the writelines() function in Python writes a
sequence of text. The text is not written line by line in the file. If we want the text
to be written line by line in the text file then we have to modify our code and
insert a ‘\n’.
Example 7.3
#file handling operations
#writing to a new file hello.txt
f = open('hello.txt', 'w', encoding = 'utf-8')
f.write("Hello Python Developers!\n")
f.write("Welcome to Python World\n")
mylist =["Apple\n", "Orange\n", "Banana\n"]
#writelines() is use to write multiple lines in to the file
f.writelines(mylist)
f.flush()
f.close()

Now if we open the file, we could see the following output:


Hello Python Developers!
Welcome to Python World
Apple
Orange
Banana

Till now we have modified the same file and every time the file is overwritten. Let’s
now modify the same program and this time we will use append mode ‘a’.
Creating text file in Append Mode
Example 7.4
#file handling operations
#writing the file hello.txt in append mode
f = open('hello.txt', 'a', encoding = 'utf-8')
f.write("Now I am appending this line!\n")
f.write("Let's write another list\n")
mylist =["Cabbage\n", "Potato\n", "Tomato\n"]
#writelines() is use to write multiple lines in to the file
f.writelines(mylist)
f.flush()
f.close()

The time the file hello.txt is appended. The output is as follows:


Hello Python Developers!
Welcome to Python World
Apple
Orange
Banana
Now I am appending this line!
Let's write another list
Cabbage
Potato
Tomato
Creating Binary Files
We need to write data as binary files such as image files or sound files. We can
also write text data in binary, we must supply data in the form of objects that
expose data as bytes (e.g., byte strings, bytearray objects, etc.).
Example 7.5
# Write binary data to a file
#writing the file hello.dat write binary mode
f = open('hello.dat', 'wb')
#writing as byte strings
f.write(b"I am writing data in binary file!\n")
f.write(b"Let's write another list\n")
f.close()

Now open hello.dat in notepad to see what was written into the disk.
If we need to read or write text from a binary-mode file, we would use to decode
or encode function.
Example 7.6
# Write binary data to a file
#writing the file hello.dat write binary mode
f = open('hello.dat', 'wb')
text = 'Hello World'
f.write(text.encode('utf-8'))
f.close()
Creating binary file in Append Mode
Example 7.7
# Write binary data to a file
#writing the file hello.dat write append binary mode
f = open('hello.dat', 'ab')
line1 = 'Hello Python Developers!'
line2 = 'Binary files are great'
f.write(line1.encode('utf-8'))
f.write(line2.encode('utf-8'))
f.close()

The file would be appended.


With construct – Most of the times many developers forgot to close the file.
Python support with construct. For example - with open("test.txt",'w) as f: after
this colon block of python file handling code follows. In this case no need to
explicitly close the file. The Python compiler will take care of it. So it is a better
option to use this clause. Let’s see an example below using the with:
Example 7.8
# Write binary data to a file
#writing the file hello.dat write append binary mode
with open("hello.dat",ab) as f:
f.write("Hello world\n")
f.write("This is a demo using with \n\n")
f.write("This file contains three lines\n")

#no need to explicitly use f.close

The file would be created in the disk.


Example 7.9
# Write binary data to a file
#writing the file hello.dat write append binary mode
with open("hello.dat",'ab') as f:
f.write(b"Hello world\n")
f.write(b"This is a demo using with \n\n")
f.write(b"This file contains three lines\n")

#no need to explicitly use f.close

The file would be created in the disk.


Opening an existing file
We have created so many files in text mode as well as binary mode. Now let’s read
some of those files from the disk.
Example 7.10
# Read binary data to a file
#writing the file hello.dat write append binary mode

with open("hello.dat",'rb') as f:
data = f.read()
text = data.decode('utf-8')
print(text)

The output of the file is as follows:


>>>
Hello world
This is a demo using with
This file contains three lines
Hello world
This is a demo using with

This file contains three lines

>>>

Similarly to read a text file we would open it in text mode. This is left for you as an
exercise.
Moving to a specific location in a file (seeking)
Change the file position to offsetbytes, in reference to from (start, current, end).
Example 7.11
# Read binary data to a file
#writing the file hello.dat write append binary mode
with open("hello.dat",'rb') as f:
#reading first 10 characters
data = f.read(10)
text = data.decode('utf-8')
print(text)
#after reading 10 characters let's move the cursor to initial position
f.seek(0)
data = f.read()
text1 = data.decode('utf-8')
print("\n")
print(text1)

The output as follows:


>>>
Hello worl

Hello world
This is a demo using with

This file contains three lines


Hello world
This is a demo using with
This file contains three lines

>>>

In the first line of the output first 10 characters were written i.e., “Hello worl”.
After we seek the file pointer to the initial position and after that we use a read()
with empty parameters to read every things.
Before we move into a different topic let us see some more examples of reading
and writing files by providing hard coded path. But hard coded path is not
recommended for cross-platform portability. As a demo, these are shown below:

Example 7.12
# Read binary data to a file
#writing the file hello.dat write append binary mode

with open("C:\\Users\\ABaruah\\Desktop\\Pyout\\ospathTest\\hello.dat",'rb') as
f:
#reading first 10 characters
data = f.read(10)
text = data.decode('utf-8')
print(text)
#after reading 10 characters let's move the cursor to initial position
f.seek(0)
data = f.read()
text1 = data.decode('utf-8')

print("\n")
print(text1)

In the above example, we have hardcoded the file path. The output is shown
below:
>>>
Hello worl

Hello world
This is a demo using with

This file contains three lines


Hello world
This is a demo using with

This file contains three lines

>>>

In the same way we could also write a file in a specified path.


In the above example we have provided full path (hard coded)
i.e.,"C:\\Users\\ABaruah\\Desktop\\Pyout\\hello.dat"
From the drive letter, we knew that this program is written in windows
environment. Since we have hard coded with the absolute path (full path), if we
need to port it into Unix/Linux or Mac environment then we have to modify it
again and change the path something like /usr/home/Pyout. Since Python is cross
platform we would directly copy the Python program in any O/s and run the
program without any modification if we write our program in an intelligent ways.
Python provides a module known as os. We will discuss about os module in the
pages below.
Absolute and Relative file paths
Absolute file paths are notated by a leading forward slash or drive label. For
example, /usr/home/python3/pyout or C:/Windows/System32/cmd.exe.
Relative file paths are notated by a lack of a leading forward slash. For example,
pyout. A relative file path is interpreted from the perspective your current working
directory.
In Unix/Linux/Mac – command shell
$ pwd
/home/python/pyout
$ ls
helloworld.py

In Windows Command Prompt:


Dir
C:\Windows\System32

The above table shows Unix/Linux/Mac and Windows command ls or dir to list
directories.
Operating System Interfaces - os.path
Platform-independent manipulation of file names. Writing Python program to
work with files on multiple platforms is easy using the functions included in the
os.path module. Even programs not intended to be ported between platforms
should use os.path for reliable filename parsing.
Example 7.13
# Demo program to read / write crossplatform (different os environment)
#Reading the file hello.dat write append binary mode
import os
filePath = os.path.join(os.path.dirname(__file__), 'hello.dat')
with open(filePath,'rb') as f:
#reading first 10 characters
data = f.read(10)
text = data.decode('utf-8')
print(text)
#after reading 10 characters let's move the cursor to initial position
f.seek(0)
data = f.read()
text1 = data.decode('utf-8')

print("\n")
print(text1)

The output is as follows:


>>>
Hello worl

Hello world
This is a demo using with
This file contains three lines
Hello world
This is a demo using with

This file contains three lines

>>>

In the above program we are using os module by importing it and then using the
os.path.join and os.path.dirname(__file__), ‘hello.dat’. The __file__ refers to the
script's file name.
If we type the following line in Python Shell –
>>> os.path.dirname(__file__)
'C:/Users/ABaruah/Desktop/Pyout'
>>> filePath = os.path.join(os.path.dirname(__file__), 'hello.dat')
>>> filePath
'C:/Users/ABaruah/Desktop/Pyout\\hello.dat'

If we copy the Python script file and the hello.dat from windows to Linux or Mac
and copy it in a directory, we could able to run the above program without having
to modify a single line of code. The os.path.dirname(__file__) will return the path
of that O/s directory and os.path.join append the file name ‘hello.dat’. In this way
the above Python program become platform independent.
os.path.dirname(path) returns the directory name of pathname path and
os.path.join(path1[, path2[, ...]]) join one or more path components intelligently.
Directories in Python

Python handles directories too. The os module has several methods that help you
create, remove, and change directories.
The mkdir() Method
You can use the mkdir() method of the os module to create directories in the
current directory. You need to supply an argument to this method which contains
the name of the directory to be created.
>>> import os
>>> os.mkdir("ExampleDir")
>>>
The chdir() Method
You can use the chdir() method to change the current directory. The chdir()
method takes an argument, which is the name of the directory that you want to
make the current directory. For example we will change the directory to
ExampleDir –
>>> os.chdir("ExampleDir")
The getcwd() Method
The getcwd() method displays the current working directory.
>>> os.getcwd()
'C:\\Users\\ABaruah\\Desktop\\Pyout\\ExampleDir'
>>>
The rmdir() Method
The rmdir() method deletes the directory, which is passed as an argument in the
method.
>>> os.getcwd()
'C:\\Users\\ABaruah\\Desktop\\Pyout\\ExampleDir'
>>> os.mkdir("ex1")
>>>
>>> os.rmdir("C:\\Users\\ABaruah\\Desktop\\Pyout\\ExampleDir\\ex1")
>>>
List Directories and Files
All files and sub directories inside a directory can be listed using the listdir()
method. This method takes in a path and returns a list of sub directories and files
in that path. If no path is specified, it returns from the current working directory.
>>> os.chdir("C:\\Users\\ABaruah\\Desktop\\Pyout")
>>> os.listdir()
['.metadata', 'binFile.py', 'Data', 'ExampleDir', 'exampleFolder', 'files.py', 'foo.dat',
'foo.txt', 'hello.dat', 'hello.txt', 'IrisClassificationch2.py', 'MLDatasets', 'ospathTest',
'sklearn', 'somefile.bin', 't1', 'Temp', 'test', 'test1', 'tt.py',
'WebTrafficAnalysisCh1.py']
>>>
Renaming a Directory or a File
The rename() method can rename a directory or a file. The first argument is the
old name and the new name must be supplies as the second argument.
>>> os.rename('binFile.py','newBinFile.py')
>>>
Chapter Summary
In this chapter we have learned about File Input/Output functions and some
common functions available in os module. In the next chapter we will discuss
Regular expression.
Chapter 8: Regular Expressions
Python has a very powerful library called regular expressions that handles
many of searching and extracting tasks quite elegantly. Regular Expressions
are used in programming languages to filter texts or textstrings. It's
possible to check, if a text or a string matches a regular expression. The
syntax of regular expressions is the same for almost all programming and
script languages, e.g. Python, C++, Java, C# and others. The term "regular
expression", sometimes also called regex or regexp, is originated in
theoretical computer science. A very simple use of a regular expression
would be to locate the same word spelled two different ways in a text
editor.
Python provide us regular expression library which we must import before we
could use regular expression. The regular expression library is “re”, so we have to
import re in the beginning of the program. In the example below we will use the
simple search() function of the re library to search a text string.
Basic Patterns
The power of regular expressions is that they can specify patterns, not just fixed
characters. Here are the most basic patterns which match single characters shown
below:
1) a, X, 9, < -- ordinary characters just match themselves exactly. The meta-
characters which do not match themselves because they have special meanings
are: . ^ $ * + ? { [ ] \ | ( )
2) . (a period) -- matches any single character except newline '\n'
3) \w -- (lowercase w) matches a "word" character: a letter or digit or underbar [a-
zA-Z0-9_]. Note that although "word" is the mnemonic for this, it only matches a
single word char, not a whole word. \W (upper case W) matches any non-word
character.
4) \b -- boundary between word and non-word
5) \s -- (lowercase s) matches a single whitespace character -- space, newline,
return, tab, form [ \n\r\t\f]. \S (upper case S) matches any non-whitespace
character.
6) ^ = start, $ = end -- match the start or end of the string
7) \t, \n, \r -- tab, newline, return
8) \d -- decimal digit [0-9] (some older regex utilities do not support but \d, but
they all support \w and \s)
9) \ -- inhibit the "specialness" of a character. So, for example, use \. to match a
period or \\ to match a slash. If you are unsure if a character has special meaning,
such as '@', you can put a slash in front of it, \@, to make sure it is treated just as
a character.
Performing Queries with Regular expression (Regex) in
Python
The ‘re’ package provides several methods to perform queries on an input string.
These are as follows:
a) re.search()
b) re.match()
c) re.findall()
Search method
The search() method works like matches anywhere, search() doesn’t restrict us to
only finding matches at the beginning of the string, so searching for ‘orange’ in the
below example string finds a match:
Example 8.1
import re
string ='apple, orange, mango, orange'
match = re.search(r'orange', string)
print(match.group(0))

The output is as follows:


>>>
orange
>>>

The search() method, stops looking after it finds a match, so search()-ing for
‘orange’ in our example string only finds the second occurrence i.e., after apple.
Example 8.2
# In hello.txt the following lines are there

Hello Python Developers!


Welcome to Python World
Apple
Orange
Banana
Now I am appending this line!
Let's write another list
Cabbage
Potato
Tomato

#We will read this file and search some patterns below:

#!/usr/bin/python3
import re
#example using a regular expression
#let's open one of the file that we have created earlier
with open("C:\\Users\\ABaruah\\Desktop\\Pyout\\hello.txt",'r') as f:
text =re.search(r'Welcome', f.read())
print(text.group(0))

The output is as follows:


Welcome

We have use a very simple word search. Our search keyword was “Welcome” so
the file was searched for welcome and shown the result. Now let’s modify the
same code and see the output. We will only show the modified code line below.
While practicing you could only copy and replace this line to the above program.
text =re.search(r'W....me', f.read())

We have use four dots, these dots actually replace one character in the regex
pattern and output the word “Welcome”.
>>>
Welcome
>>>
Now let’s use a .* wild card character:
text =re.search(r'W.*me', f.read())

>>>
Welcome
>>>

Now let’s finally modify with the below code:


text =re.search(r'W.*', f.read())

The output is as follows:


>>>
Welcome to Python World
>>>

In the search keyword we have used “W.* “ which means everything after that so
the entire line was searched.
Match method
The match() method works like matches the beginning. The match() method works
is that it will only find matches if they occur at the start of the string being
searched.So for example, calling match() on the string ‘orange apple orange
mango’, looking for the pattern ‘orange’ will match:
Example 8.3
import re
string ='apple, orange, mango, orange'
strmatch = re.match(r'orange', string)
print(strmatch)

The output shown below results “None” because in the first position of the string
“apple” is there:
>>>
None
>>>

Now let us modify the above string in the below example:


Example 8.4
import re
string ='orange, apple, mango, orange'
strmatch = re.match(r'orange', string)
print(strmatch)

The output is as follows:


>>>
<_sre.SRE_Match object; span=(0, 6), match='orange'>
>>>
The match is found in the beginning so it is showing the match. But the correct
way to print is as follows:
import re
string ='orange, apple, mango, orange'
strmatch = re.match(r'orange', string)
print(strmatch.group(0))

The output is as follows:


>>>
orange
>>>
Findall method
The re.findall() method get a list of all matching patterns.
Example 8.5
import re
string ='apple, orange, mango, orange'
strmatch = re.findall(r'orange', string)
print(strmatch)

The output of the above example is a list of all search key word “orange”. In our
string variable we have two oranges so the output of the list returned two orange:
>>>
['orange', 'orange']
>>>

The findall() method come very handy to search common matching from a large
text string. One common example is the find the email #id’s from an email text
sting. Let’s write a program to in email# in the below example:
Example 8.6
import re
string = "Hello from arunbaruah@gmail.com to sangranran@gmail.com about the
party @8PM. Hay Sangram, I am remainding you for the party, Please don't forget
my favourite brand!"
searchstr = re.findall('\S+@\S+', string)
print(searchstr)

The output is as follows:


>>>
['arunbaruah@gmail.com', 'sangranran@gmail.com']
>>>
The important point to note the expression “searchstr = re.findall('\S+@\S+',
string)”. We have used a two character sequence that matches a non-whitespace
character (\S). The “\S+” matches as many non whitespace characters as possible
but it would not match the string “@8PM” because there are no non-blank
characters before the at-sign.

Okay, the above example returned us a list of the email #ids because of non-blank
or non-whitespace character in the beginning of the ids, as mentioned above that
it has ignored the @8PM. Let’s modify the above program and add some more
email #ids with some characters and see what happens:
Example 8.7
import re
string = "Hello from arunbaruah@gmail.com to sangranran@gmail.com
;dinesh@gmail.com ;kuldeep@gmail.com about the party @8PM. Hay Sangram, I
am remainding you for the party, Please don't forget my favourite brand!"
searchstr = re.findall('\S+@\S+', string)
print(searchstr)

The output is as follows:


>>>
['arunbaruah@gmail.com', 'sangranran@gmail.com', ';dinesh@gmail.com',
';kuldeep@gmail.com']
>>>

In the above output we could see that the other email #ids one extra character “;”
was also included. But that was not our intension to print. If we do not want such
junk character which may be present in the search string we have to modify our
search parameters. We were interested with email starting with letters only
because all email #id begins with a letter. Let’s modify the above search string so
that it searches with letters in the below program:
Example 8.8
import re
string = "Hello from 111baba@gmail.com arunbaruah@gmail.com to
sangranran@gmail.com ;dinesh@gmail.com ;kuldeep@gmail.com about the party
@8PM. Hay Sangram, I am remainding you for the party, Please don't forget my
favourite brand!"
searchstr = re.findall('[a-zA-Z]\S*@\S*[a-zA-Z]', string)
print(searchstr)

The output is as follows:


>>>
['baba@gmail.com', 'arunbaruah@gmail.com', 'sangranran@gmail.com',
'dinesh@gmail.com', 'kuldeep@gmail.com']
>>>

The junk character was ignored. But there was an email #id starting with number
“111baba@gmail.com” which we were not expecting. We can modify our search
string to include numbers. In the below example let’s see:
Example 8.8
import re
string = "Hello from 111baba@gmail.com arunbaruah@gmail.com to
sangranran@gmail.com ;dinesh@gmail.com ;kuldeep@gmail.com about the party
@8PM. Hay Sangram, I am remainding you for the party, Please don't forget my
favourite brand!"
searchstr = re.findall('[a-zA-Z0-9]\S*@\S*[a-zA-Z]', string)
print(searchstr)
Repetition in the pattern
Things get more interesting when you use + and * to specify repetition in the
pattern:
1) + -- 1 or more occurrences of the pattern to its left, e.g. 'i+' = one or more i's
2) -- 0 or more occurrences of the pattern to its left
3) ? -- match 0 or 1 occurrences of the pattern to its left
Leftmost & Largest match for the pattern
First the search finds the leftmost match for the pattern, and second it tries to use
up as much of the string as possible -- i.e. + and * go as far as possible (the + and *
are said to be "greedy").
The output is as follows:
>>>
['111baba@gmail.com', 'arunbaruah@gmail.com', 'sangranran@gmail.com',
'dinesh@gmail.com', 'kuldeep@gmail.com']
>>>
Escape character
The escape character is a special characters in regular expressions to match the
beginning or end of a line or specify wild cards, we need a way to indicate that
these characters are “normal” and we want to match the actual character such as
‘@’.
Square Brackets
Square brackets can be used to indicate a set of chars, so [abc] matches 'a' or 'b' or
'c'. The codes \w, \s etc. work inside square brackets too with the one exception
that dot (.) just means a literal dot. For the emails problem, the square brackets
are an easy way to add '.' and '-' to the set of chars which can appear around the
@ with the pattern r'[\w.-]+@[\w.-]+' to get the whole email address:
Example 8.9
import re
string = "Hello from 111baba@gmail.com arunbaruah@gmail.com to
sangranran@gmail.com ;dinesh@gmail.com ;kuldeep@gmail.com about the party
@8PM.
searchstr = re.search(r'[\w.-]+@[\w.-]+', string)
print(searchstr.group(0))

The output is as follows:


111baba@gmail.com
Chapter Summary
In this chapter we have learned about regular expression functions available in re
module. In the next chapter we will discuss Exception Handling.
Chapter 9: Exception Handling
Exceptions are the customary way in Python to indicate to a calling method
that an abnormal condition has occurred. When a method encounters an
abnormal condition (an exception condition) that it can't handle itself, it
may throw an exception. There are a number of built-in exceptions, which
indicate conditions like reading past the end of a file, or dividing by zero.
You can also define your own exceptions. In Python, exceptions are
triggered automatically on errors, and they can be triggered and
intercepted by your code. Below is the list of except handling statements in
Python:

try/except : try and catch are used to try a block of code and recover from
exceptions raised by Python, or by you.
Raise: raise triggers an exception manually in your python code.
assert: assert conditionally trigger an exception in your code.
finally: finally perform cleanup actions, whether exceptions occur or not.
Raising exceptions
If a program attempts to do something erroneous, Python raises exception to such
conduct. For example:
Example 9.1
x = 10
y =0
result = x/y #trying to divide by zero
print(result)

The output is as follows:


>>>
Traceback (most recent call last):
File "D:\Python34\tt.py", line 3, in <module>
result = x/y
ZeroDivisionError: division by zero
>>>

Python raise the above error because we tried to divide by zero and we have not
tried to gracefully deal the error. In the example below we will not deal with the
error gracefully:
Example 9.2
x = 10
y =0
result =0
try:
result = x/y
print(result)
except ZeroDivisionError:
print ("You are trying to divide by zero.")
The output is as follows:
>>>
You are trying to divide by zero.
>>>

In the above program we have gracefully handled the error.


In the below example we will demonstrate how exception could propagate up the
call stack.
Example 9.3
#this example show the propagation of error up the call stack
def add(x):
return validate(x) + 1

def validate(x):
if x < 0: raise ValueError
else: return x

try:
a = int(input("Enter a Negative Number to raise the error:"))
print(add(a))
print("The result is %d" %a)
except ValueError:
print("You entered an invalid number.")

The output is as follows:


>>>
Enter a Negative Number to raise the error:10
11
The result is 10
>>>
Enter a Negative Number to raise the error:-5
You entered an invalid number.
>>>

In the above example, the print statement calls the function add(x). That function
calls the function validate(x), which will raise an exception of type ValueError.
Neither add(x) nor validate(x) has a try/except block to handle ValueError. So the
exception raised propagates out to the main code, where there is an exception-
handling block waiting for it. So when the user had entered -5 the code prints:
That value was invalid.
User-Defined Exceptions
Sometime we need to raise exception as per our specific requirement. This is
common to create custom exception class in object oriented programming. In
Python we can create our own exception class which inherit from a built-in
exception class usually the class named Exception: The below example
demonstrate it.
Example 9.4
class CustomException(Exception):
def __init__(self, value):
self.parameter = value
def __str__(self):
return repr(self.parameter)

try:
raise CustomException('This is a CustomError!')
except CustomException as ex:
print("Caught: " , ex.parameter)

The output is as follows:


>>>
Caught: This is a CustomError!
>>>

Exception classes can be defined which do anything any other class can do, but are
usually kept simple, often only offering a number of attributes that allow
information about the error to be extracted by handlers for the exception. When
creating a module that can raise several distinct errors, a common practice is to
create a base class for exceptions defined by that module, and subclass that to
create specific exception classes for different error conditions. We will learn about
classes and object in the next chapter. Here is another toy example:
Example 9.10
#User-defined exceptions
class Error(Exception):
#Base class for other exceptions
pass

class ValueTooSmall(Error):
#Raised when the input value is too small
pass

class ValueTooLarge(Error):
#Raised when the input value is too large
pass

# main program
number = 5
while True:
try:
i_num = int(input("Enter a number: "))
if i_num < number:
raise ValueTooSmall
elif i_num > number:
raise ValueTooLarge
break
except ValueTooSmall:
print("Value is too small, try again!")
print()
except ValueTooLarge:
print("Value is too large, try again!")
print()
print("You have enterred correct number.")

The output is as follows:


>>>
Enter a number: 5
You have enterred correct number.
>>>
Defining Clean-up Actions
The try statement has another optional clause “finally” which is intended to define
clean-up actions that must be executed under all circumstances. A finally clause is
always executed before leaving the try statement, whether an exception has
occurred or not. When an exception has occurred in the try clause and has not
been handled by an except clause (or it has occurred in a except or else clause), it
is re-raised after the finally clause has been executed. The finally clause is also
executed “on the way out” when any other clause of the try statement is left via a
break, continue or return statement. Let’ see an example:
Example 9.10
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("Division by zero!")

else:
print("result is", result)
finally:
print("Executing finally clause")

divide(2, 0)

The output is as follows:


>>>
Division by zero!
Executing finally clause
>>>
Chapter Summary
In this chapter we have learned about exception handling techniques. In the next
chapter we will discuss Object Oriented Programming.
Chapter 10: Object Oriented Programming
Object Oriented Programming (OOP) is an approach to program
organization and development that attempts to eliminate some of the
pitfalls of conventional programming methods by incorporating the best of
structured programming features with several powerful new concepts. It is
a new way of organizing and developing programs and has nothing to do
with any particular language. In this chapter we will learn the basics of
OOPs.
Object Oriented Paradigm
The major motivating factor in the invention of object-oriented approach is to
remove some of the flaws encountered in the procedural approach. OOP treats
data as a critical element in the program development and does not allow it to
flow freely around the system. It ties data more closely to the function that
operate on it, and protects it from accidental modification from outside function.
OOP allows decomposition of a problem into a number of entities called objects
and then builds data and function around these objects. The organization of data
and function in object-oriented programs is shown in fig.1. The data of an object
can be accessed only by the function associated with that object. However,
function of one object can access the function of other objects.

Fig. 1 – Organization of data and functions in OOP


Some of the features of object oriented programming are:
1) Emphasis is on data rather than procedure.
2) Programs are divided into what are known as objects.
3) Data structures are designed such that they characterize the objects.
4) Functions that operate on the data of an object are ties together in the data
structure.
5) Data is hidden and cannot be accessed by external function.
6) Objects may communicate with each other through function.
7) New data and functions can be easily added whenever necessary.
8) Follows bottom up approach in program design
Basic Concepts of Object Oriented Programming
It is necessary to understand some of the concepts used extensively in object-
oriented programming. These include:
1) Classes
2) Objects
3) Data abstraction and encapsulation
4) Inheritance
5) Polymorphism
6) Dynamic binding
We shall discuss these concepts in some detail below in this section.
Classes
Classes are the blue-prints / design for objects. The entire set of data and code of
an object can be made a user-defined data type with the help of class. In fact,
objects are variables of the type class. Once a class has been defined, we can
create any number of objects belonging to that class. Each object is associated
with the data of type class with which they are created. A class is thus a collection
of objects similar types. For examples, Vehicle class is a blue-print or design for the
type of various vehicle like cars, bus, trucks. Vehicles have some common
functionality like the number of wheels, gearbox, etc. We can create various
objects from the vehicle class like Ford, Benz etc. Classes are user-defined that
types and behave like the built-in types of a programming language.
Objects
Objects are the basic run time entities in an object-oriented system. They may
represent a person, a place, a bank account, a table of data or any item that the
program has to handle. They may also represent user-defined data such as vectors,
time and lists. Programming problem is analyzed in term of objects and the nature
of communication between them. Program objects should be chosen such that
they match closely with the real-world objects.
Data Abstraction and Encapsulation
The wrapping up of data and function into a single unit (called class) is known as
encapsulation. Data and encapsulation is the most striking feature of a class. The
data is not accessible to the outside world, and only those functions which are
wrapped in the class can access it. These functions provide the interface between
the object’s data and the program. This insulation of the data from direct access
by the program is called data hiding or information hiding.
Abstraction refers to the act of representing essential features without including
the background details or explanation. Classes use the concept of abstraction and
are defined as a list of abstract attributes such as size, wait, and cost, and function
operate on these attributes. They encapsulate all the essential properties of the
object that are to be created. The attributes are sometime called data members
because they hold information. The functions that operate on these data are
sometimes called methods or member function.
Inheritance
Inheritance is the process by which objects of one class acquired the properties of
objects of another classes. It supports the concept of hierarchical classification. In
the figure 2 below shows the inheritance tree of Vehicle, we can see that the
Electric class and the Petrol class is inherited from the Car class and the Car class is
inherited from the Vehicle Class and in the same way the Truck Class is inherited
from the Vehicle Class. The principal behind this sort of division is that each
derived class shares common characteristics with the class from which it is derived.
In OOP, the concept of inheritance provides the idea of reusability. This means
that we can add additional features to an existing class without modifying it. This
is possible by deriving a new class from the existing one. The new class will have
the combined feature of both the classes. The real appeal and power of the
inheritance mechanism is that it allows the programmer to reuse a class i.e.,
almost, but not exactly, what he wants, and to tailor the class in such a way that it
does not introduced any undesirable side-effects into the rest of classes.

Fig. 2 - The inheritance tree of Vehicle Class


Polymorphism
Polymorphism is another important OOP concept. Polymorphism, a Greek term,
means the ability to take more than on form. An operation may exhibit different
behavior is different instances. The behavior depends upon the types of data used
in the operation. For example, we have a base class Shape and it has a draw
method. Think that the shape class is like a window (i.e., your PC window). In
windows we have Circle, Triangle, Box and many other forms of window. The base
class Shape has a draw method which draws a Window, Circle is a derived class
and it has implemented an overridden draw method which draw a Circle and So
on. Figure 3 below illustrates that a single function name can be used to handle
different number and different types of argument. This is something similar to a
particular word having several different meanings depending upon the context.
Using a single function name to perform different type of task is known as function
overloading.

Fig. 3 Polymorphism
Dynamic Binding
Binding refers to the linking of a procedure call to the code to be executed in
response to the call. Dynamic binding means that the code associated with a given
procedure call is not known until the time of the call at run time. It is associated
with polymorphism and inheritance. A function call associated with a polymorphic
reference depends on the dynamic type of that reference. For example the draw
method of the figure 3 by inheritance, every object will have this procedure. Its
algorithm is, however, unique to each object and so the draw procedure will be
redefined in each class that defines the object. At run-time, the code matching the
object under current reference will be called.
Chapter Summary
In this chapter we have learned about Object Oriented Programming fundamental
concepts. In the next chapter we will discuss Class and Objects with lots of
example in Python.
Chapter 11: Classes and Objects
Recap – Classes = Blueprint:

a) Classes are blueprints/designs for objects.


b) Creating objects using classes: We instantiate objects. Objects are also called
instances of a class.
c) Objects of the same class have the same basic structure, but they can differ in
various respects.
Creating Classes
The class statement creates a new class definition. The name of the class
immediately follows the keyword class followed by superclass object within a
parenthesis and followed by a colon. The below code snippets is as follows:
class ClassName(object):
'Optional class documentation string'
‘constructors, destructor, member variables also known as fields and methods

Let’s now write a Python class in the below example:


Example 11.1
class Vehicle(object):
#constructor
def __init__(self, steering, wheels, clutch, breaks, gears):
self.__steering = steering
self.__wheels = wheels
self.__clutch = clutch
self.__breaks = breaks
self.__gears = gears
#destructor
def __del__(self):
print ("This is destructor....")

#member functions or methods


def Display_Vehicle(self):
print('Steering: ' , self.__steering)
print('Wheels: ', self.__wheels)
print('Clutch: ', self.__clutch)
print('Breaks: ', self.__breaks)
print('Gears: ', self.__gears)
#instantiate a vehicle object
myGenericVehicle = Vehicle('Power Steering', 4, 'Super Clutch', 'Disk Breaks', 5)
myGenericVehicle.Display_Vehicle()

The output is as follows:


('Steering: ', 'Power Steering')
('Wheels: ', 4)
('Clutch: ', 'Super Clutch')
('Breaks: ', 'Disk Breaks')
('Gears: ', 5)

This example includes class definition, constructor function, destructor function,


attributes and methods definition and object definition. These definitions and
uses will be introduced specifically in the following.
Class Definition and Object Instantiation
a) Class definition syntax:
class subclass[(superclass)]:
[attributes and methods]

b) Object instantiation syntax:


object = class()

c) Attributes and methods invoke:


object.attribute
object.method()
Special Class Attributes in Python
Except for self-defined class attributes in Python, class has some special attributes.
They are provided by object module.
Attributes Name Description
__dict__ Dict variable of class name space
__doc__ Document reference string of class
__name__ Class name
__module__ Module name consisting of class
__bases__ The tuple including all the superclasses

Example 11.2
class Cat(object):
itsWeight=0
itsAge=0
itsName=""
def Meow(self):
print("Meow!")

def DisplayCat(self):
print("I am a Cat Object, My Name is ", self.itsName)
print("My age is ", self.itsAge)
print("My weight is", self.itsWeight)

frisky = Cat()
frisky.itsAge=10
frisky.itsName="Frisky"
frisky.DisplayCat()
frisky.Meow()

The output is as follows:


('I am a Cat Object, My Name is ', 'Frisky')
('My age is ', 10)
('My weight is', 0)
Meow!
Accessing Class Members
We have defined the Cat object Frisky as shown in the example --we use the dot
operator (.) to access the members of that object. Therefore, to assign 10 to frisky's
Age member variable, you have written as frisky.itsAge=10. In the same way, to call
the DisplayCat() and Meow() function, i.e., objectName.Method().
In the above example, we have accessed the member variables of Cat class from
the object which is not a convenient way to access the member variables. Instead
we could create accessor methods to provide encapsulation or information hiding.
Let’s see the below example.
Example 11.3
class Cat(object):
itsAge=None
itsWeight=None
itsName=None
#set accessor function use to assign values to the fields or member vars
def setItsAge(self, itsAge):
self.itsAge = itsAge

def setItsWeight(self, itsWeight):


self.itsWeight = itsWeight

def setItsName(self, itsName):


self.itsName = itsName

#get accessor function use to return the values from a field


def getItsAge(self):
return self.itsAge

def getItsWeight(self):
return self.itsWeight
def getItsName(self):
return self.itsName

objFrisky = Cat()
objFrisky.setItsAge(5)
objFrisky.setItsWeight(10)
objFrisky.setItsName("Frsiky")
print("Cats Name is: ",objFrisky.getItsName())
print("Its age is :", objFrisky.getItsAge())
print("Its weight is :", objFrisky.getItsName())

The output is as follows:


('Cats Name is: ', 'Frsiky')
('Its age is :', 5)
('Its weight is :', 'Frsiky')

In the above example we have used accessor methods to set and get the member
variables. This is actually done for encapsulation or data hiding. Encapsulation is
done if the member variables are private or protected, but in Python all the
member variables are public by default. In Python, there is no keywords like
‘public’, ‘protected’ and ‘private’ to define the accessibility. In other words, In
Python, it acquiesce that all attributes are public.
Many object-oriented languages prevent access to the attributes of a class or
instance, the idea being that if the author of the class didn't define a method to
manipulate an attribute, then the user of the instance has no right to examine or
change it. As you might have already guessed, Python doesn't take this approach.
Attribute reference syntax can be used to access most instance and class
attributes, and __dict__ attributes give the entire show away. The assumption is
that you know what you're doing, and if you want to shoot yourself in the foot,
that's your affair. That said, Python does support name mangling which we will be
talking after sometime.
For those programmers / developers of C++ or Java or C# world who still want to
use the same programming techniques of making private or protected member
variable or protected member functions in Python, we are providing the below
examples. There is a way to create private or protected member variables. At the
end of both the example we will talk if it is really necessary to write code in the
same this way or to adapt Python way.
In the below example we will modify the example 11.3 and make the member
variable private.
Private member variable example
Example 11.4
class Cat(object):
# we made all member variable private by adding a __ prefix
__itsAge=None
__itsWeight=None
__itsName=None
#set accessor function use to assign values to the fields or member vars
def setItsAge(self, itsAge):
self.itsAge = itsAge

def setItsWeight(self, itsWeight):


self.itsWeight = itsWeight

def setItsName(self, itsName):


self.itsName = itsName

#get accessor function use to return the values from a field


def getItsAge(self):
return self.itsAge

def getItsWeight(self):
return self.itsWeight

def getItsName(self):
return self.itsName

objFrisky = Cat()
objFrisky.setItsAge(5)
objFrisky.setItsWeight(10)
objFrisky.setItsName("Frsiky")
print("Cats Name is: ",objFrisky.getItsName())
print("Its age is :", objFrisky.getItsAge())
print("Its weight is :", objFrisky.getItsName())
#Now let's prove if we could access the private variable
#directly from objFrisky as we did in the 2nd example
objFrisky.itsAge(100)

The output is as follows:


Traceback (most recent call last):
File "C:\Users\ABaruah\Desktop\Pyout\class1\src\Cat.py", line 34, in <module>
objFrisky.itsAge(100)
TypeError: 'int' object is not callable
('Cats Name is: ', 'Frsiky')
('Its age is :', 5)
('Its weight is :', 'Frsiky')

There was an error message popped up in the above example. Python is now
complaining that int object is not callable. Since we marked the member variable
as private we cannot access it from outside.
Protected member variable
Protected member is (in C++ and Java) accessible only from within the class and its
subclasses. How to accomplish this in Python? The answer is – by convention. By
prefixing the name of your member with a single underscore, you’re telling others
“don’t touch this, unless you’re a subclass”. We will see it in the below example.
Example 11.5
class Cat(object):
#making member variable protected by prefixing a single _
_itsAge=None
_itsWeight=None
_itsName=None
#set accessor function use to assign values to the fields or member vars
def setItsAge(self, itsAge):
self.itsAge = itsAge

def setItsWeight(self, itsWeight):


self.itsWeight = itsWeight

def setItsName(self, itsName):


self.itsName = itsName

#get accessor function use to return the values from a field


def getItsAge(self):
return self.itsAge

def getItsWeight(self):
return self.itsWeight

def getItsName(self):
return self.itsName
objFrisky = Cat()
objFrisky.setItsAge(5)
objFrisky.setItsWeight(10)
objFrisky.setItsName("Frsiky")
print("Cats Name is: ",objFrisky.getItsName())
print("Its age is :", objFrisky.getItsAge())
print("Its weight is :", objFrisky.getItsName())
#Now let's prove if we could access the private variable
#directly from objFrisky as we did in the 2nd example
objFrisky.itsAge(100)

The output is as follows:


Traceback (most recent call last):
File "C:\Users\ABaruah\Desktop\Pyout\class1\src\Cat.py", line 34, in <module>
('Cats Name is: ', 'Frsiky')
('Its age is :', 5)
('Its weight is :', 'Frsiky')
objFrisky.itsAge(100)
TypeError: 'int' object is not callable

In the above example we have mark the member variable with a _prefix which
means they are protected. And we tried to assign objFrisky.itsAge(100) we get an
error message that the object is not callable.
Okay, from the above two examples we are now confirmed that if we prefix with a
single underscore (_) or (__) underscore we could able to make to member
variables protected or private.
In the below examples we will show you how to inherit from a parent class and
then discuss how can we access the private / protected member variables.
Example 11.6
class Animal(object):
def __init__(self, _noOfLegs):
self._noOfLegs = _noOfLegs

def DisplayAnimal(self):
print("Number of Legs :", self._noOfLegs)

class Human(Animal):
def __init__(self, _noOfLegs, _sex):
Animal.__init__(self, _noOfLegs)
self._sex = _sex

def DisplayHuman(self):
self.DisplayAnimal()
print("Sex =", self._sex)

#instantiate human
objHuman = Human(2, 'M')
objHuman.DisplayHuman()
#try to set the value of the parent class member var, we can do that
#because Human class inherits all the protected member variables
objHuman._noOfLegs = 1
print("Well, I have modified the number of legs to 1, think this Human have only 1
leg!")
objHuman.DisplayHuman()

The output is as follows:


('Number of Legs :', 2)
('Sex =', 'M')
Well, I have modified the number of legs to 1, think this Human have only 1 leg!
('Number of Legs :', 1)
('Sex =', 'M')

In the above example, from objHuman which is an object of Human class accessed
and modified the protected member variable of its super class Animal.
Now let’s see another example, if we can do the same behavior with __ private
member variable inherited from a parent class as it is mentioned that a by
prefixing the name of your member with a single underscore, you’re telling others
“don’t touch this, unless you’re a subclass”. This means that even if a sub-class
cannot able to access the private member variables, they need to be protected.
Let’s see in the below example by sub-classing a parent class and try to access the
__ private member variables.
Example 11.7
class Animal(object):
def __init__(self, __noOfLegs):
self.__noOfLegs = __noOfLegs

def DisplayAnimal(self):
print("Number of Legs :", self.__noOfLegs)

class Human(Animal):
def __init__(self, __noOfLegs, __sex):
Animal.__init__(self, __noOfLegs)
self.__sex = __sex

def DisplayHuman(self):
self.DisplayAnimal()
print("Sex =", self.__sex)

#instantiate human
objHuman = Human(2, 'M')
objHuman.DisplayHuman()
#try to set the value of the parent class member var, we can do that
#because Human class inherits all the protected member variables
objHuman.__noOfLegs=1
print("Well, I have modified the number of legs to 1, think this Human have only 1
leg!")
objHuman.DisplayHuman()

The output is as follows:


('Number of Legs :', 2)
('Sex =', 'M')
Well, I have modified the number of legs to 1, think this Human have only 1 leg!
('Number of Legs :', 2)
('Sex =', 'M')

The result of the above program is exactly same as program 11.6. By using a __
private member variable we could access the parent’s private variable from the
child class. Then how does protected works in Python. Is there really a protected
concept?
Well, by looking at the result of the above example, we could say no difference.
This is just a naming convention. Actually we could use a _ single underscore or a
__ double underscore to make things private. There is no protected concept in
Python. Python takes care by name mangling. Let’s discuss about name mangling.
What is name mangling
In compiler construction, name mangling (also called name decoration) is a
technique used to solve various problems caused by the need to resolve unique
names for programming entities in many modern programming languages. It
provides a way of encoding additional information in the name of a function,
structure, class or another datatype in order to pass more semantic information
from the compilers to linkers. The need arises where the language allows different
entities to be named with the same identifier as long as they occupy a different
namespace (where a namespace is typically defined by a module, class, or explicit
namespace directive) or have different signatures (such as function overloading).
Any object code produced by compilers is usually linked with other pieces of
object code (produced by the same or another compiler) by a type of program
called a linker. The linker needs a great deal of information on each program
entity. For example, to correctly link a function it needs its name, the number of
arguments and their types, and so on.
Name mangling in Python
In Python, mangling is used for "private" class members which are designated as
such by giving them a name with two leading underscores and no more than one
trailing underscore. For example, __thing will be mangled, as will ___thing and
__thing_, but __thing__ and __thing___ will not. Python's runtime does not
restrict access to such members, the mangling only prevents name collisions if a
derived class defines a member with the same name.
On encountering name mangled attributes, Python transforms these names by a
single underscore and the name of the enclosing class. Python magically changes
the name so that references to this attribute made in the usual way will fail. For
example let us take our above example and add just one line of code at the end
and run the program:
print (dir(objHuman))

['DisplayAnimal', 'DisplayHuman', '_Animal__noOfLegs', '_Human__sex', '__class__',


'__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__noOfLegs', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Why we have mentioned about name mangling?
The main motive of mentioning name mangling here in class & object chapter is to
show the readers how Python takes care of the class attributes and name is
mangled so that the conflict do not occur and also to show the user that the
culture in Python is that names starting with underscores mean, "don't use these
unless you really know you should." You might choose to begin your "protected"
methods with underscores. But keep in mind, this is just a convention, it doesn't
change how the method can be accessed. Names beginning with underscores are
mangled, so that inheritance hierarchies can be built without fear of name
collisions. Some people use these for "private" methods, but again, it doesn't
change how the method can be accessed. The best strategy is to get used to a
model where all the code in a single process has to be written to get along.
Shall I use __ to make something private?
The answer is of course you can. But Python does not support access protection as
C++/Java/C# does. Everything is public. The motto is, "We're all adults here."
Document your classes, and insist that your collaborators read and follow the
documentation.
We hope that the readers understood these concepts by now and would adapt a
coding style which suits best. So let’s move on and see more on Classes and
Objects.
Property
A property gets and sets a value. It is just like a method, but uses simpler syntax. A
property can be assigned like a variable. This causes the setter method to be
executed. In our Cat class in the above examples we have used getter and setter
properties. The setter property assigns a value to the member variables and a
getter property returns a value from the member variables.

#set accessor function use to assign values to the fields or member vars
def setItsAge(self, itsAge):
self.itsAge = itsAge

def setItsWeight(self, itsWeight):


self.itsWeight = itsWeight

def setItsName(self, itsName):


self.itsName = itsName

#get accessor function use to return the values from a field


def getItsAge(self):
return self.itsAge

def getItsWeight(self):
return self.itsWeight
Static vs. Instance Member Variable
A member variable declared inside a class can be shared as a class member
variable and instance variable. Let’s see the example below example:
Example 11.8
class Animal(object):
def __init__(self, __noOfLegs):
self.__noOfLegs = __noOfLegs

def DisplayAnimal(self):
print("Number of Legs :", self.__noOfLegs)

class Human(Animal):

def __init__(self, __noOfLegs, __sex):


Animal.__init__(self, __noOfLegs)
self.__sex = __sex

def DisplayHuman(self):
self.DisplayAnimal()
print("Sex =", self.__sex)
#member variables – which will be shared by the class as well as the object.
Static variable
counter=0

#instantiate human
objHuman = Human(2, 'M')
objHuman.DisplayHuman()
Human.counter +=1
print("Class variable counter is accessed from the Human Class: ", Human.counter)
objAnotherHuman =Human(2,'F')
objAnotherHuman.counter +=1
print("Class variable counter is accessed from the Object of that class: ",
objAnotherHuman.counter)

The output is as follows:


('Number of Legs :', 2)
('Sex =', 'M')
('Class variable counter is accessed from the Human Class: ', 1)
('Class variable counter is accessed from the Object of that class: ', 2)

This example shares the counter class member variable both from the class as well
as from the object of that class.
Static vs. Instance Method
Static methods can be called without creating an object of class using its class
names. A static method accepts no self instance. Instance method requires an
object of its class to be created before it can be called while static method doesn't
require object creation. Most methods in a class accept a first argument with name
"self." With the @staticmethod decorator, though, we omit this argument. Let’s
see an example below:
Example 11.9
class OnlineStore(object):
#shared member variable
> def __init__(self, __custId, __custName):
self.__custId = __custId
self.__custName = __custName

#static method
@staticmethod
def UpdateOnlineCustomers():
OnlineStore.onlineCustomer +=1

@staticmethod
def DisplayTotalCustomersOnline():
print("Total number of customer online :",OnlineStore.onlineCustomer)

#instance method
def DisplayCustomerDetail(self):
print("Customer Id : ", self.__custId )
print("Customer Name :", self.__custName )

#instantiate object
obj1 = OnlineStore(100, "Mainu")
#call the static method to increment the no. of online customers
OnlineStore.UpdateOnlineCustomers()
#call the instance method
obj1.DisplayCustomerDetail()
# call the static method to display number of customers online
OnlineStore.DisplayTotalCustomersOnline()

#create another instance and repeat the above METHODS


obj1 = OnlineStore(150, "Shainu")
#call the static method to increment the no. of online customers
OnlineStore.UpdateOnlineCustomers()
#call the instance method
obj1.DisplayCustomerDetail()
# call the static method to display number of customers online
OnlineStore.DisplayTotalCustomersOnline()

The output is as follows:


('Customer Id : ', 100)
('Customer Name :', 'Mainu')
('Total number of customer online :', 1)
('Customer Id : ', 150)
('Customer Name :', 'Shainu')
('Total number of customer online :', 2)
Id method
Every object has an id. This is unique to the instance. Its exact number is an
implementation detail and will vary between program executions. Here we look at
class id# looks in the below example:
class OnlineStore(object):
def __init__(self, __custId, __custName):
self.__custId = __custId
self.__custName = __custName

#now instantiate objects


obj1 = OnlineStore(100,"Mainu")
obj2 = OnlineStore(150,"Shainu")
print("The id of obj1 is",id(obj1))
print("The id of obj2 is", id(obj2))

The output is as follows:


('The id of obj1 is', 36826472L)
('The id of obj2 is', 36874504L)

The id# may vary from computer to computer.


Chapter Summary
In this chapter we have learned about Recap – Classes = Blueprint, Creating
Classes, Class Definition and Object Instantiation, Special Class Attributes in
Python, Accessing Class Members, Private member variable example, Protected
member variable, What is name mangling, Name mangling in Python, Why we have
mentioned about name mangling?, Shall I use __ to make something private?,
Property, Static vs. Instance Member Variable, Static vs. Instance Method, Id
method. In the next chapter we will discuss Inheritance and Polymorphism in
details.
Chapter 12: Inheritance
Inheritance
Inheritance is one of the key feature of object-oriented programming including
Python which allows user to create a new class (derived class) from an existing
class (base class). The derived class inherits all feature from a base class and it can
have additional features of its own. We have already seen some examples in the
previous chapter. In this chapter we will see more program.
Example 12.1
#Example - of inheritance
#base class
class Student(object):
def __init__(self, name, rollno):
self.name =name
self.rollno = rollno

#Graduate class inherits or derived from Student class


class GraduateStudent(Student):
def __init__(self, name, rollno, graduate):
Student.__init__(self, name, rollno)
self.graduate = graduate

def DisplayGraduateStudent(self):
print("Student Name :", self.name)
print("Student Rollno :", self.rollno)
print("Study Group :", self.graduate)

#Post Graduate class inherits from Student class


class PostGraduate(Student):
def __init__(self, name, rollno, postgrad):
Student.__init__(self, name, rollno)
self.postgrad = postgrad
def DisplayPostGraduateStudent(self):
print("Student Name :", self.name)
print("Student Rollno :", self.rollno)
print("Study Group :", self.postgrad)

#instantiate from Graduate and PostGraduate classes


objGradStudent = GraduateStudent("Mainu", 1, "MS-Mathematics")
objGradStudent.DisplayGraduateStudent()
objPostGradStudent = PostGraduate("Shainu", 2, "MS-CS")
objPostGradStudent.DisplayPostGraduateStudent()

The output is as follows:


('Student Name :', 'Mainu')
('Student Rollno :', 1)
('Study Group :', 'MSC-Mathematics')
('Student Name :', 'Shainu')
('Student Rollno :', 2)
('Study Group :', 'MSC-CS')

In the above example we have shown a very simple inheritance example, where
there is a base class “Student” which have two member variable – name and
rollno. The “GraduateStudent” class derived from the base class “Student” class
and inherits all the member variables and functions from the base class and add a
new feature i.e., another member variable “graduate” and a member function. In
the same way the “PostGraduate” class does. Nothing new up to this step. We
have seen similar example in the previous chapter.
Overriding Base-Class Members in a Derived Class
Overriding is the ability of a class to change the implementation of a method
provided by one of its ancestors or the base class. Basic meaning of overriding in
object oriented programming is the phenomenon of replacing the same parental
behavior in child class. In OOP meaning of overriding is to replace parent class
method or modify or add extra features in child class. Overriding is a very
important part of OOP since it is the feature that makes inheritance exploit its full
power. Through method overriding, a class may "copy" another class, avoiding
duplicated code, and at the same time enhance or customize part of it. Method
overriding is thus an important part of the inheritance mechanism. Let’s see some
examples below:
Example 12.2
#method overriding example
#base class MyWindow
class MyWindow(object):
def __init__(self):
pass
def displayWindow(self):
print("I am myWindow object")

class MyCircle(MyWindow):
def __init__(self):
MyWindow.__init__(self)
pass
#overriding the base class implementation
def displayWindow(self):
print("I am myCircle object")

objMyWindow = MyWindow()
objMyWindow.displayWindow()
print("-" * 30)
objMyCircle = MyCircle()
objMyCircle.displayWindow()

The output of is as follows:


I am myWindow object
------------------------------
I am myCircle object

In Python, when a subclass contains a method that overrides a method of the


superclass, you can also call the superclass method by calling super(Subclass,
self).method instead of self.method. Let’s see in the below example:
Example 12.3
#method overriding example
#base class MyWindow
class MyWindow(object):
def __init__(self):
pass
def displayWindow(self):
print("I am myWindow object")

class MyCircle(MyWindow):
def __init__(self):
super(MyCircle, self).__init__()
pass
#overriding the base class implementation
def displayWindow(self):
print("I am myCircle object")
super(MyCircle, self).displayWindow()

objMyWindow = MyWindow()
objMyWindow.displayWindow()
print("-" * 30)
objMyCircle = MyCircle()
objMyCircle.displayWindow()
The output is as follows:
I am myWindow object
------------------------------
I am myCircle object
I am myWindow object

Now if we compare the output, we can see that on calling


“objMyCircle.displayWindow()” method, it has printed both the statements “I am
myCircle object” and “I am myWindow object”
There is also another method exist to output the same behavior. Let’s see that in
the below example:
Example 12.4
#method overriding example
#base class MyWindow
class MyWindow(object):
def __init__(self):
pass
def displayWindow(self):
print("I am myWindow object")

class MyCircle(MyWindow):
def __init__(self):
MyWindow.__init__(self)
pass

def displayWindow(self):
MyWindow.displayWindow(self)
print("I am myCircle")

objMyWindow = MyWindow()
objMyWindow.displayWindow()
print("-" * 30)
objMyCircle = MyCircle()
objMyCircle.displayWindow()

The output is as follows:


I am myWindow object
------------------------------
I am myWindow object
I am myCircle

If we compare the above three examples, we can see that the last two are
identical, but the order of display is altered. We can use any of the last two
examples 12.3 or 12.4 methods if we want to keep the base class implementation
and add new content on the top of it as we did. In case we want a complete new
implementation we can write the code as we did in the example 12.2.
Overloading
Overloading refers to the ability to use a single identifier to define multiple
methods of a class that differ in their input and output parameters. Overloaded
methods are generally used when they conceptually execute the same task but
with a slightly different set of parameters. Overloading is when you define two or
more functions with same name and different signatures i.e., number of
parameters.
In Python, we generally don't need to overload functions because Python is
dynamically typed, and supports optional arguments to functions. For example:
def myfunction(empno, name, phone = None):
if phone is None:
#just use empno and name
else:
#use all three

myfunction(101, ‘Arun’) # phone will be None, so enter the 'if' clause


myfunction(101, ‘Arun’, 96587577) # third isn't None, so enter the 'else' clause

I will discuss the Pythonic way of writing function latter at this chapter, but let’s
discuss the other OOP language’s style of overloading function using the
overloading.py module, which could be downloaded from the link -
https://github.com/bintoro/overloading.py
We need to install this module, to do that first we need to unzip it and from the
command prompt or command shell type the following code:
a) $ Python overloading.py install in Windows / Linux
b) pip install overloading (In Linux). If pip is installed in windows then you can
also try this command.
After that you need to import the module - from overloading import *
Let’s see some examples in the below section:
Example 12.5
#method overloading example
from overloading import *
class EmpRecord(object):
def __init__(self):
pass

@overloaded #please note the spelling here


def displayEmpDetails(self, empno, name):
print(empno, name)

@overloads(displayEmpDetails) #please note the spelling here


def displayEmpDetails(self, empno, name, phone):
print(empno, name, phone)
empObj = EmpRecord()
empObj.displayEmpDetails(101, 'Mainu')
empObj.displayEmpDetails(150, 'Shainu', '878787878')

The output is as follows:


101 Mainu
150 Shainu 878787878

As per the imported module – we have to use @overloaded at first to denote that
this method will be overloaded. In the second or subsequence definitions, we have
to use @overloads(displayEmpDetails) i.e., the method’s name which we are going
to overload and after that we write the overloaded method.
There are two or more libraries available freely in the web, and their syntax might
be different then the above one.
Pythonic ways of writing function
Actually method overloading itself is a non-Pythonic concept. Generally we don't
need to overload functions in Python. Python is dynamically typed, and supports
optional arguments to functions. Let’s see the example below:
Example 12.6
#method overloading pythonic way example. We can use this type for Python
version 2.x
# to 3.3. In 3.4 we have singledispatch decorator to functools, we will see so on
class EmpRecord(object):
def __init__(self):
pass

def displayEmpDetails(self, empno, name, phone=None):


if phone is None:
print(empno, name)
else:
print(empno, name, phone)
empObj = EmpRecord()
empObj.displayEmpDetails(101, 'Mainu')
empObj.displayEmpDetails(150, 'Shainu', '878787878')

The output is as follows:


101 Mainu
150 Shainu 878787878
Method Overloading in Python 3.4
Python 3.4 added a “singledispatch” decorator to functools, which provides
method overloads. This enables you to perform different operations based on the
type of the first argument.
A generic function is composed of multiple functions implementing the same
operation for different types. Which implementation should be used during a call
is determined by the dispatch algorithm. When the implementation is chosen
based on the type of a single argument, this is known as single dispatch.
To define a generic function, decorate it with the @singledispatch decorator. Note
that the dispatch happens on the type of the first argument.
By default, it prefers to work with static methods. Let’s see an example below:
Example 12.7
import functools
class TestClass(object):
@functools.singledispatch
def displayArgs(arg):
print("Let me just say,", end=" ")
print(arg)

@displayArgs.register(int)
def _(arg):
print("Strength in numbers, eh?", end=" ")
print(arg)

@displayArgs.register(list)
def _(arg):
print("Enumerate this:")

for i, elem in enumerate(arg):


print(i, elem)
if __name__ == '__main__':
TestClass.displayArgs(55555)
TestClass.displayArgs([33, 22, 11])

The output is as follows:


Strength in numbers, eh? 55555In [62]:
Enumerate this:
0 33
1 22
2 11

However, to get overloading on instance-methods, we’ll just place our own


wrapper around the standard singledispatch wrapper. Let’s see in the example
below:
Example 12.8
import functools

def instancemethod_dispatch(func):
dispatcher = functools.singledispatch(func)
def wrapper(*args, **kw):
return dispatcher.dispatch(args[1].__class__)(*args, **kw)
wrapper.register = dispatcher.register
functools.update_wrapper(wrapper, func)
return wrapper

class TestClass2(object):
@instancemethod_dispatch
def displayArgs(self, arg):
print("2: Let me just say,", end=" ")
print(arg)

@displayArgs.register(int)
def _(self, arg):
print("2: Strength in numbers, eh?", end=" ")
print(arg)

@displayArgs.register(list)
def _(self, arg):
print("2: Enumerate this:")

for i, elem in enumerate(arg):


print(i, elem)

if __name__ == '__main__':
obj1 = TestClass2()
obj1.displayArgs(55555)
obj1.displayArgs([33, 22, 11])

The output is as follows:


2: Strength in numbers, eh? 55555
2: Enumerate this:
0 33
1 22
2 11
Operator Overloading
Operator overloading means giving more than one meaning to the standard
operators, applying to objects constructed from programmer-defined classes.
Python provides us many operators like +, -, *, / etc. We can use these operators
for addition, subtraction, multiplication, division etc. List of operators are given in
the chapter 3. For now we will consider one of these to demonstrate how we can
overload operators.
Fox example, we could add : z = x + y and we get the results. What if we try to add
a rational number (p/q where q is not equal to zero)?
If we try like this we will not get the results as expected: 2/3 + 3/4. For that we
need to overload the operator. Let’s see the below example:
Example 12.9

class RationalNumber(object):
def __init__(self, numerator=0, demoniator=1):
self.numerator = numerator
self.demoniator = demoniator
self.reduce()

def __add__(self,rhs):
n1 = self.numerator
d1 = self.demoniator
n2 = rhs.numerator
d2 = rhs.demoniator
r = RationalNumber(d2*n1+d1*n2,d1*d2)
return r

def gcd(self,a,b):
if b == 0:
return a
return self.gcd(b,a%b)
def reduce(self): #reduce the fraction
d=1
if self.demoniator != 0 and self.numerator !=0:
d = self.gcd(self.numerator, self.demoniator)
if d > 1: #reduce away!
self.numerator /= d
self.demoniator /= d

def __str__(self):
s = "%d /% d" % (self.numerator,self.demoniator)
return s

#class is ready now test


x = RationalNumber(4,9)
y = RationalNumber(1,3)
print("The rational number x =", x)
print("The rational number y =", y)
print("The sum of the rational numbers x + y =", x + y )

The output is as follows:


The rational number x = 4 / 9
The rational number y = 1 / 3
The sum of the rational numbers x + y = 7 / 9

Like this we can overload other operators for special purpose.


Multiple inheritance
Multiple inheritance on the other hand is a feature in which a class can inherit
attributes and methods from more than one parent class. Suppose ClassC derives
from ClassB and ClassB derives from ClassA. But one most important thing to
remember is that circular inheritance is not possible.
Let’s see an example of multiple inheritance below:
Example 12.10
class Truck(object):
def __init__(self, name):
self.name = name
def has_strings(self):
return True
class Car(object):
def displaySpeciality(self):
print ('I am a {0}'.format(self.__class__.__name__))
class HybridCar(Truck, Car):
def has_strings(self):
return False
objHybridCar = HybridCar('Hybrid Car having 8 wheels!')
objHybridCar.displaySpeciality()

The output is as follows:


I am a HybridCar
Chapter Summary
In this chapter we have learned about inheritance, overriding base class members
in derived class, overloading, Pythonic ways of writing functions, method
overloading in Python 3.4, operator overloading and multiple inheritance. In the
next chapter we will discuss Modules and Packages.
Chapter 13: Modules and Packages
Modules
Python modules are the highest-level program organization unit that provides self-
contained namespaces. A module is a file containing Python definitions and
statements. The file name is the module name with the suffix .py appended. In
other words modules are indeed Python files. While coding professional program,
we save our classes into many files with .py extensions in a project. We also use
third-party programs as module. We have already seen many programs with
import statement in our previous programs. Now let’s see some examples below:
Example 13.1 In this example, we will create three files – vehicle.py, car.py and a
main.py file where we will use those classes.
We are using “C:\Users\ABaruah\Desktop\Pyout\Examples” folder for this program
#base class Vehicle vehicle.py
class Vehicle(object):
pass
def displayVehicleType(self):
print("This is Base Class Vehicle")

#derived class car


Import vehicle
class Car(vehicle.Vehicle):
pass
def displayVehicleType(self):
print("This is Car")

#import Car to use in main. We need not import the Vehicle because
#it was imported in the Car module
import car
objCar = Car()
objCar.displayVehicleType()
The output is as follows:
This is Car

In this example the modules are in the same directory as main.py, or is a default
module that comes with python. We leave out the '.py' at the end of the file - it is
ignored. We normally put all import statements at the beginning of the python
file, but technically they can be anywhere.
While accessing the module we used <namespace:class> i.e., class
Car(vehicle.Vehicle).
We can also import a particular method or function from a module if we intend to
use only that method of the module. This is very helpful when the module
contains many methods and we only need some or one of the methods. Let’s see
the below example.
Example 13.2
#base class Vehicle
class Vehicle(object):
pass
def displayVehicleType(self):
print("This is Base Class Vehicle")
#emulating many many functions
def Gear(self):
pass
def Clutch(self):
pass
def Steering(self):
pass

#only import the function that you intend to use


from vehicle import Vehicle
class Car(Vehicle):
pass
def displayVehicleType(self):
print("This is Car")

import car
objCar = Car()
objCar.displayVehicleType()

The output is as follows:


This is Car

If we want to import all then we will use from vehicle import * . Let’s see the
below example. 
Example 13.3
#base class Vehicle
class Vehicle(object):
pass
def displayVehicleType(self):
print("This is Base Class Vehicle")

#only import the function that you inttend to use


from vehicle import Vehicl
class Car(Vehicle):
pass
def displayVehicleType(self):
print("This is Car")
#suppose added these function here in car
def Gear(self):
print("Testing Gear function!")
def Clutch(self):
print("Testing Clutch function!")
def Steering(self):
print("Testing Steering function!")

from car import *


objCar = Car()
objCar.displayVehicleType()
objCar.Gear()
objCar.Clutch()
objCar.Steering()

The output is as follows:


This is Car
Testing Gear function!
Testing Clutch function!
Testing Steering function!
More on Modules
A module can contain executable statements as well as function definitions. These
statements are intended to initialize the module. They are executed only the first
time the module name is encountered in an import statement. They are also run if
the file is executed as a script.
Each module has its own private symbol table, which is used as the global symbol
table by all functions defined in the module. Thus, the author of a module can use
global variables in the module without worrying about accidental clashes with a
user’s global variables. On the other hand, if you know what you are doing you can
touch a module’s global variables with the same notation used to refer to its
functions, modname.itemname.
Modules can import other modules. The imported module names are placed in the
importing module’s global symbol table.
Executing modules as scripts
Many times we need to run Python script from the command prompt. Let’s now
try to run the below example.
Example 13.4
#main.py
from car import *
objCar = Car()
objCar.displayVehicleType()
objCar.Gear()
objCar.Clutch()
objCar.Steering()

The output is as follows:


C:\Users\ABaruah\Desktop\Pyout\Examples>python main.py
File "main.py", line 2
from car import *
^
IndentationError: unexpected indent
C:\Users\ABaruah\Desktop\Pyout\Examples>

In order to run Python script from the command prompt as script we need to
modify and add __name__ and set to “__main__”. The code module will execute
just as if you imported it. Let’s see the below example.
Example 13.5
if __name__ == "__main__":
from car import *
objCar = Car()
objCar.displayVehicleType()
objCar.Gear()
objCar.Clutch()
objCar.Steering()

The output is as follows when we execute the above program from the command
shell as script.
C:\Users\ABaruah\Desktop\Pyout\Examples>python main.py
This is Car
Testing Gear function!
Testing Clutch function!
Testing Steering function!
C:\Users\ABaruah\Desktop\Pyout\Examples>
Compiled Python files
As an important speed-up of the start-up time for short programs that use a lot of
standard modules, if a file called car.cpython-34.pyc exists in the __pycache__ ,
this is assumed to contain an already-“byte-compiled” version of the module
car.py. The modification time of the version of car.cpython-34.pyc used to create
car.cpython-34.pyc is recorded in car.cpython-34.pyc, and the .pyc file is ignored if
these don’t match. In our case we have the compiled code in __pycache__
directory as shown below:
C:\Users\ABaruah\Desktop\Pyout\Examples\__pycache__>dir
Volume in drive C has no label.
Volume Serial Number is 0AA4-887D
Directory of C:\Users\ABaruah\Desktop\Pyout\Examples\__pycache__
06/20/2015 10:17 PM <DIR> .
06/20/2015 10:17 PM <DIR> ..
06/20/2015 10:17 PM 1,075 car.cpython-34.pyc
06/20/2015 10:00 PM 477 vehicle.cpython-34.pyc
2 File(s) 1,552 bytes
2 Dir(s) 13,191,704,576 bytes free
C:\Users\ABaruah\Desktop\Pyout\Examples\__pycache__>

Normally, we don’t need to do anything to create the car.cpython-34.pyc file.


Whenever car.cpython-34.pyc is successfully compiled, an attempt is made to write
the compiled version to car.cpython-34.pyc. It is not an error if this attempt fails; if
for any reason the file is not written completely, the resulting car.cpython-34.pyc
file will be recognized as invalid and thus ignored later. The contents of the
car.cpython-34.pyc file are platform independent, so a Python module directory
can be shared by machines of different architectures.
The dir() Function
The built-in function dir() is used to find out which names a module defines. It
returns a sorted list of strings.
For example let’s see car object:
import
dir(car)
Out[192]:
['Car',
'Vehicle',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__']
Packages
So far, we have imported modules. In addition to a module name, an import can
name a directory path. A directory of Python code is said to be a package. In effect,
a package import turns a directory on your computer into another Python
namespace, with attributes corresponding to the subdirectories and module files
that the directory contains.
Packages are a way of structuring Python’s module namespace by using “dotted
module names”. For example, the module name A.B designates a submodule
named B in a package named A. Just like the use of modules saves the authors of
different modules from having to worry about each other’s global variable names,
the use of dotted module names saves the authors of multi-module packages like
NumPy or the Python Imaging Library from having to worry about each other’s
module names.
Suppose we want to design a collection of modules (a “package”) for the uniform
handling of a Company information. There are many different information relating
to different department like HR, Operations, IT, so you may need to create and
maintain a growing collection of modules for respected departments. Here’s a
possible structure for your package:
officemanagement/ Top-level package
__init__.py Initialize the OfficeManagement package
HR/ Subpackage for HR related information management
__init__.py
employeeDetails.py
employeeAttendance.py
employeeLeave.py
employeeExitManagement.py

operations/ Subpackage for operation management
__init__.py
operations.py
rawMaterialMgnt.py
wasteMgnt.py
...
it/ Subpackage for IT department
__init__.py
itLicenseMgnt.py
itActiveMachineInfo.py
itSystemUpdate.py
...

When importing the package, Python searches through the directories on sys.path
looking for the package subdirectory.
The __init__.py files are required to make Python treat the directories as
containing packages; this is done to prevent directories with a common name,
such as string, from unintentionally hiding valid modules that occur later on the
module search path. In the simplest case, __init__.py can just be an empty file, but
it can also execute initialization code for the package or set the __all__ variable.
Users of the package can import individual modules from the package, for
example:
import officemanagement.operations.rawMaterialMgnt
Chapter Summary

In this chapter we have learned about modules and packages. This chapter
concludes the book. Hope you would have enjoyed learning Python with this book.

You might also like