Arun Teaches Python A Step by Step Guide
Arun Teaches Python A Step by Step Guide
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
Acknowledgments
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
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:
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:
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
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
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
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)
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)
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 ‘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!")
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")
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)
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 .....')
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")
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)()
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 –
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 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 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))
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!"
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")
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
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
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)
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)
#list of numbers
numbers =[1,2,3,4,5,6,7,8,9,10]
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]
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]
Example 6.10
#!/usr/bin/python3
from functools import reduce
result = reduce( (lambda x, y: x + y), [1, 2, 3, 4] )
print(result)
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)
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)
Equivalent to:
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()
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()
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()
with open("hello.dat",'rb') as f:
data = f.read()
text = data.decode('utf-8')
print(text)
>>>
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)
Hello world
This is a demo using with
>>>
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
>>>
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)
Hello world
This is a demo using with
This file contains three lines
Hello world
This is a demo using with
>>>
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 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
#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))
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
>>>
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
>>>
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)
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)
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 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))
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)
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.
>>>
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.")
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)
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.")
else:
print("result is", result)
finally:
print("Executing finally clause")
divide(2, 0)
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:
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()
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())
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 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)
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 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)
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()
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 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))
#set accessor function use to assign values to the fields or member vars
def setItsAge(self, itsAge):
self.itsAge = 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 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)
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
onlineCustomer = 0
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()
def DisplayGraduateStudent(self):
print("Student Name :", self.name)
print("Student Rollno :", self.rollno)
print("Study Group :", self.graduate)
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()
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
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()
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
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
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
@displayArgs.register(int)
def _(arg):
print("Strength in numbers, eh?", end=" ")
print(arg)
@displayArgs.register(list)
def _(arg):
print("Enumerate this:")
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:")
if __name__ == '__main__':
obj1 = TestClass2()
obj1.displayArgs(55555)
obj1.displayArgs([33, 22, 11])
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
#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
import car
objCar = Car()
objCar.displayVehicleType()
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")
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__>
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.