Introduction To Python by Rachna Verma
Introduction To Python by Rachna Verma
Introduction to Python
Rachna Verma
Professor of Master of Computer Application,
Faculty of Engineering and Architecure,
JNV University, Jodhpur, Rajasthan, India
ii
Introduction to Python
Copyright © 2024 Dr. Rachna Verma and Dr. Arvind Kumar Verma
ISBN:
First published in India by Dr. Rachna Verma and Dr. Arvind Kumar Verma
All rights reserved. No part of this publication may be reproduced or distributed
in any form or by any means, or stored in a data base or retrieval system, without
the prior written permission of the authors.
Cover (illustration) by Dr. Rachna Verma
Set by Dr. Rachna Verma
Published by https://kdp.amazon.com
iii
Introduction to Python
Table of contents
Preface xiii
1. Introduction to Computing 1
1.1 Components of a Computer 1
1.1.1 Input Devices 2
1.1.2 Output Devices 2
1.1.3 Central Processing Unit 2
1.1.4 Memory 4
1.2 Computer Software 4
1.2.1 Types of System Software 5
1.3 Programming Languages 7
1.3.1 Types of Computer Programming Languages 9
1.4 Algorithms and Flowcharts 12
1.4.1 Guidelines to Write Algorithms 13
1.4.2 Examples of Some Algorithms 14
1.4.3 Pseudocode 17
1.4.4 Flowchart 18
1.4.5 Examples of Flowcharts 19
1.4.6 Python Programs 25
2 Overview of Python 33
2.1 History of Python 33
2.2 Why Python? 34
2.3 Installing Python 35
2.4 Starting Python In Windows 39
2.4.1 Python Command Prompt 39
iv
2.4.2 Python IDLE 41
2.5 Structuring Python Programs 44
2.5.1 Python Statements 44
2.5.2 Line Continuation 45
2.5.3 Comments in Python 46
2.5.4 Proper Indentation 48
2.6 Structure of a Python Program 49
2.7 Coding Style 51
2.8 Identifier Naming Convention 52
2.9 Python Implementations 53
2.10 Python IDEs 54
2.11 Python Distributions 55
3 Basics of Python Programming 61
3.1 Character Set 61
3.2 Python Token 63
3.3 Keywords 63
3.4 Identifiers 66
3.4.1 Rules for Naming Identifiers 67
3.5 Literals and Datatypes 68
3.5.1 String Literals 68
3.5.2 Numeric Literals 75
3.5.2.1 Integer Literals 75
3.5.2.2 Floating-Point Literals 77
3.5.2.3 Complex Number Literals 78
3.5.3 Boolean Literals 79
3.5.4 Collection Literals 80
3.5.4.1 List Literals 80
3.5.4.2 Tuple Literals 81
3.5.4.3 Dictionary Literals 82
3.5.4.4 Set Literals 84
v
3.5.5 Special Literal None 85
3.6 Variables 86
3.7 Operators 87
3.8 Delimiters 88
3.9 Input and Output Functions 90
3.9.1 The Input Function 90
3.9.2 Reading Single Numeric Data 92
3.9.3 Reading Multiple Numeric Data Separated with a Delimiter 95
3.9.4 The Eval Function 97
3.9.5 The Print Function 100
3.10 Formatting Numbers and Strings 102
3.10.1 The Traditional % Formatting Operator 102
3.10.2 The Format Function 106
3.10.3 Formatting with the Format Method of the Str Object 109
3.10.4 F-String in Python 112
4 Operators and Expressions 123
4.1 Operators 123
4.1.1 Arithmetic Operators 123
4.1.2 Relational (Comparison) Operators 129
4.1.3 Logical Operators 130
4.1.4 Bitwise Operators 133
4.1.5 Assignment Operators 135
4.1.6 Membership Operators 139
4.1.7 Identity Operators 141
4.2 Expressions 143
4.2.1 Arithmetic Expressions 143
4.2.2 Logical Expressions 145
4.2.3 String Expressions 146
4.3 Operator Precedence and Associativity 147
4.4 Statements vs Expressions 150
vi
4.5 Python Built-in functions 150
4.6 Importing Mathematic Functions 167
5 Decision Making and Branching 189
5.1 if Statement 189
5.2 if-else Statement 193
5.3 Nested if Statement 195
5.4 Ladder if (if-elif-else) Statement 198
5.5 Ternary Operator 203
5.6 pass Statement 206
6 Loop Control Statements 219
6.1 while Loop 220
6.2 for Loop 224
6.3 break Statement 226
6.4 continue Statement 229
6.5 else Statement 233
6.6 Nested Loops 236
6.7 quit () and exit () Functions 236
7 User-Defined Functions 261
7.1 Introduction 261
7.2 Defining a User-defined Function 265
7.3 Parameters and Arguments in a Function 267
7.3.1 Positional Parameters 268
7.3.2 Parameters with Default Values 268
7.3.3 Keyword Arguments 269
7.3.4 Variable Number of Parameters 271
7.4 Calling a Function 273
7.5 Local and Global Functions 276
7.6 Scope and Life of a Aariable 277
7.6.1 Local Variables 277
7.6.2 Global Variables 278
vii
7.7 Passing Arguments to a Function 281
7.8 Return Values from Functions 285
7.8.1 Returning Multiple Values from a Function 286
7.9 Passing and Returning Function Objects to a Function 288
7.10 Recursive Functions 289
7.11 Lambda Function 290
7.12 Generator Functions 291
7.13 Command Line Arguments 293
8 Lists 315
8.1 List Creation 315
8.1.1 Lists from Data 315
8.1.2 Converting Other Data Types to Lists 316
8.1.3 List Comprehension to Create a New List 318
8.1.4 Split a String into a List of Words 321
8.2 Accessing an Element of a List 321
8.2.1 List Traversal 323
8.3 List Slicing 324
8.3.1 Traversing Sliced List 326
8.4 Commonly Used Built-in Function for Lists 327
8.4.1 The max() and min () Functions for a List of Lists or Iterables 330
8.4.2 The max () and min () Functions with a List of Complex 332
numbers
8.5 Creating Copies of a List 332
8.5.1 Reference Copy 334
8.5.2 Shallow Copy 336
8.5.3 Deep Copy 338
8.6 Methods of the list Class 338
8.7 Random Reshuffle of the Elements of a List 341
8.8 Using a List as a Matrix and an Array 343
8.8.1 Creating a Matrix from Data 343
viii
8.8.2 Creating an Array from data 345
8.8.3 Reading a Matrix from the Keyboard 349
8.8.4 Nested List Comprehension to Process Matrices 351
8.9 List Operators 353
9 Strings 377
9.1 Creating String Objects 377
9.1.1 Assigning a String Literal to a Variable 377
9.1.2 Using the Construction of the string Class 378
9.2 Built-in Functions for Strings 379
9.3 Accessing Characters in a String 379
9.4 Traversing a String 380
9.5 Slicing Operation with a String 381
9.6 String Operators 383
9.7 String Class Methods 383
10 Tuples, Sets and Dictionaries 403
10.1 Tuple 403
10.2 Create Tuples 404
10.2.1 From Data 404
10.2.2 From Other Iterables 404
10.2.3 Using Comprehension 405
10.3 Built-in Functions for Tuples 407
10.4 Indexing of Tuple Elements 409
10.5 Slicing of Tuples 410
10.6 Operations on Tuples 410
10.7 Traversing Tuples 411
10.8 Sorting a Tuple 413
10.9 Zipping Tuples Together 413
10.10 Tuple Methods 414
10.11 Lists and Other Mutable Sequences as Elements of Tuples 415
10.12 Tuple vs List 416
ix
10.13 Sets 417
10.14 Creating Sets 417
10.15 Built-in Functions for Sets 419
10.16 Membership Operators: in and not in 420
10.17 Set Methods 420
10.18 Traversing Sets 424
10.19 Frozenset 425
10.20 Dictionaries 426
10.21 Creating Dictionaries 426
10.22 Accessing a Dictionary Element 430
10.23 Nested Dictionary 430
10.24 Removing an Element from a Dictionary 431
10.25 Traversing a Dictionary 431
10.26 Built-in Functions for Dictionaries 432
10.27 Methods of the dict Class 433
11 File Handling 453
11.1 Types of Files 453
11.2 Steps in File Handling 454
11.3 Opening a File 455
11.4 Reading from a Text File 462
11.5 Writing into a Text File 465
11.6 Writing Numbers and Booleans in a File 467
11.7 Reading Numbers from a File 468
11.8 Seek and Tell Methods 469
11.9 Iterating Over Lines in a File 471
11.10 Accessing Binary Files 471
11.11 Serialization in Python 476
11.11.1 The pickle Module 477
11.11.2 The json Module 478
11.12 CSV Files 485
x
11.13 File and Directory Management 488
12 Object Oriented Programming in Python 513
12.1 Basic concepts of Object-Oriented Programming 514
12.1.1 Objects and Classes 514
12.1.2 Data Encapsulation 515
12.1.3 Inheritance 515
12.1.4 Polymorphism 518
12.1.5 Dynamic Binding 519
12.1.6 Message Passing 519
12.2 Define a Class in Python 520
12.3 Constructors and Destructor 524
12.4 Encapsulation in Python 528
12.5 Instance Methods 531
12.6 Name Mangling 533
12.7 Display Class Attributes and Instance Methods 534
12.8 Inheritance in Python 536
12.9 Types of Inheritance in Python 540
12.10 The object Class 543
12.11 Method Resolution Order in Python 544
12.12 Type and Class Membership Tests 548
12.13 Polymorphism in Python 550
12.14 Method Overloading 550
12.15 Operator Overloading 552
12.16 Overloading Built-in Python Functions 557
12.17 Decorator Classes 558
13 Exception Handling in Python 576
13.1 Python Built-in Exceptions 578
13.2 Handling a General Exception 581
13.3 Catching Specific Exceptions 582
13.4 Raising Exceptions 589
xi
13.5 User-defined Exception 590
13.6 Assertions 592
14 Introduction to NumPy 603
14.1 Introduction 603
14.2 NumPy Arrays 603
14.3 Data structure of NumPy arrays 605
14.4 Creating Arrays in NumPy 607
14.5 Attributes of the ndarray Class 618
14.6 Indexing and Slicing NumPy Arrays 620
14.7 Operations on NumPy Arrays 626
14.7.1 Element-wise Operations 626
14.7.2 Matrix and Linear Algebra Functions 629
14.7.3 Reduction Operations on Arrays 635
14.7.4 Broadcasting NumPy Arrays 637
14.7.5 Array Shape Manipulation 639
14.7.6 Sorting Data 643
14.8 Structured NumPy Arrays 644
15 Introduction to Matplotlib 663
15.1 Steps to Create a Plot in Matplotlib 663
15.2 The plot Method 666
15.3 Creating Sub-plots 670
15.4 Customizing a Plot 672
15.4.1 Adding Axis Labels and Plot Titles 672
15.4.2 Adding a Grid to a Plot 674
15.4.3 Adding Ticks and Tick-labels 676
15.4.4 Adding Legends 678
15.4.5 Twin Axis 680
15.5 Bar Charts 682
15.6 Histogram Plots 687
15.7 Pie Chart 689
xii
15.8 Scatter Plots 691
15.9 Contour Plots 692
15.10 Box Plots 694
15.11 Violin Plots 696
15.12 Quiver Plots 698
15.13 3D Plots 700
15.14 3D Contour Plots 703
15.15 Wireframe and Surface Plots 705
15.16 Animation using Matplotlib 707
15.16.1 Steps to Create an Animation Plot using FuncAnimation 708
15.16.2 Steps to Create Animation Plot using ArtistAnimation 710
16 GUI Applications using tkinter 727
16.1 Introduction to Graphics User Interface 727
16.2 Components of Event Driven Programming 729
16.2.1 Widgets 729
16.2.2 Events 731
16.2.3 Event Listener Functions 735
16.3 Creating a GUI Application using the tkinter Module 735
16.4 Creating and Customizing the Main Application Window 739
16.5 Creating Widgets 741
16.5.1 Standard Attributes of Widgets 742
16.5.2 Geometry Layout Manager 750
16.6 Button Widget 765
16.7 Canvas Widget 768
16.8 Checkbutton Widget 779
16.9 Entry Widget 783
16.10 Frame Widget 785
16.11 Label Widget 787
16.12 Listbox Widget 788
16.13 Menu Widget 795
xiii
16.14 Menubutton Widget 799
16.15 Message Widget 801
16.16 Radiobutton Widget 802
16.17 Scale Widget 804
16.18 Scrollbar Widget 806
16.19 Text Widget 808
16.20 Toplevel Widget 811
16.21 Spinbox Widget 812
16.22 Messagebox Widget 814
Index 824
xiv
Preface
Python is a very powerful and one of the most widely used computer programming
language for general purpose, scientific and technical computations. Its popularity is
due to a huge collection of library functions and very easy to learn. Further, a large
number of help material and forums are available for Python. Since it is freely available,
many commercial developers are also using it to reduce their project cost and has
reported many successful applications.
This book is written following several years of teaching the Python programming
course to our students. The basic objective to write this book is to teach Python in a
friendly, non-intimidating fashion to students who have no previous programming
knowledge and experience. Therefore, the book is written in simple language with many
sample problems in mathematics, science, and engineering. Starting from the basic
concepts, the book gradually builds advanced concepts, making it suitable for freshmen
and professionals. This makes this book unique among the many books available in the
market which assume previous knowledge of a programming language. The book deals
with the latest version of the language.
For promoting outcome-based learning, each chapter of the book starts with chapter
learning objectives and lucidly introduces the basic concepts, with sample examples, to
achieve those objectives. Each chapter concludes with a summary. Finally, the chapter
ends with multiple choice questions, review questions and programming assignments
so as students can apply the concepts learned in the chapter.
The book consists of sixteen chapters. Chapter 1 introduces the basic concepts of
Computing, algorithms, flowcharts and programming. Chapter 2 gives an overview of
Python programming language. Chapter 3 gives the basics of Python Programming.
Chapter 4 discusses the operators available in Python and concepts of expressions.
Chapter 5 introduces the basic concepts of decision making and branching constructs of
Python. Chapter 6 explains loop control statements. Chapter 7 discusses User-Defined
Functions. Chapter 8 introduces the basic concepts of Lists. Chapter 9 describes
Strings. Chapter 10 covers Tuples, Sets and Dictionaries. Chapter 11 describes File
Handling in Python. Chapter 12 presents the basic concepts of Object Oriented
Programming in Python. Chapter 13 briefly explains Exception Handling in Python.
Chapter 14 introduces NumPy forefficeint numerical computations. Chapter 15 gives
overview of Matplotlib to create charts. And Chapter 16 discusses GUI Applications
using tkinter.
xv
We hope that the book will be useful in lucidly building expertise in Python
programming to the readers. We sincerely welcome any suggestion to further improve
the book. Authors can be reached at [email protected], [email protected]
and [email protected] .
Rachna Verma
xvi
About the Authors
xvii
xviii
Chapter 1
Introduction to Computing
Learning outcomes
1. Describe computer, its components, and its functioning
2. Describe different types of software
3. Describe types of programming languages
4. Develop programming logic using flowcharts and algorithms
1
Input devices Central processing unit Output devices
Memory
An input device reads data. The data can be in the form of numbers, texts,
images/videos, sound waves, etc. The read data can either be processed by the CPU or
stored in memory. The typical input devices are keyboards, mice, scanners, cameras,
joysticks, microphones.
Arithmatic and logic unit: The ALU unit consists of electronic circuits to perform addition,
subtraction, comparison, and other operations.
2
Instruction decoder: The instruction decoder unit decodes the instruction to be executed
by the processor.
Control Unit: The control unit generates required control signals to different components
for their operations. Due to this, CU is called the brain of a computer.
Registers and Cache memory: To efficiently perform various operations, the CPU has a
few high-speed internal memories, commonly known as registers. In addition to the above,
to further reduce the memory access time and enhance the computational speed of
computers, modern-day CPUs have additional high-speed memory called cache memory.
Busses: Busses, a bunch of wires, are used to exchange data and control signals among
various components. In figure 1.2, they are shown with lines.
Control unit
Registers
Memory
3
1.1.4 Memory
Computer memory
System Software can be of the following types, based on the kind of work they perform:
(c) Utility programs: Utility programs help users in system maintenance tasks and
perform tasks of routine nature. Common utility tasks are disk defragmentation,
disk clean-up, compression, virus cleaning. Some examples are CCleaner,
Everything, Partition Wizard, WinZip.
5
User
Application Software
System Software
Machine level programming: For example, on the execution of the binary code 1010000
(equal to 80 in hexadecimal) on an 8085 microprocessor, the processor will add the number
stored in register B with the number stored in register A and store the result back in register
A. A computer program is a set of such binary codes written in a particular sequence to
solve a problem. However, it is incredibly tedious and cumbersome to write instructions
manually in binary codes (called machine-level programming) even for simple tasks.
Further, each different type of CPU has its unique machine codes, making programming
more complex.
7
Ease of programming
Python, Java, C++, C,
FORTRAN, JavaScript
High Level Languages
Assembly code
Machine code
Computer hardware
Every language has its strengths and weaknesses. For example, FORTRAN is
suitable for scientific data processing but has no mechanism to organize and manage large
programs. C++ and Java have powerful object-oriented features, but it is complex and
challenging to learn. Python is suitable for interactive programming but slower in
comparison to C.
8
1.3.1 Types of Computer Programming Languages
A computer program, called source code, can be written any plain text editor, such
as Notepad, Notepad++. However, most modern programming languages have their
integrated development environments (IDE) to create/edit, compile and run a program. A
computer program written in any programming language is finally converted into machine
codes so that the computer can understand and process it. Based on the ways high-level
programs are converted into machine codes, a programming language can be classified as
a compiled, interpreted, or intermediate programming language.
A source code passes through several steps before it is converted into an executable
program. Figure 1.6 shows the major steps of this conversion. The basic steps to generate
an executable program are:
• In the first step, the compiler checks syntax errors in the source code, and if there is no
error, it converts the high-level source code into an assembly code.
• In the second step, the assembler converts the assembly code into the native object code,
i.e. machine code of a particular machine.
• Finally, the linker combines the object code, libraries, and other object codes into an
executable program. Every language has libraries of commonly used tasks, such as to
find square root, sine of an angle, etc. Other object codes are precompiled user defined
sub-programs.
9
compiled languages. Examples of popular interpreted languages are PHP, Ruby, Python,
and JavaScript.
Source code
Specific Compiler
Assembly code
Assembler
Object code
Other object
Libraries Linker codes
Executable code
10
Source code
Executable code
Source code
Generic compiler
Byte code
11
Table 1.2: Comparison of compiled and interpreted languages
5 A single error in the source program Execution of the program halts at the
stops the whole compilation process. occurrence of the first error.
12
programming skills. It is strongly recommended that a learner should master to use these
tools.
An algorithm is a finite set of steps designed to solve a task. There are no defined rules
to write algorithms, but the following are some guidelines that help in writing practical
algorithms:
13
• Identify the input and output required to solve a task.
• Break the tasks into precise and small steps to easily convert them into statements
of a target programming language. Each step in the algorithm should be clear and
unambiguous.
• Algorithms should use the most effective and efficient way out of the different ways
to solve a problem.
Step 1: Start
Step 2: Read num1 and num2.
Step 3: Calculate sum = num1+num2
Step 4: Print sum
Step 5: Stop
Example 1.2: An algorithm to find the largest number among three different
numbers.
Step 1: Start
Step 2: Input a, b and c.
Step 3: If a > b
14
If a > c
x=a
Else
x= c
Else
If b > c
x=b
Else
x=c
Step 4: Print x
Step 5: Stop
Step 1: Start
Step 2: Read coefficients a, b and c of the equation
Step 3: Calculate discriminant D = b2 - 4ac
Step 4: If D ≥ 0
r1 = (-b+√D)/2a
r2 = (-b-√D)/2a
Print Real roots are: r1 and r2.
Else
Calculate real part rp = -b/2a
Calculate imaginary part ip = √(-D)/2a
Print Complex roots are: rp+j(ip) and rp-j(ip)
15
Step 5: Stop
Step 1: Start
Step 2: Read n
Step 3: Initialize factorial =1 and i=1
Step 4: Repeat the steps until i = n
factorial = factorial*i
i = i+1
Step 5: Print factorial
Step 6: Stop
Step 1: Start
Step 2: Read n
Step 3: Initialize flag = 1 and i = 2
Step 4: Repeat the following steps until i <=(n/2)
If remainder of n/i equals 0
flag = 0
go to step 5
i= i+1
Step 5: If flag == 0
16
Print n is not prime
else
Print n is prime
Step 6: Stop
1.4.3 Pseudocode
17
}
Else
{
print “The given number is a prime number.”
}
}
1.4.4 Flowchart
18
Input-Output It represents input or output operations, i.e., reading
(Parallelogram) or writing data from/to input/output devices.
19
Example 1.7: A flowchart to add two numbers entered by the user.
Start
Sum=num1 + num2
Print sum
Stop
20
Example 1.8: A flowchart to find the largest number among three different
numbers.
Start
Read a, b, c
yes no
a>b
no no
a>c b>c
yes yes
x=c
x=a x=b
Print x
Stop
21
Example 1.9: A flowchart to find roots of a quadratic equation ax2 + bx + c = 0.
Start
Read a, b, c
d = b2-4ac
yes no
d >= 0
r1 = (-b+√d)/2a rp = -b/2a
r2 = (-b-√d)/2a ip = √(-d)/2a
Print rp, ip
Stop
Stop
22
Example 1.10: A flowchart to calculate the factorial of a number entered by
the user.
Start
Read n
factorial=1
i=1
factorial= factorial * i
i=i+1
yes
i<n
no
Print
factorial
Stop
23
Example 1.11: A flowchart to check whether a given number is a prime
number or not.
Start
Read n
flag=1
i=2
yes
Is reminder =0?
no flag=0
yes
Is i<=n/2?
no
no yes
Is flag =1?
Stop
24
1.4.6 Python Programs
Following is a Python program that finds out whether a given number is a prime
number or not. The program implements the flowchart shown in example 1.11. Readers
may skip this section as the basic syntaxes of Python are introduced in chapter 2. However,
it shows that a Python program is easy to understand as it is very near to a natural language.
This feature makes Python a popular programming language.
Output
25
Chapter Summary
26
2. Which of the following is not a part of a computer?
(a) CPU
(b) Memory
(c) Input device
(d) None of the above
3. Which of the following is an input device?
(a) Printer
(b) Speaker
(c) joystick
(d) Monitor
4. Which of the following is not an output device?
a) Printer
(b) Speaker
(c) Camera
(d) Monitor
5. Which of the following is not a part of the CPU of a computer?
(a) ALU
(b) CU
(c) Register
(d) RAM
6. Which of the following is not a permanent memory?
(a) RAM
(b) ROM
(c) Hard disk
(d) Flash memory
7. Which of the following is not a system software?
(a) Windows
(b) Linux
(c) Notepad
(d) Unix
8. Which of the following is an application software?
(a) MS Word
(b) Tally
(c) AutoCAD
(d) All of the above
27
9. Which of the following is not performed by the operating system of a
computer?
(a) File management
(b) Memory management
(c) Handling input devices
(d) Write a letter
10. Which of the following is not a programming language?
(a) C++
(b) Java
(c) Python
(d) Linux
11. Which of the following is not an operating system?
(a) Linux
(b) Windows
(c) Unix
(d) None of the above
12. Which of the following is a utility software?
(a) WinZip
(b) CCleaner
(c) Partition wizard
(d) All of the above
13. Which of the following is not a high-level programming language?
(a) C++
(b) Python
(c) Java
(d) None of the above
14. Which of the following is a low-level program?
(a) Python program
(b) BASIC program
(c) Java program
(d) Assembly program
15. Which of the following is a compiled programming language?
(a) C++
(b) Python
(c) PHP
28
(d) None of the above
16. Which of the following is not an interpreted Programming language?
(a) C++
(b) Python
(c) Java
(d) Ruby
17. Which of the following is an intermediate programming language?
(a) C++
(b) Java
(c) Python
(d) FORTRAN
18. Addition of two numbers is _____________.
(a) an imperative statement
(b) a conditional statement
(c) an iterative statement
(d) None of the above
19. Choosing a flow path based on the comparison of two numbers is
_____________.
(a) an imperative statement
(b) a conditional statement
(c) an iterative statement
(d) None of the above
20. Repeating a block of code for n times is _____________.
(a) an imperative statement
(b) a conditional statement
(c) an iterative statement
(d) None of the above
Review Questions
Programming Exercises
30
6. Write an algorithm and draw a flowchart to read the distance d (in
kilometer) traveled by a vehicle in time t ( in minutes) and calculate the
vehicle's speed in m/s.
10. Write an algorithm and draw a flowchart to find the sum of the first N
natural numbers.(Hint: sum=n*(n+1)/2)
11. Write an algorithm and draw a flowchart to find the last digit of a number.
(Hint: divide the given number by 10 and multiply the quotient by 10 and
subtract the original number).
31
32
Chapter 2
Overview of Python
Learning Outcomes
1. Identify some domains where Python is widely used.
2. Install and run the Python interpreter.
3. Create and execute Python programs using IDLE
4. Describe the basic structure of a python program
Python is a free and open-source programming language available for all major
computing platforms and operating systems. Further, it has a large set of free standard
libraries. Since it is an interpreted language, the edit-test-debug cycle is incredibly fast.
Easy debugging of Python programs is also another significant advantage of Python.
Python supports source-level debugging that allows inspection of local and global
variables, evaluation of arbitrary expressions, setting breakpoints, stepping through the
code a line at a time, and so on. Due to these features, Python is the widely used
programming language.
33
1980s. It is designed as a sequel to the ABC programming language, with exception
handling capability. The name Python is taken from the British TV show Monty Python.
Similar to other languages, Python evolves through several versions. In 1991, the
first version of Python, Python 0.9.0, was released. The first version included features
such as exception handling, classes, lists, and strings. In addition, it had lambda, map,
filter, and reduce, which made it suitable for functional programming.
In 2000, the second version, Python 2.0, was released as an open-source project and
included list comprehensions, a full garbage collector, and support for Unicode.
In 2008, Python 3.0 was released. The major noticeable change was the way the print
statement works in Python 3.0. The print statement of Python 2.0 was replaced with the
print () function in Python 3.0.
Python is one of the easiest programming languages to learn and use due to:
These features also make the Python code readable and easy to maintain and reuse.
34
3) Maturity and vast support of libraries
Python is a very mature language as it is widely used for more than 30 years.
Further, over the years, a large collection of libraries is now available at no cost. Plenty
of learning materials, such as documentation, guides, and video tutorials for Python
language, are available to programmers. Hundreds of Python libraries and popular
frameworks are available due to corporate sponsorship and a large community of
Python developers. These libraries and frameworks save time and efforts in the software
development cycle. In addition, many specialized libraries, such as nltk for natural
language processing, scikit-learn for machine learning applications, are available for
research in emerging areas of development. Further, there are libraries for the
commonly used tasks, such as Matplotib for plotting charts and graphs, SciPy for
engineering, scientific and mathematical applications, BeautifulSoup for HTML and
XML parsing, NumPy for scientific computing, and Django for server-side web
development.
Python is widely used in the emerging areas of computer science, such as cloud
computing, machine learning, neural network, data science, and big data. Leading
universities and research centers use Python to carry out research and development in
the above emerging areas.
6) Software integration
Python code can easily use libraries developed in other programming languages,
such as C, C++, and Java. This feature makes it very easy to extend the capabilities of a
python program and reduces the development cycle.
35
Python is available for almost all operating systems, such as Windows, Linux, Mac.
We can download the latest version and older versions of Python for any platform freely
from www.python.org/downloads. Python is preinstalled on most Linux distributions.
Following is a step-by-step instruction to install the latest version of Python on the
Windows operating system.
Step 1: Download the latest version of Python for windows from the
www.python.org/downloads website. The older versions of Python are also available
on the same website.
36
If the Python Installer finds an earlier version of Python installed on your computer,
the installer will give the option to upgrade to the latest version or install the latest
version separately.
Step 3: Click the Install Now (or Upgrade Now) message to start the installation. Click
Yes to the message "Do you want to allow this app to make changes to your device" to
begin the installation. Figure 2.2 shows the installation progress window. It will show
the various components it is installing, and finally, a pop-up window will appear saying
that "Setup was successful", as shown in figure 2.3.
To verify that Python is installed on your computer, open the command prompt and
type python; you will see a window, as shown in figure 2.4, telling the version and other
details. We can open a command prompt window by any one of the following options:
(1) Right-click the Start button and choose Command Prompt (or PowerShell)
(2) Press Windows key + X, followed by C (non-admin) or A (admin)).
37
Step 4: Click the close button. Python is now installed on your system.
38
2.4 Starting Python in Windows
Once Python is installed, we can use Python in two ways: Python command prompt
and Python IDLE.
The Python interpreter starts running when we enter python at the window’s
command prompt. Figure 2.5 shows the Python command prompt window. The Python
command prompt (>>>) is ready to execute Python codes. We can directly type a Python
statement at the prompt, and by pressing the enter key, the interpreter runs the
statement and produces the results. This interactive mode of the Python interpreter can
be used as a very powerful scientific calculator. For example, figure 2.5 shows how to
use the Python command prompt to evaluate the expression 10+15*3+2/3, and write a
program to add two numbers. However, the Python command prompt is not widely
used for writing programs in this fashion.
If the Python interpreter is not included in the PATH environment variable, we have
to specify the complete address of the interpreter, and the above command becomes as
given below:
C:\>C:\Users\MBM\AppData\Local\Programs\Python\Python39\python
c:\users\mbm\test.py.
39
Figure 2.5: Writing Python program at the command prompt
Program test.py
40
2.4.2 Python IDLE
A Python program can be written in any text editor, such as notepad, and can be
executed directly from the command prompt, but it is not a very convenient way to
write large programs. Therefore, most programmers use integrated development
environments (IDE), such as IDLE, VS code, Spyder, PyCharm. These IDEs provide
integrated facilities to create, edit, debug and execute a program. Most of the IDEs are
freely available. We can download an IDE of our choice from its website and install it
on our computer (More information about IDE is given in section 2.10).
In this book, we are using IDLE for creating and testing Python programs. Python's
Integrated Development and Learning Environment (IDLE) is installed by default when
we install Python. IDLE can create, modify, and execute Python programs and executes
a single statement in the interactive mode.
We can start IDLE like any other windows program from the start menu or search it
and click its icon. Figure 2.7 shows an IDLE window and it is called the IDLE Shell. The
IDLE Shell is similar to the Python command prompt and allows users to run Python
statements at its prompt. The interactive mode of IDLE is suitable for small Python
programs. But as the complexity and size of a program increases, it becomes difficult
and cumbersome to work in this mode. Therefore, for writing large programs, IDLE
provides an integrated programming editor. We can start the editor from the File menu
of the IDLE shell (File->New File) or using the shortcut command Ctrl + N, as shown
in figure 2.8. Creating a program in the editor is called script mode programming.
The IDLE editor has all the facilities to create, edit, save, open, run and debug a
program in an integrated environment. Figure 2.9 shows an editor window. The default
name of the new program is untitled. It is recommended to give a suitable name to a
program and save it before executing it.
To run the current program from the editor, use Run->Run Module, or F5 key, from
the drop-down menu of the editor (figure 2.10). The output of the program is shown in
the Python Shell, as shown in figure 2.11.
41
Figure 2.7: IDLE Shell
42
Figure 2.9: Script editor
43
2.5 Structuring Python Programs
One of the main reasons for Python's popularity is the simple syntaxes and
structures used to create Python programs. This section describes the proper structuring
and formatting of python programs.
It is a common practice to write one python statement in one line, and the 'new line
character' terminates the statement. However, it is possible to write more than one python
statement in a single line separated by semicolons, but it is not recommended, as it reduces
the program's readability. Example 2.1 shows a simple program that uses multiple
statements in a single line. Example 2.2 shows a preferred way of writing the previous
program.
44
2.5.2 Line Continuation
Some statements may be very long, and to view them, the programmer has to scroll
the screen left and right frequently. A lengthy statement can be broken into multiple lines
using line continuation to avoid scrolling and enhance readability. Python supports two
types of line continuation: implicit and backslash.
>>> a=(1+
2+
3+
4)
>>> print(a)
10
>>> b=[1,
2,
3,
4,
5]
>>> print(b)
[1, 2, 3, 4, 5]
>>> c={'a':1,
'b':2,
'c':3
45
}
>>> print(c)
{'a': 1, 'b': 2, 'c': 3}
In explicit line continuation, a backslash (\) at the end of a line indicates that the
current statement is incomplete and continues to the next line. The explicit line continuation
is typically used when implicit line continuation is not applicable, such as a long expression
without brackets. Example 2.4 shows an example of explicit line continuation.
>>> a=1\
+2\
+3\
+4
>>> print(a)
10
Comments are lines in a program that the interpreter ignores and are primarily used
to document the code properly. They greatly help in code readability and make code
maintenance and reuse very easy. In addition, we can use a comment to explain the purpose
and logic of a statement or a block of code. We can write comments throughout a program.
Python supports both line comment and block comment. To comment a single line
of text till the end of the line, we put a hash (#) character at the beginning of the text. The
line comment can begin from the start of a line (for example, #This whole line is a
comment) or start after a statement (for example, x=10 #This part of the line is a comment)
and continues until the end of the line. If we want to comment more than one line as
comments, we have to put a hash character at the beginning of each line. Please note that a
hash (#) inside a string does not make the text after it a comment, for example, x="In this
string, #this part is not a comment".
46
Python uses a pair of triple-double quotation marks (""") to create a multi-line string
literal. If we do not assign such a string to a variable, it can be used as a multi-line block
comment. Instead of a pair of triple-double quotation marks, we can also use a pair of triple-
single quotation marks (''') to create a block comment.
Please note, we begin a block comment from a line without any indentation, i.e.,
before the beginning triple-double quote, nothing is allowed, not even white spaces. In
contrast, a line comment can begin anywhere in a line and can have white spaces or any
other Python statement before the # mark.
#Show result
print(c)
x="The part after # is not a comment as it is\
inside a string"
y='The portion between """ is not a comment """" \
as it is inside a string'
print(x)# print the value of x
47
print(y) # print the value of y
#End of program
Output
30
The part after # is not a comment as it is inside a string
The portion between """ is not a comment """" as it is inside a string
48
print(a*b)
else:
print(a-b)
print(a/b)
A Python program can seamlessly include and use the codes written in other python
programs. The import statement is the primary mechanism to include codes from other
Python scripts. Though import statements can be written anywhere in the program, they
must be written before using the imported code. However, writing import statements at the
top of a program tells the program's dependencies on other modules. Hence, it is a
recommended approach.
49
The main block of a program is coded with no indentation. The program execution
begins from the first statement of the main block. The main block codes may not be
contiguous. It can be written in many segments. For example, we can write a function block,
then a part of the main block, another function block, and the other part. Example 2.7 shows
the above concepts with an example.
Documentation section
Import section
Function definitions
Main program
#Documentation section
"""
Script Author: Arvind
Organization: MBM Engineering College, Jodhpur, India
Date: 10 December 2020
Version: 1.0
Purpose: Print the largest of three randomly generated numbers
"""
#import section
#importing the random module to include random number
#generator functions
import random
#Function section
50
#Function to find the largest of three numbers
x=random.randint(10,100)
y=random.randint(10,100)
z=random.randint(10,100)
print("The largest of (",x,",",y,",",z,") is ",largest(x,y,z))
51
more readable and consistent codes. Following are the most important points of the PEP 8
style:
• Use docstrings. A docstring is the first block comment string written after the function
header or written at the beginning of a module. Python uses the docstring of a
module/function for automatically generating the help of the function/module.
• Limit the number of characters in a line to less than 80 characters. This limit helps view
a program without using a horizontal scroll and correctly print a program on a paper.
To meet the 80 characters’ limit, a program line can be broken into multiple lines using
line continuation mechanisms.
• Use comments to explain the purpose and logic of the code. Comments should form
complete sentences and should be meaningful to the code.
• Use Python’s default UTF-8 or ASCII encodings for writing programs. These encodings
make programs portable internationally. UTF-8 is a Unicode-based encoding system to
accommodate characters of most of the natural languages.
• Use a consistent naming convention. For example, refer to the naming convention
section 2.8 below, which describes a widely used naming convention.
• Don’t use non-ASCII characters in identifiers, as this reduces code reusability and
creates problems in code maintenance.
• Use relevant names instead of generic names. For example, use student_list,
class_list instead of list1, list2.
52
• Avoid using similar-looking characters as single-characters identifier names. For
example, ‘l’ (lowercase letter el) and ‘I’ (uppercase letter eye) confuse with 1.
Similarly, ‘O’ (uppercase letter oh) confuses with zero.
Following are the specific conventions to be used to name different types of objects in
Python:
• Packages and modules: Use all lower case letters to name a package/module. For
multiple words package names, use an underscore to separate each word. However,
a single-word package/module name is preferable, for example, numpy, sklearn,
sklearn.linear_model.
• Classes: Use camelCase to name a user-defined class. In camelCase, the first letter
of the first word in the identifier name is in the lower case, while the first letter of
every subsequent word is in the uppercase. Further, use only the English alphabets
in a class name; avoid using numerals, underscore, and special symbols. In Python,
all the built-in classes are in lowercase words, except the Error class.
• Jython: Jython is a Java implementation of Python and can be used on any platform
with a JVM installed. Jython has an interactive interpreter that can interact with Java
packages as well as running Java applications. This interactive interpreter makes it
a rapid application development tool and helps seamless interaction between
Python and Java.
• PyPy: PyPy is another Python implementation using Python itself and uses just-in-
time (JIT) compilation. It is said to be 7.5 times faster than CPython. In JIT
compilation, the source codes are compiled directly to the native machine code,
making it very fast.
54
standard Python. The two popular editors are described next, for others, refer their websites
for their features.
PyCharm, developed by JetBrains, is another popular IDE used for the Python
programming language. It provides code analysis, a debugger, and supports web
development with the Django web framework. It is cross-platform and available for
Windows, MacOS, and Linux. The Community Edition is freely available and can be
downloaded from the link https://www.jetbrains.com/PyCharm/download/.
2. 11 Python Distributions
As already stated, Python is a general-purpose programming language that is
widely used for many tasks, such as data science, machine learning. However, the standard
Python installation may not be suitable for different tasks as it frequently requires installing
dependent packages from scratch. Several tools and utilities are freely available to manage
packages easily, called distributions. A Python distribution is a bundle that contains a
Python implementation along with a bunch of libraries, tools, and IDEs. Popular Python
distributions are Anaconda, Enthought Canopy, ActiveState, and Intel. We can install
multiple Python distributions on a single system and use them independently as per our
requirements.
Anaconda is a free and open-source Python distribution widely used for data science
and machine learning applications. It uses conda as its package manager. Anaconda is pre-
bundled with popular data science and machine learning software libraries, such as Scikit-
learn, Keras, PyTorch, TensorFlow, SciPy, and many other popular data science packages
suitable for Windows, Linux, and MacOS. It also includes two popular IDEs, namely,
Spyder and Jupyter notebook for writing and executing Python programs. We can
download the Anaconda Individual Edition distribution from
https://www.anaconda.com/download. For other distributions, interested readers may
refer to their websites.
55
Chapter Summary
56
3. Python is initially developed by
(a) Charles Babbage
(b) Guido van Rossum
(c) Dennis Ritchie
(d) Larry Wall
4. Which of the following can be used to write a Python program?
(a) IDLE
(b) PyCharm
(c) Spyder
(d) All of the above
5. Which of the following is not a Python distribution?
(a) Anaconda
(b) Enthought Canopy
(c) ActiveState
(d) None of the above
6. The default package manager of Anaconda distribution is
(a) conda
(b) Spyder
(c) Jupyter
(d) pip
7. Which of the following IDE is installed by default with Python?
(a) IDLE
(b) VS Code
(c) Spyder
(d) Jupyter
8. Which of the following character is used to start a line comment?
(a) #
(b) /
(c) %
(d) “
9. Which of the following is valid to start a block comment?
(a) """
(b) %
(c) #
(d) None of the above
57
10. Which of the following character is used to separate multiple statements in a
line?
(a) comma
(b) Semi-colon
(c) Colon
(d) Space
11. Which of the following character is used to separate multiple expressions?
(a) comma
(b) Semi-colon
(c) Colon
(d) Space
12. Which of the following character is used to continue a statement to the next
line?
(a) Backslash
(b) Forward slash
(c) Colon
(d) Space
13. Which of the following function key is used to run a script in IDLE?
(a) F5
(b) F6
(c) F7
(d) F8
14. Which of the following shortcut key is used to open a new script?
(a) Ctrl+O
(b) Ctrl+S
(c) Ctrl+N
(d) Ctrl+P
15. Which of the following is the default name of a script in IDLE?
(a) script
(b) noname
(c) untitled
(d) None of the above
58
Review Questions
59
60
Chapter 3
Like any other high-level programming language, Python uses a set of symbols,
such as a, b, +, /, 1, 2, and keywords along with a set of syntax rules to write computer
programs. However, Python is very close to the English language in constructing its
statements, making it one of the most widely used programming languages. Further, it
uses fewer syntactic constructions and uses common English keywords, making Python
programs highly readable, easy to comprehend, and economical to maintain.
61
Most of the IDEs used to write programs using English keyboards do not have direct
facilities for typing all the Unicode characters. However, any Unicode character can be
easily included in a string using the escape character sequence “\u+Unicode of the
character”. For example, to create a string a=”αβγ”, in Python code, it is coded as
a=”\u03b1\u03b2\u03b3”, where 03b1, 03b2, and 03b3 are the Unicode of α, β, and γ,
respectively.
Example 3.1: Use of Unicode(from Hindi and Grrek letters) in a Python program
return अ + ब
>>> क=10
>>> ख=20
क और ख का जोड़ : 30
Letters All English alphabets, both lower and upper case, i.e., A, B, C,
…X, Y, Z, and a, b, c, … x, y, z.
Digits 0,1,2,3,4,5,6,7,8,9
Special Symbols Comma (,), period (.), semicolon (;), colon (:), question mark
(?), apostrophe ('), quotation mark ("), exclamation mark (!),
vertical bar (|), slash (/), backslash (\), tilde(~), underscore(_),
dollar($), percent sign(%), ampersand (&), caret (^), asterisk
(*), minus sign(-), plus sign (+), opening angle bracket or less
than sign (<), closing angle bracket or greater that sign (>), left
parenthesis ((), right parenthesis ()), left bracket ([), right
bracket (]), left brace ({), right brace ( }), number sign (#).
62
White spaces Blank space, horizontal tab, newline, carriage return, form
feed.
Python Token
3.3 Keywords
Keywords are reserved words for specific purposes to write Python statements, and they
can’t be used for any other purpose, such as naming variables, functions, or any other
identifier. They are the building blocks of Python and are used to define the syntax and
structure of the Python language. Keywords are case sensitive in Python, and there are 33
keywords in Python 3. Table 3.2 lists all the keywords of Python 3.10 with a brief description
of each. In all, there are 35 keywords in Python 3.10. Please note, the number of keywords
may be different in different versions of Python. You can use the help () function in your
Python shell without any argument and then type a keyword to list the keywords in your
Python installation, as illustrated below.
63
>>> help()
If this is your first time using Python, you should definitely check out
the tutorial on the Internet at https://docs.python.org/3.9/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
help> keywords
Here is a list of the Python keywords. Enter any keyword to get more help.
Keyword Description
64
as To create an alias
continue To skip the remaining portion of the body of a loop and continue the
next iteration of the loop
65
import To import a module
3.4 Identifiers
An identifier is a sequence of characters used to name a variable, function, class,
module, or other objects. In Python, an identifier starts with an alphabet, preferably an
English letter, A to Z or a to z or an underscore (_), followed by zero or more letters,
underscores, and digits (0 to 9). Python is a case-sensitive language, i.e., upper case letters
66
are different from the lower case letters. Hence, Name, NAME, and name are different
identifiers.
1. An identifier name must contain only letters, digits, and underscore. The letter can
be from any human language. However, English letters are widely used and highly
recommended.
2. The first character of an identifier name must be a letter or underscore, i.e., an
identifier name can’t start with a digit.
3. A Python keyword cannot be used as an identifier name.
4. An identifier cannot have space or special characters, such as $, +, -, %.
5. An identifier can be of any length.
Examples of some valid identifier names are: a, B, Abc, var1, var_1, _var, _1var, my_list,
name_of_student. Please note, an underscore ( _ ) is a valid identifier name. Non-English
alphabets/words such as क, ख, कमल, जोड़, are some Hindi valid identifier names, and a,
b. d, m, l, p, ab are some Greek valid identifier names. Table 3.3 gives examples
of some invalid identifier names along with reasons.
67
3.5 Literals and Their Types
A literal in a program is a constant value, such as 10, 25.5, 'abc', (1,2,3), that does not
change during the execution of a program. Python supports the following literal types: int,
float, complex, str, bytes, bool, NoneType, list, tuple, dict and set. Figure 3.2 shows a
classification of literal types of Python.
Python literals
string bytes
A string literal is a fixed text. In Python, a string literal is written using a pair of single
quotes ('), double quotes ("), triple single quotes ('''), or triple double quotes ("""), for
example,
There is no difference between a single quote and double quote literals. However, we
cannot start a literal with a single quote and end with a double quote, i.e., mixing single and
double quotes is invalid. Hence, an attempt to define a string literal as ‘Mixing of single and
double quotes is an error” will generate an error. Triple single/double quotes are used to
create formatted multiline strings. Python ignores a string literal that is not assigned to a
variable. Hence, triple quote multiline literals can be used to write comments in Python.
Example 3.2 illustrates the above concepts.
>>> print(c)
This is an
example
of
multiline and formatted triple single quote
literal
>>> d=""" This is a
69
triple double
quote string literals"""
>>> print(d)
This is a
triple double
quote string literals
Python 3 literals, by default, use Unicode. Hence, Python can create string literals
containing any character from most human languages (e.g., English, Spanish, Japanese,
Arab, Hebrew, Hindi). Contrary to Python 2, Python 3 string literals are Unicode. Hence
there is no requirement of prefixing u before a string literal to make it a Unicode string
literal. For example, the Python 2.0 Unicode string literal u'abc' is written in Python 3 as
'abc'.
Any Unicode character can be inserted in a string literal by using escape sequence
\u followed by the four-digit hexadecimal code of the character. For example, The Python
equivalent of the string αβγ is "\u03b1\u03b2\u03b3", where 03b1, 03b2, and 03b3 are
Unicodes of α, β, and γ, respectively. Example 3.3 illustrates the above concepts.
70
By default, Python 3.0 string literals use the UTF-8 encoding system, and the literals
created are of type str. However, a string literal can be made byte string (uses only ASCII
characters) by prefixing it with b. The object type of byte string literals is bytes. We can get
the type of an object by the type () built-in function. For example, b"My String" is a byte
string. An str object can be converted into a byte object by the encode () method of the str
object. And, a byte object can be converted into an str object by the decode () method of the
byte object. String literals can be encoded using other encoding systems, such as UTF-16,
and decoded back by explicitly passing the coding system in the encode () and decode ()
functions. Example 3.4 illustrates the above concepts.
71
UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x2e
in position 60: truncated data
>>> s5=s2.decode('UTF-8')
>>> print(s5)
String literals can be made byte strings by prefixing with b.
>>> s6=s1.encode('utf-16')
>>> print(s6)
b'\xff\xfeP\x00y\x00t\x00h\x00o\x00n\x00 \x003\x00 \x00s\x00t\x00r
\x00i\x00n\x00g\x00s\x00\x00u\x00s\x00e\x00 \x00U\x00T\x00F\x00\x008
\x00 \x00c\x00o\x00d\x00i\x00n\x00g\x00 \x00f\x00o\x00r\x00 \x00s
\x00t\x00r\x00i\x00n\x00g\x00
\x00l\x00i\x00t\x00e\x00r\x00a\x00l\x00s\x00'
>>> s7=s6.decode('utf-16')
>>> print(s7)
Python 3 strings use UTF-8 coding for string literals
By default, a backslash (\) character and a few characters after it have special
meaning in a string literals. Table 3.4 lists commonly used such combinations along with
their brief descriptions. The backslash (\) is called the escape character.However, to change
this default behavior of backslash characters in string literals, Python supports the concept
of a raw string. In a raw string, Python treats a backslash (\) as a simple character instead
of an escape character. A raw string literal is created by prefixing a string literal with 'r' or
'R'. It is useful when we don’t want to give special meaning to the backslash character.
Example 3.5 illustrates escape sequences, and Example 3.6 shows the concept of raw string.
Escape Description
Sequence
\\ To include a backslash (\) in a string
\' To include a single quote (') in a string
\" To include a double quote (") in a string
72
\a To include a bell sound in a string
\b To include a backspace character in a string
\f To include a form feed character in a string
\n To include a line feed character in a string.
\r To include a carriage return character in a string.
\t To include a horizontal tab character in a string.
\v To include a vertical tab character in a string.
\ooo To include a character with an octal value ooo in a string.
\xhh To include a character with a hex value hh in a string..
\N{name} To include a character that is identified by a name in the
Unicode database in a string.
\uxxxx To include a character with 16-bit hex value xxxx. Exactly
four hexadecimal digits are required in a string.
\Uxxxxxxxx To include a character with 32-bit hex value xxxxxxxx.
Exactly eight hexadecimal digits are required in a string.
73
This string includes a form feed() character
>>> print("This string is \nprinted in two lines")
This string is
printed in two lines
>>> print("This string is \rprinted in two lines")
This string is
printed in two lines
>>> print("In this string, a tab\tis inserted")
In this string, a tab is inserted
>>> print("This string is \vprinted in two lines")
This string is
printed in two lines
>>> print("Print ABC using octal codes \101\102\103")
Print ABC using octal codes ABC
>>> print("Print ABC using hexadecimal codes \x41\x42\x43")
Print ABC using hexadecimal codes ABC
>>> "Delta symbol is \N{GREEK CAPITAL LETTER DELTA}"
'Delta symbol is Δ'
>>> "Alpha symbol is \N{GREEK SMALL LETTER ALPHA}"
'Alpha symbol is α'
>>> print("Print omega using 16-bit Unicode \u03A9")
Print omega using 16-bit Unicode Ω
>>> print("Print omega using 32-bit Unicode \U000003A9")
Print omega using 32-bit Unicode Ω
74
>>> print(r"This\tis\ta\traw\nPython string")
This\tis\ta\traw\nPython string
>>> print(r"In raw strings,\\ has no special meaning")
In raw strings,\\ has no special meaning
Numeric literals are fixed numerical values. Python has many types of numeric
literals: integer number, floating-point number, and complex number.
Integer literals represent whole numbers. In Python, integer literals can be classified
as decimal integer, octal integer, hexadecimal integer, and binary integer. There is no limit
on the number of digits in an integer literal. Further, we can use an underscore (_) to
separate the two adjacent digits of an integer literal for better clarity and readability. The
underscore is ignored when processing an integer literal. For example, 100 can be written
as 1_0_0. However, we cannot use more than one underscores to separate two consecutive
digits. For instance, 1__0_0 will raise the invalid decimal literal error. Also, note that leading
zeros in decimal integer literals are not allowed. For example, the statement a=0100 will
raise an error.
A hexadecimal integer literal begins with 0x, an octal integer literal begins with 0o,
and a binary integer literal begins with 0b. For example, the decimal literal 100 can be
75
represented in hexadecimal, octal, and binary integer literals as 0x64, 0o144, and 0b1100100,
respectively. Irrespective of the types of integer literals used to assign a value to a variable,
Python’s print () function will always print the variable's value as a decimal integer only.
To print the integer literal in the hexadecimal, octal, or binary format, we have to convert
an integer literal to an equivalent string using the built-in functions hex (), oct (), and bin (),
respectively. For example, hex (100) will return '0x64', oct (100) will return '0o144', and bin
(100) will return '0b1100100'. The returned string literals can be converted back to integers
with the help of the int () function. A proper base value should be used for the correct
conversion. For example, to convert ‘0x64’ into an equivalent integer, use int ('0x64', 16).
Similarly, to convert '0o144', use int ('0o144', 8) and for '0b1100100', use int('0b1100100', 2).
The second parameter in the function int () is the base value of the number system of the
first parameter. However, we can use any form of integer literals in calculations directly.
For example, the expression 100+0x64+0o144+0b1100100 is a valid Python expression and
evaluates to 400. Example 3.8 shows the above concepts.
76
>>> print(hex(c)) #Print a hexadecimal equivalent string
0x64
>>> print(oct(c)) #Print an octal equivalent string
0o144
>>> e=0b1100100 #Create a binary integer
>>> print(e)
100
>>> print(bin(e)) #Print a binary equivalent string
0b1100100
>>> print(int('0x64' ,16))#Convert a hexadecimal integer string into int
100
>>> print(int('0o144' ,8))#Convert an octal integer string into int
100
>>> print(int('0b1100100',2)) #Convert a binary integer string into int
100
>>> print(a+c+d+e)
400
>>> f=100+0x64+0o144+0b1100100 #Addition of different types of literals
>>> print(f)
400
>>>
Any number with a fraction (fraction value may be zero) and a decimal point is a
floating-point literal, for example, 100.50, 31.4, 0.0012, -10.25. A floating-point literal can
also be written in the exponent form, using the character ‘e’, for example, 1.0050e2, 3.14e1,
1.2e-3, -1.025e1. Like integer literals, an underscore can also separate consecutive digits of a
float literal for enhanced readability. For example, 1.23_4e1_2 is a valid float number.
Python float literals are 64-bit double-precision values. The maximum value of a float literal
is approximately 1.8 x 10308. Example 3.9 shows the above concepts.
77
Example 3.9: Floating-point literals
>>> a=3.14
>>> b=3.12e2
>>> print(a,b)
3.14 312.0
>>> a=1.23_4e1_2 #underscores are ignored
>>> print(a)
1234000000000.0
>>> c=1.0e-2
>>> print(c)
0.01
>>> import sys #import sys module
>>> sys.float_info #shows the information of float literals.
Sys.float_info(max=1.7976931348623157e+308, max_exp=1024,
max_10_exp=308,
min=2.2250738585072014e-308, min_exp=-1021,
min_10_exp=-307, dig=15, mant_dig=53,
epsilon=2.220446049250313e-16, radix=2, rounds=1)
A complex number can also be created using the complex () function, which takes
either two real numbers or a string as its parameters. For example, to create the complex
78
number 10+20i, we can use the expressions complex(10,20) or complex(‘10+20j’). We can
obtain the real and imaginary parts of a complex number using real and imag attributes of
the number, respectively. For example, c.real will return the real part of a complex number
c, and c.imag will return the imaginary part. The abs () function returns the absolute value
of a complex number. Example 3.10 illustrates the above concepts.
There are only two Boolean literals in Python: True and False. True represents true
logical value, and False represents false logical value. Boolean literals is of the bool type.
Hence, type(True) will return 'bool'. In python, the numerical value of True is 1 and of
False is 0, when used in arithmetic expressions. For example, the expression 2+False is equal
to 2, and the expression 2+True is equal to 3. A relational expression, such as a>b, will return
True if it satisfies the given condition; else, it will return False. For example, 10<20 will
79
evaluate to True, whereas 10>20 will evaluate to False. Example 3.11 illustrates the above
concepts.
Python has four different types of collection literals: List, Tuple, Dict, and Set. They
are briefly discussed in the following sections but are discussed in greater detail in later
chapters, as they are vital in Python programming.
A list literal is a collection of literals of different data types. The values stored in a
list literal are separated by comma (,) and enclosed within square brackets ([]). For example,
a=[1,2,3, 'Four', 'Five']. We can access an individual item in a list using an index. For
example, a[2] will return 3. A list literal can contain other list literals or any other collection
80
literals. The variable created by assigning a list literal is mutable, i.e., we can modify the
contents of a list variable. Example 3.12 illustrates the above concepts.
Similar to a list literal, a tuple literal is also a collection of literals of different data
types, but it is immutable. It means that once a tuple is assigned to a variable, the content
of the variable cannot be modified. However, we can assign a new tuple to the variable. A
tuple literal is enclosed in parenthesis, (), and each element is separated by a comma (,). For
example, a = (1,2,3, 'Four', 'Five'). Like a list, we can access an individual item of a tuple
using indexing. For example, a[2] will return 3. An attempt to modify a will result in an
error. Example 3.13 illustrates the above concepts.
81
Example 3.13: Tuple literals
A dict literal (dict stand for dictionary) uses a pair of curly brackets to store a
collection of data in the form of key: value pairs. A key and its value are separated by a
colon (:). It uses curly-braces '{}' to enclose key: value pairs and the consecutive pair is
separated by a comma (,). The key values are distinct and unique in a dict literal. If we repeat
a key in a dict literal, the last key: value pair will overwrite the previous one.
82
>>> b['name']
'Ram'
>>> a[1]
'One'
>>> c={1.2:'Float',1:"Integer",'abc':'String'}
>>> c[1.2]
'Float'
>>> a={1:'One',2:'Two',1:'Three'} #Duplicate key, last one is
retained.
>>> a
{1: 'Three', 2: 'Two'}
>>> a[1]
'Three'
>>> b={[1,2,3]:'123', (1,2,3):'One'}#Error: Lists cannot be used as
keys.
Traceback (most recent call last):
File "<pyshell#105>", line 1, in <module>
b={[1,2,3]:'123', (1,2,3):'One'}
TypeError: unhashable type: 'list'
>>> b={(1,2,3):'123', (1):'One'}#Tuples are used as keys
>>> b
{(1, 2, 3): '123', 1: 'One'}
>>> b={(1,2,3):[1,2,3], (1):'One'}
>>> b
{(1, 2, 3): [1, 2, 3], 1: 'One'}
>>> b[(1,2,3)]
[1, 2, 3]
>>> b[1]
'One'
>>> b[0] #Error: Undefined keys will generate the KeyError
Traceback (most recent call last):
83
File "<pyshell#112>", line 1, in <module>
b[0]
KeyError: 0
>>> c={(1,2,3):'1,2,3',(4,5,6):'4,5,6'}
>>> c[(1,2,3)]
'1,2,3'
84
File "<pyshell#24>", line 1, in <module>
s2={1,2,[3,4,5]}
TypeError: unhashable type: 'list'
>>> s1[0] #Error: Indexing not allowed
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
s1[0]
TypeError: 'set' object is not subscriptable
>>> for a in s1: #Items can be accessed through iteration
print(a)
(5, 6, 7)
1
2
Three
Four
Python has a special literal, None, to represent nothing or a null value. 'None' is
used to define a null variable. It is not the same as an empty string, False, or a zero. It is a
data type of the class NoneType. If we assign None to a variable, the variable contains
nothing. In Python, if a function does not return anything, it returns None. Example 3.15
illustrates the above concepts.
85
>>> if a== None:
print('A is empty')
A is empty
>>> def fun(a,b): #Function that return nothing, returns None
c=a+b
>>> print(fun(10,20))
None
>>> print(False==None) # None is not equal to false
False
>>> print(''==None) # None is not equal to an empty string
False
>>> print(0==None) # None is not equal to zero
False
>>> print(None=={}) # None is not equal to an empty set
False
>>> print(None==[]) # None is not equal to an empty list
False
>>> print(None==dict()) # None is not equal to an empty dictionary
False
>>> print(None==()) # None is not equal to an empty tuple
False
>>> print(None==None) #None is only equal to None
True
3.6 Variables
A variable is a data that permits the modification of its value during the execution
of the program. In Python, we create a variable by assigning a value to an identifier. For
example, the statement x=10 creates the variable x in the memory. The type of value hold
86
by a variable decides the type of the variable. Python does not support explicit type
declaration of a variable. A variable can hold different types of data at different times during
the execution of a program. Hence, the type of a variable is dynamic. For example, the type
of the variable x is int, as currently, it is holding an integer, i.e., 10. The type of a variable
can be checked by the function type (). Hence, the statement type(x) will return int. The type
of a variable is dynamic in nature as the type of a variable will change when we assign a
different type of data to it. For example, the statement x=10.5 will change the data type of
the variable x to float. Example 3.16 illustrates the above concepts.
>>> x=10
>>> type(x)
<class 'int'>
>>> x=10.5
>>> type(x)
<class 'float'>
3.7 Operators
Operators are special symbols or reserved words used to perform various
operations on data. For example, in the expression s= 10 + 20, the character + is an operator
and performs the addition operation on data 10 and 20. The data are called operands.
Python has a rich set of operators for performing arithmetic, relational, logical, bitwise,
assignment, membership, and identity operations. Table 3.5 lists all the built-in operators
of Python. Example 3.17 illustrates some arithmetic operators. Chapter 4 describes these
operators in detail.
87
&, |, ^ Bitwise operators
=, +=, -=, /=, //=, Assignment Operators
is, is not Identity operators
in, not in Membership operators
>>> a,b=19,7
>>> print(a+b, a-b, a*b, a/b, a**b,a//b, a%b)
26 12 133 2.7142857142857144 893871739 2 5
>>> a,b=5.5,2.2
>>> print(a+b, a-b, a*b, a/b, a**b,a//b, a%b)
7.7 3.3 12.100000000000001 2.5 42.540042248725975 2.0
1.0999999999999996
>>> print(a==b, a<b, a>b, a!=b)
False False True True
3.8 Delimiters
In Python programs, some special characters are used as punctuation marks, such
as separating data, assigning special meaning to the next character or a group of characters,
grouping data. Table 3.6 lists commonly used delimiters. Example 3.18 illustrates the uses
of some of the delimiters.
Symbol Description
Comma ( , ) To separate data items, variables, expressions.
Colon ( : ) • Used as the slice operator for a sequence.
• To create a new block in a conditional statement, a looping
statement, or function definition.
• To create a key and value pair in a dictionary.
88
Dot ( . ) To access an attribute or a method of an object.
Single quote (') • A pair of single quotes are used to create a string literal.
• A pair of triple single quotes are used to create a multiline
preformatted string literal.
Double quote(") • A pair of double quotes are used to create a string literal.
• A pair of triple-double quotes are used to create a multiline
preformatted string literal.
Semi colon ( ; ) • To separate statements which are written in a single line.
• To end a line.
Parentheses ( ) • To enclose items of a tuple.
• To enclose arguments/ parameters in a function.
• To change the order of evaluation of operators in an
expression.
Brackets [ ] • To create a list.
• To access items in a collection.
Curly Brackets { } • To create a dictionary or a set.
• To format strings.
>>> list1=[1,2,3,4,5,6,7,8]
>>> list1[2:4] # Use a colon to slice a collection
[3, 4]
>>> dict1={1:'One',2:'Two'} # Use a colon to link key and value pair
>>> string1='I love Python'
>>> string1.upper()# Use a dot to access a member function
89
'I LOVE PYTHON'
>>> a='This is a single line string using single quote'
>>> b="This is also a single line string using double quote"
>>> c="""This
is
a multiline string"""
>>> d='''This is also a multiline string
using triple single quote'''
>>> a=10; b=20; c=30; # Use a semicolon to separate two statements
>>> b=(1,2,3) # Use parentheses to create a tuple
>>> sum(10,20) # Use parentheses to call a function
30
>>> c=[1,2,3] # Use square brackets to create a list
>>> b[1],c[1] # Use square brackets to access items in collections
(2, 2)
>>> set1={1,2,3,4} # Use curly brackets to create a set
>>> dict1={1:'one',2:'two'} # Use curly brackets to create a dict
The input () function is used to read data from the keyboard up to the newline
character and returns the read data as a string. It is important to remember that the input ()
function returns the input line as a string, and we have to explicitly convert the returned
string into desired data types, such as integer, float, as per our requirement. The syntax and
parameters of the input function are given in table 3.7.
90
Table 3.7: The input function
Syntaxes:
1. variable = input ()
2. variable = input(prompt)
In the second format, the input function first prints the string prompt on the console
and then takes the input. Example 3.19 illustrates the uses of both forms of the input ()
function. We cannot read integers, floats, complex numbers, lists, tuples, sets, and
dictionaries data directly. The input function reads everything as a string, and we have to
convert the returned string into the desired data types explicitly.
>>> a=input() # Reads data from the keyboard without a prompt. Not
preferred.
10
>>> type(a) # Note the return type. It is always the string type.
<class 'str'>
>>> print(a)
10
>>> b=input("Enter a number") # Reads data with a prompt. Preferred.
Enter a number10
>>> type(b) # Note the return type.
<class 'str'>
>>> print(b)
10
>>> c=input("Enter a string: ")
91
Enter a string: Python is a very powerful language
>>> print(c)
Python is a very powerful language
>>> d=input("Enter numbers: ")
Enter numbers: 1,2,3
>>> print(d)
1,2,3
>>> type(d) # Note the return type.
<class 'str'>
>>> e=input ("Enter a list: ")
Enter a list: [1,2,3,4,5]
>>> print(e)
[1,2,3,4,5]
>>> type(e) # Note the return type.
<class 'str'>
As we have already discussed, the input () function returns an input line as a single
string. However, we can easily convert the returned string into its equivalent numeric data
by using int (), float (), and complex () functions. For example, to convert a string of digits
into an integer number, we use the int (str_data, [base]=10) function. For example, the
expression int ('123') converts the string '123' into the decimal integer 123.
We can also use the int() function to convert a string containing an integer in the
binary, octal, and hexadecimal forms using a suitable base value, i.e., 2, 8, or 16, for binary,
octal, and hexadecimal, respectively. For example, the expression int('1010',2) evaluates to
10; the expression int('1010',8) evaluates to 520; and the expression int('1010',16) evaluates
to 4112. Please note, the parameter str_data must be valid for the specified base value;
otherwise, an error is generated. For example, int('123',2) results in an error, as the string
'123' is not a valid binary number string.
Similarly, the float (str_data) function converts a string containing a float number
into a float number. For example, the expression float('123.45') evaluates to 123.45. The
92
str_data parameter may contain a float number in the scientific notation. For example, the
expression float('12.345e1') evaluates to 123.45.
We use the complex (str_data) to convert a string containing a complex number into
a complex number. For example, the expression complex('3+4j') evaluates to (3+4j).
If the str_data parameter is not a valid string for the desired data type, an error is
raised. For example, the expressions int('123.45'), int('abc123'), int("12 22"),
float('abc123.45'), complex('3+4i') result in errors.
Example 3.20 illustrates some uses of the int () function for reading various types of
integer data, and example 3.21 illustrates uses of the float () and complex () functions.
93
>>> print(a, oct(a))
5346 0o12342
>>> a=int(input("Enter a hexadecimal number:"),16) #Read a
hexadecimal number
Enter a hexadecimal number: FF
>>> a # By default, a number is printed in decimal format
255
>>> a=int(input("Enter an integer number:")) #Invalid integer string
Enter an integer number:12a
Traceback (most recent call last):
File "<pyshell#109>", line 1, in <module>
a=int(input("Enter an integer number:"))
ValueError: invalid literal for int() with base 10: '12a'
>>> a=int(input("Enter a binary integer number:"),2)#Invalid binary
Enter a binary integer number:123
Traceback (most recent call last):
File "<pyshell#110>", line 1, in <module>
a=int(input("Enter a binary integer number:"),2)
ValueError: invalid literal for int() with base 2: '123'
Example 3.21: Reading float and complex numbers from the console
94
Enter a float number:1.2e 2
Traceback (most recent call last):
File "<pyshell#111>", line 1, in <module>
a=float(input("Enter a float number:"))
ValueError: could not convert string to float: '1.2e 2'
>>>
>>> a=complex(input("Enter a complex number:"))
Enter a complex number:2+7j
>>> a
(2+7j)
>>> a=complex(input("Enter a complex number:")) #Error: spaces are
not allowed
Enter a complex number:2 + 3j
Traceback (most recent call last):
File "<pyshell#112>", line 1, in <module>
a=complex(input("Enter a complex number:"))
ValueError: complex() arg is a malformed string
We can use the int (), float (), and complex () functions to convert a string consisting
of a single numeric data, but these functions cannot convert a string that consists of more
than one numeric data separated by delimiters. To convert such a string into a set of
numbers, we first split the string into its substrings with the help of the split () method of
the string class, and then we convert each substring into its equivalent number using an
appropriate conversion function. By default, the split () function uses white space as a
delimiter, but any other character can be passed as a delimiter. The split () function returns
substrings as a list of strings. The generated set of numbers can also be stored in a list of
numbers and processed further. Example 3.22 illustrates the above.
95
Enter numbers separated by spaces:1 2 3 4 5
>>> print(s)
1 2 3 4 5
>>> s1=s.split() #Split the string into substrings
>>> print(s1)
['1', '2', '3', '4', '5']
>>> a=[] #Initialise an empty list
>>> for x in s1:#Convert each substring into an integer and add to
list
a.append(int(x))
>>> print(a) #Print numeric list
[1, 2, 3, 4, 5]
>>> type(a)
<class 'list'>
>>> s=input("Enter numbers separated by comma:")#Use a comma as the
delimiter
Enter numbers separated by comma:1,2,3,4,5
>>> s1=s.split(',') #Split into substrings using comma as a delimiter
>>> a=[]
>>> for x in s1:
a.append(int(x))
>>> print(a)
[1, 2, 3, 4, 5]
>>> s=input("Enter real numbers separated by commas:") #Read floats
Enter real numbers separated by commas:1.2, -0.3, 2.3e2, 4
>>> s1=s.split(',')
>>> a=[]
>>> for x in s1:
a.append(float(x))
>>> print(a)
[1.2, -0.3, 230.0, 4.0]
96
>>> s=input("Enter complex numbers separated by commas:") #Read
complex
Enter complex numbers separated by commas:1+2j,3-5j,1,-4j,1.2e2+3j
>>> s1=s.split(',')
>>> a=[]
>>> for x in s1:
a.append(complex(x))
>>> print(a)
[(1+2j), (3-5j), (1+0j), -4j, (120+3j)]
The eval (string) function is a powerful built-in function that can execute valid
Python expressions stored in a string. For example, the statement x =eval ('10+20') will
execute the expression '10+20' and assign the result 30 to x. Similarly, the statement x,
y=eval ('10+20, 20*3') will execute the expressions 10+20 and 20*3 and assigns the results to
x and y. The syntax and parameters of the eval () function are given in table 3.8. Please note
that the eval () function cannot evaluate statements. Hence, the statement eval ('x=10,
y=5+10') will generate error. This ability to dynamically execute expressions in a string and
assign results to variables can be used, along with the input function, to read multiple data
from the console.
We can use the eval () function to parse a string containing every type of literals,
including list, tuple, set, and dict. Example 3.23 illustrates some uses of the eval () function
to convert the string returned by an input function into different data types.
Since the eval () function can execute any valid Python expression, such as deleting
files from the computer, its use to read from the console may be dangerous as an illegitimate
user may input malicious codes that may harm your computer. A malicious code is an
expression/command intended to cause undesired effects, security breaches, or damage to
a system. This danger can be reduced through the additional parameters (globals and locals)
but cannot be ruled out. Hence, it is strongly recommended not to use the eval () function
for reading data from the console when the safety and security of the system are a concern.
97
Table 3.8: The eval function
Syntax:
Parameters:
98
>>> print(a,b)
(1+2j) (4-3j)
>>> a,b=eval(input("Enter two strings:")) #Read strings
Enter two strings:'Python', 'Programming'
>>> a,b,
('Python', 'Programming')
>>> print(a,b)
Python Programming
>>> a,b=eval(input("Enter two strings:"))#Error: undefined variables
Enter two strings:abc , xyz
Traceback (most recent call last):
File "<pyshell#165>", line 1, in <module>
a,b=eval(input("Enter two strings:"))
File "<string>", line 1, in <module>
NameError: name 'abc' is not defined
>>> a=eval(input("Enter a list:")) #Read a list
Enter a list:[1,2,3,4,5]
>>> print(a)
[1, 2, 3, 4, 5]
>>> a=eval(input("Enter a tuple:")) #Read a tuple
Enter a tuple:(1,2,3)
>>> print(a)
(1, 2, 3)
>>> a=eval(input("Enter a set:")) #Read a set
Enter a set:{1,2,3,2,3}
>>> print(a)
{1, 2, 3}
>>> a=eval(input("Enter a dictionary:")) #Read a dictionary
Enter a dictionary:{1:'One',2:'Two'}
>>> print(a)
{1: 'One', 2: 'Two'}
99
3.9.5 The print Function
The print () function writes the data on the console or other output device, such as
a printer. However, we will limit our discussion in this section to print only on the console.
The syntax and its parameters are given in table 3.9. The print () function can have zero or
more expressions separated by commas. The output can be formatted using the additional
parameters. Example 3.24 illustrates some uses of the print () function.
Syntax:
Parameters:
2. sep: it specifies the character to be used to separate the outputs of the expressions. It
is optional, and the default separator is a space character.
3. End: it specifies what to print at the end of the last expression output. It is optional,
and the default setting is to print a newline character, '\n', at the end.
4. file: It specifies the output device where the output is written. It is optional, and, by
default, the output is written on the console, i.e. sys.stdout.
5. flush: The flush parameter is a Boolean. If flush = True, the output is flushed; else,
the output is buffered. It is optional, and the default value is False.
100
>>> print(1+2,3*4,'Hello',[1,2,3]) #Print different types of data
3 12 Hello [1, 2, 3]
>>> #Print with a specified separator
>>> print(1+2,3*4,'Hello',[1,2,3], sep=',')
3,12,Hello,[1, 2, 3]
>>> a,b,c=1,{1,2,3},{1:"One",2:"Two"}
>>> print(a,b,c,sep=':') #Print variables
1:{1, 2, 3}:{1: 'One', 2: 'Two'}
>>> #Print with the default end character, i.e. a newline character.
>>> print("Hello");print("World"); print("I like Python")
Hello
World
I like Python
>>> #Print the specified character at the end
>>> print("Hello World.", end=' ');print("I like Python.")
Hello World. I like Python.
>>> x=print("Hello") #The print function returns nothing.
Hello
>>> print(x)
None
101
3. the format () method of the str class, and
4. Python’s f-string.
1 0b1 1.000
2 0b10 0.500
3 0b11 0.333
4 0b100 0.250
The % operator is used to format a Python data item as a string. For example, the
expression "%8.2f"%(1/3) will convert the value of the expression 1/3 into an equivalent
string of 8 characters with two digits after the decimal point, i.e., ' 0.33', in place of its
default value of 0.3333333333333333. In this way, we can control the printing width,
alignment, and the number of digits after the decimal point, i.e., precision. The syntax of the
% format operator is given in table 3.10.
Syntax:
102
"%Formatting string"% expression
Parameters:
Type Description
i The same as d.
103
x To convert an integer into a lowercase hexadecimal integer string.
g To convert a float number into a decimal float string using either the
decimal notation or the exponential notation, depending on the exponent
value. If the exponent value is >6 or < -4, it uses the exponential format
(using small case e); else, it uses the decimal form.
G To convert a float number into a decimal float string using either the
decimal notation or the exponential notation, depending on the exponent
value. If the exponent value of the number is >6 or < -4, it uses the
exponential format (using capital case E); else, it uses the decimal form.
R To convert any python object into the equivalent string using the repr()
function.
S To convert any python object into the equivalent string using the str()
function.
Flag Description
104
# It is with the type parameters o, x, or X to include 0o, 0x, or 0X,
respectively, as a prefix in the converted string
- By default, the converted string is the right justified in the specified width.
The – flag forces the converted string to be left-justified.
>>> a,b,c,d=10,-10,22/7,"Python"
>>> print(a,b,c,d) #Default
10 -10 3.142857142857143 Python
>>> print("%5d"%a,"%5d"%b,"%8.3f"%c,"%8s"%d) #Formatted
10 -10 3.143 Python
>>> print("%-5d"%a,"%-5d"%b,"%-8.3f"%c,"%-8s"%d) #Left justified
10 -10 3.143 Python
>>> print("%+5d"%a,"%#5X"%b,"%8.3e"%c,"%8s"%d) #Include + sign
+10 -0XA 3.143e+00 Python
>>> print("%#05o"%a,"%05d"%b,"%08.3f"%c,"%8s"%d) #Octal, binary
0o012 -0010 0003.143 Python
>>> print("%G"%1234,"%G"%1234567) #Auto choose e or f
1234 1.23457E+06
>>> print("%G"%(1/1234),"%G"%(1/1234567)) #Auto choose e or f
0.000810373 8.10001E-07
105
>>> print("%s"%[1,2,3,4,5]) #Convert list to a string
[1, 2, 3, 4, 5]
The format () function can be used to format only a single numeric or string data.
The syntax of the format function is given in table 3.13.
Syntax:
Parameters:
2. “formatting string”: a string that describes how to format the value of the
expression.
Return value:
A formatted string.
Option Description
< The output string is left-aligned within the specified width. By default, string
data are left-aligned and numeric data are right aligned.
0 The leading spaces in the output string of a numeric value is padded with 0.
>>> a,b,c,d=10,-10,22/7,"Python"
107
>>> print(a,b,c,d)
10 -10 3.142857142857143 Python
>>> print(format(a,"5d"),format(c,"8.3f"),format(d,"8s"))
10 3.143 Python
>>> print(format(a,"<5d"),format(b,"05d"),format(c,"<8.3f"))
10 -0010 3.143
>>> print(format(a,"5x"),format(b,"5o"),format(a,"8b"))
a -12 1010
>>> print(format(a,"05x"),format(b,"05o"),format(a,"08b"))
0000a -0012 00001010
>>> print(format(a,"#5x"),format(b,"#5o"),format(a,"#8b"))
0xa -0o12 0b1010
>>> print(format(a,"#05x"),format(b,"#05o"),format(a,"#08b"))
0x00a -0o12 0b001010
>>> a,b=12345678, 123456789.12345
>>> print(format(a,",d"),format(b,",f"))
12,345,678 123,456,789.123450
>>> c="Python"
>>> print(format(c,"<15s"),format(c,">15s"),format(c,"^15s"),
sep=':')
Python : Python: Python
>>> print(format(-123,"010d"))
'-000000123'
From Python 2.6, Python added the format () method to the str class to format
different types of data as a string object more elegantly and conveniently. The syntax of the
format () method is given in table 3.15.
108
Syntax:
Parameters:
1. template: a string object or a string literal which is used as a formatting string. The
template string contains fields that are replaced by the corresponding arguments
in the format method. A field is defined by enclosing the position index of a
positional argument or the key value of a key-value argument within a pair of curly
brackets. A field also contains formatting instruction separated by a colon with the
filed label.
2. p0,p1, …, positional arguments, which will replace the corresponding fields in the
template string.
3. k0=v0, k1=v1, …, key=value pairs are for the additional arguments. The key=value
arguments can be referred to in the template by their key values. Please remember,
key-value arguments will appear only after all the positional arguments.
Return value:
A formatted string.
The template string used for formatting purposes has special structures called fields.
Fields are embedded at various locations where we want to insert the formatted data. A
field is created by a pair of curly braces {}, and it contains a reference to an argument of the
format method and its formatting codes. A field in a template string has the following two
formats: {index: formatting code}, or {key: formatting string}, where the index is the
position index (reference) of the positional arguments in the format function, the key is the
key of a key-value argument, and the formatting code is the formatting instructions. Both
the reference and formatting codes are optional.
109
The expression "{name} is {age} years old".format(name="John", age=10) produces the
output 'John is 10 years old'. Here, the keys are replaced by the corresponding values.
We can specify references in any order in a template string. For example, the
expression "{2},{0},{1}".format(12,34.5,"Python") produces the output 'Python,12,34.5'. We
can repeat a reference. For example, the expression "{2},{2},{2}".format(12,34.5,"Python")
produces the output 'Python,Python,Python'. When we give argument references in the
fields, it is called manual referencing. The above examples use manual referencing.
If references in fields are not given, the first field is mapped to the first argument;
the second field is mapped to the second argument, and so on. This referencing style is
called automatic referencing. For example, the expression "{},{},{}".format(12,34.5,"Python")
produces the output '12,34.5,Python'. Please note, we cannot mix the manual and automatic
referencing. This mixing is an error. However, we can mix the automatic referencing of the
positional arguments and the key referencing. For example, in the expression
"{},{key1},{},{key2},{}".format(1,2,3,key1=4, key2=5), the blank fields are automatically
mapped with the positional arguments, in sequence and the key references are mapped to
the key arguments. The expression produces the output '1,4,2,5,3'. Similarly, we can mix the
manual referencing with the key referencing. For example, the expression
"{1},{key1},{2},{key2},{0}".format(1,2,3,key1=4, key2=5) produces the output '2,4,3,5,1'.
The parts of the string outside the fields are included in the output string without
any change. So, for example, the expression "I love {} programming".format("Python")
produces the output 'I love Python programming'.
A brace character is included in the output string by doubling it, i.e. {{ or }}. For
example, the expression "{{I love {}}}".format("Python") produces the output '{I love
Python}'.
110
>>> "{},{},{}".format(12,34.5,"Python") #Auto indexing
'12,34.5,Python'
>>> "{2},{1},{0}".format(12,34.5,"Python") #Randomised
'Python,34.5,12'
>>> "{0:4d},{1:8.3f},{2:10s}".format(12,34.5,"Python") #Formatting
code
' 12, 34.500,Python '
>>> "Value of {0} in binary:{0:04b}, in
hexadecimal:{0:#04X}".format(23)
'Value of 23 in binary:10111, in hexadecimal:0X17'
>>> "Value of {0} in binary:{0:08b}, in
hexadecimal:{0:#08X}".format(23)
'Value of 23 in binary:00010111, in hexadecimal:0X000017'
>>> "Left:{0:<15s}, Center:{0:^15s} and
Right:{0:>15s}".format("Python")
'Left:Python , Center: Python and Right:
Python'
>>> "{},{key1},{},{key2},{}".format(1,2,3,key1=4, key2=5)
'1,4,2,5,3'
111
Example 3.29: f- strings
name = 'John'
height = 1.72
weight = 75
#Embedding variables and expressions in a string literal
print(f"Hello, I am {name}. My BMI is {weight/(height*height)}")
Output
Hello, I am John. My BMI is 25.351541373715524
a=10.2 #A float
b=20 #An integer
c="abc" #A string
#Formatting a float, an integer and a string in an f-string
print(f"Float:{a:8.2f}\nInteger:{b:6d}\nString:{c:>10s}")
Output
Float: 10.20
Integer: 20
String: abc
112
import math
x=3
#Calling a function inside a f-string
print(f"The sqrt of {x} is {math.sqrt(x):8.3f}")
Output
The sqrt of 3 is 1.732
We can include symbols such as a double quotation mark ("), a single quotation
mark ('), a slash (\) by using the escape sequence, and a curly bracket is included by
doubling it. Other brackets require no special treatment. Example 3.32 illustrates this.
When using dictionary elements in an f-string, we must use proper quotation marks
to begin and end an f-string. If dictionary keys and values are defined using single quotation
marks, we must begin and end an f-string with a double quotation mark and vice versa.
Example 3.33 illustrates this.
113
Output
I am John. My age is 50.
Chapter Summary
1. Python 3.0 and newer versions support Unicode characters to name identifiers.
2. A token is the smallest unit of a computer program. Tokens are the building blocks
of computer expressions and statements.
3. Keywords are reserved words and have predefined meaning in programs.
4. Python identifiers can be of any length and can include Unicode characters.
5. A literal in a program is a fixed value that does not change during the execution of
a program. Python supports the following literal types: int, float, complex, str,
bytes, bool, NoneType, list, tuple, dict, and set.
6. A Python string literal can be created by enclosing characters in a pair of single
quotes, double quotes, triple single quotes, or triple-double quotes. However, if we
start with a single quote, it must end with a single quote.
7. Python supports the processing of integers, floats, and complex numeric values.
8. A Python integer can have any number of digits.
9. We can directly use binary, octal, decimal, and hexadecimal integers and their
combinations in an expression.
10. Python creates a complex number by adding a floating literal with an imaginary
literal.
11. Python has four different types of collection literals: List, Tuple, Dict, and Set.
12. A list is a mutable collection, whereas a tuple is an immutable collection
13. Lists, sets, and dictionaries cannot be used as a key in a dictionary.
14. A set is an unordered collection of items.
15. Python has operators to perform arithmetic, relational, logical, bitwise,
assignment, membership, and identity operations.
16. The input function always returns the read data as a string.
17. The eval function is used to execute Python commands contained in a string.
18. The print function is used to print data on the console.
19. We can format the output of an expression by the % operator, format function,
format method of the str class, and f-string.
114
Multiple Choice Questions
115
(c) Tuple
(d) Class
8. Which of the following is a literal in Python?
(a) String
(b) Complex
(c) Tuple
(d) All of the above
9. Which of the following is not a valid string literal in Python?
(a) 'This is a string literal.'
(b) "This is a string literal."
(c) """This is a string literal."""
(d) None of the above
10. Which of the following escape sequence is used to include a Unicode in a
string? Here, x is a hexadecimal digit.
(a) \N{name}
(b) \uxxxx
(c) \Uxxxxxxxx
(d) All of the above
11. Which of the following is an invalid integer literal in Python?
(a) 100
(b) 1_0_0
(c) 0100
(d) 0o100
12. Which of the following literals can be directly used in a Python expression?
(a) 0x100
(b) 100
(c) 0b100
(d) All of the above
13. Which of the following is an invalid float literal in Python?
(a) 1.23_4e1_2
(b) 1.234e12
(c) 1.234e 12
(d) None of the above
14. Which of the following is an invalid complex literal in Python?
(a) 4+5j
116
(b) 5j+4
(c) 4+j5
(d) 4-3j
15. Which of the following is not a Boolean literal?
(a) True
(b) False
(c) None
(d) None of the above
16. Which of the following is a valid list literal?
(a) [1, 2, 3, 'Four', 'Five']
(b) [1, 2, 3, 4, 5]
(c) [[1,2,3], [4,5]]
(d) All of the above
17. Which of the following is an invalid tuple?
(a) (1, 2, 3, 4, 5)
(b) ([1, 2, 3], [4,5])
(c) ()
(d) None of the above
18. Which of the following cannot be used as a key in a dictionary?
(a) Tuple
(b) Integer
(c) List
(d) Complex
19. Which of the following is an invalid set?
(a) {1, 2, 3, 4}
(b) {[1, 2, 3], [4, 5]}
(c) {(1, 2, 3), (4, 5)}
(d) {True, False}
20. Which of the following is equal to None in Python?
(a) Zero
(b) ""
(c) [ ]
(d) None of the above
21. Which of the following is not an operator in Python?
(a) add
117
(b) and
(c) is
(d) in
22. Which of the following can be returned by the input function?
(a) Integer
(b) Float
(c) String
(d) All of the above
23. Which of the following can be printed by the print () function?
(a) Number
(b) String
(c) List
(d) All of the above
24. The number of digits after the decimal point in the output of the expression
"%8.2f"%(1/3) is ___.
(a) 3
(b) 2
(c) 0
(d) None of the above
25. Which of the following can be used to format the output of an expression?
(a) % operator
(b) f-string
(c) The format () method
(d) All of the above
Review Questions
118
g. There is no special meaning of a backslash character in a raw string.
h. Python does not support the processing of complex numbers.
i. There are only two Boolean literals in Python.
j. A list is an immutable data.
k. A set can be used as a key in a dictionary.
l. A set is an ordered collection of numbers.
m. The input () function can return an integer.
n. The eval () method can be used to execute any valid Python
command contained in a string.
o. f-string is used to format a string.
2. Describe various types of Python tokens.
3. What is the purpose of keywords? List ten keywords along with their uses.
4. Describe Python identifier naming rules.
5. Describe various types of integer representation supported by Python.
6. Describe methods to create complex literals.
7. Describe various collection literals available in Python.
8. Differentiate list and tuple.
9. Describe various delimiters used in Python.
10. Describe the input () function.
11. Describe how to read multiple integers separated by a delimiter using an
input function.
12. Describe the eval () function
13. Describe the print () function.
14. Describe different methods to format output in Python.
15. Describe the f-string in Python.
Programming Exercises
1. Write a program to read a number from the keyboard and calculate its inverse
and print the result that contains three digits after the decimal point.
2. Write a program to read three numbers (a, b, c) and evaluate the expression
X=a/(b**2 –c).
Print the output in the scientific notation.
3. Print Greek symbols (alpha, beta, gamma, and lambda) using Unicode.
119
4. Write a program to find the speed of a car when distance and time are given.
First, the program will read the distance (in meters) and the time (in seconds)
from the keyboard. Then, print the formatted output on the console with two
digits after the decimal point.
5. Write a program to display the following pattern using a single print
statement:
*****
*
*
*****
6. Write a program to compute x^y for x=3.5 and y=3.5. Print the formatted
output with four digits after the decimal.
7. Write a program, which asks a user to enter his name, age, address, and
hobby and print the following sentence:
My name is [name]. I am [age] old and live at [address]. I love [hobby].
8. Write a program to convert the temperature given in Fahrenheit to Celsius
(use the formula c=(F-32)/1.8.
9. Read an integer and print it in binary, octal, and hexadecimal format.
10. Write a program to read two integers and perform the following arithmetic
operations: addition, subtraction, multiplication, and division.
11. Write a program to read three numbers and find their average.
12. Write a program to convert meters into inches.
13. Write a program to calculate the surface area and volume of a cylinder with
the given height and radius values.
14. Write a program that calculate the number of seconds in a leap year.
15. Write a program to read two complex numbers from the keyboard and find
their sum and product.
120
121
Chapter 4
4.1 Operators
Operators are symbols used to perform operations on variables and values. For
example, in the expression 10+20, the + sign is an operator and performs the addition of 10
and 20. The values 10 and 20 are called operands. Python has a rich set of operators for
performing various operations on data. It has built-in support for the following types of
operators for numeric data:
1. Arithmetic Operators
2. Comparison (Relational) Operators
3. Logical Operators
4. Bitwise Operators
5. Assignment Operators
6. Membership Operators
7. Identity Operators
122
or an expression. The operands can be integers, floats, complex numbers, and Booleans for
addition, subtraction, multiplication, division, and exponent operators. However, for the
floor division and modulus operators, complex numbers are not allowed. Python allows the
floor division and modulus operations with float operands. Table 4.1 lists all the arithmetic
operators along with their brief descriptions. Example 4.1 illustrates these operators.
Example 4.2 shows the arithmetic operators on float numbers, example 4.3 on complex
numbers, and example 4.4 on Boolean values.
In arithmetic operations, both operands need not be of the same numeric type, i.e.,
one operand can be an integer number while the other can be a float or complex or Boolean
number. In such a hybrid expression, the lower precision numeric operand is upgraded to
the higher precision operand, and the result is of the higher precision type. The order of
precision up-gradation in Python is Boolean, integer, float, and complex. For example, if we
add an integer with a float, the integer is upgraded to the float type, and the result is the
float type. Similarly, if we add a Boolean data with a float data, the Boolean is upgraded to
the float type, and the result is the float type. Example 4.5 shows the above concepts.
123
// Floor division Divides the left operand by the right operand and returns
the largest possible integer, but less than or equal to the
normal division result. The operands can be integer, float,
or Boolean. They can be positive or negative. However,
the zero denominator raises division by zero error.
Complex numbers are not allowed.
% Modulus Divides the left operand by the right operand and returns
the remainder of the division. The operands can be
integer, float, or Boolean. They can be positive or negative.
However, the zero denominator raises division by zero
error. Python uses the following mathematics to calculate
the modulus (a%b)= a-(a//b)*b. Complex numbers are not
allowed.
124
>>> print(a%b) # Modulus division. Returns reminder.
1
>>> print(c%b)
2
>>> print(a**b) # Exponent operation.
343
>>>
>>> a=5.2
>>> b=2.2
>>> print(a+b)
7.4
>>> print(a-b)
3.0
>>> print(a*b)
11.440000000000001
>>> print(a/b)
2.3636363636363633
>>> print(a//b)
2.0
>>> print(a%b)
0.7999999999999998
>>> print(a**b)
37.601689251649596
>>>
>>> a=2+3j
>>> b=3+5j
>>> print(a+b)
(5+8j)
>>> print(a-b)
125
(-1-2j)
>>> print(a*b)
(-9+19j)
>>> print(a/b)
(0.6176470588235294-0.02941176470588238j)
>>> print(a**b)
(-0.34349061841848877+0.022021533303860297j)
>>> print(a%b) # Error: Modulus operation is not defined for complex
Traceback (most recent call last):
File "<pyshell#153>", line 1, in <module>
print(a%b)
TypeError: can't mod complex numbers.
>>> print(a//b) # Error: floor division is not defined for complex
Traceback (most recent call last):
File "<pyshell#154>", line 1, in <module>
print(a//b)
TypeError: can't take floor of complex number.
>>> a=True
>>> b=False
>>> print(a+b)
1
>>> print(type(a+b))
<class 'int'>
>>> print(a-b)
1
>>> print(a*b)
0
>>> print(a/b) # Error: The numeric value of False is zero.
Traceback (most recent call last):
File "<pyshell#161>", line 1, in <module>
print(a/b)
ZeroDivisionError: division by zero
>>> print(b//a)
0
126
>>> print(b%a)
0
>>>
>>> a=3
>>> b=5.5
>>> c=2+3j
>>> d=True
>>> print(type(a+b),type(a+c), type(a+d)) # Note: Type conversion
<class 'float'> <class 'complex'> <class 'int'>
>>> print(c*a,c*b,c*d)
(6+9j) (11+16.5j) (2+3j)
>>> print(c**a,c**b,c**d)
(-46+9j) (739.1447590698494-890.1578370493768j) (2+3j)
>>> print(a**c,b**c,d**c)
(-8.893151344279719-1.38269995578789j) (11.83157699398098-
27.840191914487587j) (1+0j)
>>> print(b**c,d**c)
(11.83157699398098-27.840191914487587j) (1+0j)
>>> e=c//a # Error: Floor division note defined for complex
Traceback (most recent call last):
File "<pyshell#173>", line 1, in <module>
e=c//a
TypeError: can't take floor of complex number.
>>> e=c%b # Error: Modulus operation not defined for complex
Traceback (most recent call last):
File "<pyshell#174>", line 1, in <module>
e=c%b
TypeError: can't mod complex numbers.
>>>
127
4.1.2 Relational (Comparison) Operators
A relational operator compares the left operand with the right operand for the
specified condition and returns either True or False. For example, the expression 10<20
returns True, and the expression 10>20 returns False. Python has six relational operators:
less than (<), less than or equal to (<=), greater than (>), greater than or equal to (>=),
equal to (==), and not equal to (!=) (See table 4.2). For the >, <, >= and <= operators,
operands can be of integer, float, Boolean, string, list, tuple, set, and dict types. These
comparison operators are not defined for complex operands. However, the == and !=
operators are defined for all the Python data, i.e., operands can be integer, float, complex,
Boolean, string, list, tuple, dict, set, and NoneType. Comparison operators for string, list,
tuple, set, and dict types are discussed later in the book. Example 3.6 illustrates the
comparison operators for numeric and Boolean operands.
> Greater than Returns True if the left operand is greater than the right
< Less than Returns True if the left operand is less than the right
== Equal to Returns True if the left and the right operands are equal
!= Not equal to Returns True if the left operand is not equal to the right
>= Greater than Returns True if the left operand is greater than or equal to
or equal to the right
<= Less than or Returns True if the left operand is less than or equal to the
equal to right
>>> a=3
>>> b=4
>>> d=3
>>> e=2+3j
128
>>> f=3+2j
>>> print(a==b) # Equal to
False
>>> print(a==d)
True
>>> print(a<b) # Less than
True
>>> print(a>b) # Greater than
False
>>> print(a<=b) # Less than or equal to
True
>>> print(a<=d) # Less than or equal to
True
>>> print(a>=b) # Greater than or equal to
False
>>> print(True==False) # Comparing Boolean data
False
>>> print(a!=b) # Not equal to
True
>>> print(e==f) # Comparing complex numbers
False
>>> print(e!=f) # Comparing complex numbers
True
>>> print(2+3j==2+3j) # Comparing complex numbers
True
>>> print(2+3j <2+3j)#Error: < is not defined for complex numbers.
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
print(2+3j <2+3j)
TypeError: '<' not supported between instances of 'complex' and 'complex'
Logical operators perform logical AND, OR, and NOT operations and are primarily
used for combining relational operations. For example, the expression 1<2 and 3<4 returns
True, whereas the expression 1>2 and 3>4 returns False. Table 4.3 lists the three logical
operators of Python and their truth table.
129
Logical operators can have operands of any datatype. In a logical Python expression,
the numeric value 0, the complex number 0+0j, an empty string "", empty list [], empty tuple
(), empty set {}, and empty dict dict() are treated as False, and all other values of these data
types are treated as True. For example, the expression bool ("") evaluates to False, and the
expression bool ("ABC") evaluates to True.
We can chain different relational operators to any length. For example, x1 op1 x2
op2 x3 … xn-1 opn xn is equivalent to x1 op1 x2 and x2 op2 x3 and … xn-1 opn xn, where
op1, op2…opn can be any relational operator.
130
or Logical OR Evaluates to True if either of the operand is True, else False.
The truth table of the logical or operation is as given below:
Operand result
False True
True False
131
0 <class 'str'>
>>> type(4 and '') #The second operand is returned
<class 'str'>
>>> type('' or []) #The second operand is returned
<class 'list'>
>>> 10<20<30 #Chained logical expression
True
>>> 10<20>15 #Chaining different relational operators
True
>>>
Bitwise operators perform various operations at bit level on the integer and Boolean
operands. For bitwise operations, Boolean True is treated as 1, and Boolean False is treated
as 0. These operations are not defined for the float, complex number, string, list, tuple, set,
dict, and NoneType operands. Python supports the following bitwise operations: AND, OR,
NOT, XOR, left shift, and right shift, shown in Table 4.4. Table 4.5 shows the truth table of
various logical bitwise operations. Table 4.6 shows the concepts of bitwise shift operations.
Since Python does not use a fixed number of bits to store an integer, the bitwise left
shift will increase the number of bits in the result. For example, the expression
bin(0b111<<2) produces '0b11100', where the number of digits in the original number is 3,
whereas, in the output, it is 5. Similarly, the bitwise right shift will decrease the number of
bits. For example, the expression bin(0b11111>>2) produces '0b111', where the number of
digits in the original number is 5, whereas, in the output, it is 3.
Further, for bitwise logical operations, the number of bits in both the operands is
made equal before performing the operation by adding leading zeros to the shorter
operand. Finally, the leading zeros in the result are removed. Example 4.8 illustrates the
above concepts.
132
| Bitwise OR Performs bitwise logical OR operations on the
corresponding bits of the integer operands.
~ Bitwise NOT Performs bitwise logical NOT operations on the
individual bits of the integer operand.
^ Bitwise XOR Performs bitwise logical exclusive OR(XOR)
operations on the corresponding bits of the integer
operands.
>> Bitwise right shift Shifts the specified number of bits of the first operand
toward the right. The number of bits to be shifted is
defined by the second parameter.
<< Bitwise left shift Shifts the specified number of bits of the first operand
toward the left and adds the same number of trailing
zeros. The number of bits to be shifted is defined by
the second parameter.
133
Example 4.8: Bitwise operators
>>> a=7
>>> b=11
>>> print(bin(a), bin(b)) # The bin(x) function prints x as a binary
string
0b111 0b1011
>>> print(bin(a&b)) # Bitwise logical and operation
0b11
>>> print(bin(a|b)) # Bitwise logical or operation
0b1111
>>> print(bin(a^b)) # Bitwise logical exclusive or operation
0b1100
>>> #Note the result, it is negative as the sign bit is also flipped.
>>> print(bin(~a), bin(~b)) # Bitwise logical not operation
-0b1000 -0b1100
>>> print(bin(a<<2)) # Bitwise left shift operation
0b11100
>>> print(bin(b>>1)) # Bitwise right shift operation
0b101
The simple assignment operator ( = ) assigns values to variables. The values can be
literals, variables, or expressions. For example, in x=5, the value 5 is assigned to x. The
simple assignment operator can assign values to more than one variable. For example, in x,
y = 5, 3+4, the value 5 is assigned to x, and the output of 3+4, i.e., 7, is assigned to y. When
we assign more than one value to a variable, the values are assigned to the variable as a
tuple. For example, the statement x=1, 2, 3 is equivalent to x=(1, 2, 3). However, when we
assign multiple values to multiple variables, the number of variables must be equal to the
number of values; otherwise, an unpacking error will be generated. For example, the
statement x, y =1, 2, 3 will generate an error. The unpacking error can be avoided by using
dummy variables. For example, the statement x, y, _=1, 2, 3 sets x=1, y=2 and _=3. The
underscore ( _ ) is frequently used as a dummy variable. We can have any number of
dummy variables in a multiple assignment to avoid unpacking errors, for example, x, y, _,
_=1, 2, 3, 4.
In addition to the simple assignment operator (=) given above, Python has many
compound assignment operators that combine other operations with an assignment. For
example, in x+=5, the value 5 is added to the current value of x. Thus, the previous statement
134
is equivalent to x=x+5. Unlike the simple assignment operation, a compound assignment
operation can have one variable and one value. For example, the statement x, y += 2, 3 is
an error. Table 4.7 lists all the assignment operators that are available in Python. Example
4.9 and example 4.10 show some uses of various assignment operators.
135
%= Modulus and assign x%y, this is equivalent to x=x%y. Here, the %
operator is used as the arithmetic modulus operator.
136
>>> d=1,2,3 # Assign multiple values to a single variable. d is a tuple.
>>> print(a,b,c,d)
5 6 7 (1, 2, 3)
>>> a+=b # Add and assign
>>> print(a)
11
>>> b-=2 # subtract and assign
>>> c*=3 # Multiply and assign
>>> print(b,c)
4 21
>>> a**=4 # Exponent and assign
>>> print(a) # a uses the latest value, i.e., a=11
14641
>>> c%=b # Modulo and assign
>>> print(c)
1
>>> a=5.5
>>> b=2.2
>>> a//=b # Floor division and assign
>>> print(a)
2.0
>>> e=2+3j
>>> f=3+7j
>>> e+=f # Add and assign complex numbers
>>> print(e) #Print the modified value of e
(5+10j)
>>> e-=f #Subtract and assign complex numbers
>>> print(e) #Print the modified value of e
(2+3j)
>>> e*=f #Multiply and assign complex numbers
>>> print(e) #Print the modified value of e
(-15+23j)
>>> e/=f #Divide and assign complex numbers
>>> print(e) #Print the modified value of e
(2.0000000000000004+3j)
>>> e%=f #Error: Complex numbers are not permitted in modulus
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
e%=f
137
TypeError: can't mod complex numbers.
>>> e//=f #Error: Complex numbers not permitted in floor division
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
e//=f
TypeError: can't take floor of complex number.
>>> a=True
>>> b=2
>>> a+=b #Boolean is permitted
>>> print(a)
3
>>> a,b=3,7
>>> print(bin(a), bin(b)) #Print numbers in binary format
0b11 0b111
>>> a&=b #Bitwise logical AND and assign
>>> print(bin(a))
0b11
>>> a|=b #Bitwise logical OR and assign
>>> print(bin(a))
0b111
>>> a^=0b101 #Bitwise logical XOR and assign
>>> print(bin(a))
0b10
>>> b<<=2 #Bitwise left shift and assign
>>> print(bin(b))
0b11100
>>> b>>=1 #Bitwise right shift and assign
>>> print(bin(b))
0b1110
138
[step=1]) method generates a sequence of numbers starting from the start up to the end
with the step size of the step. The default values of start is 0 and step is 1. For example, the
expression range(1,10) returns the sequence 1,2,…,9.
There are two membership operators in Python: in and not in. The in operator
checks for the presence. For example, the expression 3 in [1,2,3] returns True, but the
expression 4 in [1,2,3] returns False. Whereas the not in operator checks for the absence.
For example, the expression 3 not in [1,2,3] returns False, but the expression 4 not in [1,2,3]
returns True. They are listed and explained in Table 4.8. Example 4.11 shows the uses of
these operators for various collections and sequences.
139
>>> print(1 in d, 10 in d, 2 not in d, 10 not in d) #Check the
existence of an item in a set
True False False True
>>> e={1:'One',2:'Two', 3:'Three'}
>>> print(1 in e, 4 in e, 1 not in e, 4 not in e) #Check the existence
of a key item in a dict.
True False False True
>>> print( 'One' in e) #Cannot check the value items in a dict. Hence,
false.
False
>>> f=range(10) #Creating a range object.
>>> print(2 in f, 12 in f, 2 not in f, 12 not in f) #Check the
existence of an item in a range.
True False False True
>>> print([1,2,3] in b) #Cannot check a sub list. Hence, false.
False
>>> print((1,2) in c) #Cannot check a sub-tuple. Hence, false.
False
>>> print( {1,3} in d) #Cannot check a subset. Hence, false.
False
In Python, we can refer to the same data with more than one variable. For example,
in the statements x=[1, 2, 3, 4] and y=x, both x and y refer to the same list in the memory,
i.e., it creates a shallow copy. Python does not allocate different memory in a shallow copy.
In shallow copy, modifying one variable will change the value of all other aliases as there is
only one copy of the actual data in memory. For example, in L1=[1,2,3], L2=L1, L1 and L2
refer to the same list, i.e. [1,2,3]. The same is true of other collection data types, such as tuple,
dict, set.
Further, the Python interpreter creates only one copy of data if we create two
identical literals of numeric, string, or Boolean types. For example, for x=5 and y=5, the
Python interpreter will create only one copy of the literal 5, and both x and y will refer to it.
However, the Python interpreter will create separate objects for the identical literals of list,
tuple, set, and dict types. For example, list1 = [1,2,3], list2 = [1,2,3] will create two separate
objects in memory. Similar is true for the other collection data types.
140
Identity operators check whether two variables refer to the same object in the
memory or not. There are two identity operators: is and is not. The is operator returns True
if both operands refer to the same object in the memory; otherwise, it returns False. For
example, with x=10; y=x, the expression x is y returns True. The is not operator does the
opposite of the is operator. For example, the expression x is not y returns False. Table 4.9
lists identity operators, and Example 4.12 illustrates some uses of the identity operators.
Operator Description
is Returns True if both operands refer to the same object in the memory,
i.e., both operands are alias of each other, otherwise returns False.
is not Returns True if both operands refer to two different objects in the
memory, otherwise returns False.
#For identical, atomic and string literal values, only one copy is
created in the memory
>>> x1, y1=5, 5
>>> x1 is y1
True
>>> s1, s2="Hello", "Hello"
>>> s1 is s2
True
>>> s3="hello"
>>> s1 is s3
False
>>> s1 is not s3
True
>>> #For collection literals, different objects are created in the
memory
>>> l1, l2 =[1,2,3], [1,2,3]
>>> l1 is l2
False
>>> l3=l1 #Shallow copy. No separate memory allocated.
>>> l1 is l3
True
>>> t1, t2 =(1,2,3), (1,2,3)
>>> t1 is t2
141
False
>>> t3=t1 #Shallow copy. No separate memory allocated.
>>> t1 is t3
True
>>> st1, st2 = {1,2,3}, {1,2,3}
>>> st1 is st2
False
>>> st3=st1 #Shallow copy. No separate memory allocated.
>>> st1 is st3
True
>>> d1, d2 = {1:'One',2:'Two'}, {1:'One',2:'Two'}
>>> d1 is d2
False
>>> d3=d1
>>> d1 is d3
True
4.2 Expressions
An expression is a combination of variables, functions, constants, and operators, as
per the programming language's syntax, and evaluates to a value. When we assign the
result of an expression to a variable, it is called a statement. For example, 10+20 is an
expression, whereas x=10+20 is a statement. Based on the type of the expression result, an
expression can be classified as an arithmetic expression, string expression, and logical
expression. An arithmetic expression returns a single numeric value; a string expression
returns a string value, and a logical (also called relational) expression returns a single logical
value. For example, 2+3 is an arithmetic expression, "Python"+" Programming" is a string
expression, and 2>3 is a logical expression, as they return a numeric (5), string ('Python
Programming'), and logical (False) values, respectively.
142
operator precedence and associativity rules are used, explained later in this chapter; see
section 4.3.
143
>>> (a+b)/(c-d)
-2.5714285714285707
>>> x,y=2.6,3.4
>>> x/y+a/b
1.2047058823529413
>>> a,b,c,d=2+3j,2-3j,3+5j,4+5j #Complex operands
>>> a+b-c*d
(17-35j)
>>> (a+b)*(c+d)
(28+40j)
>>> (a+b)/(c-d)
(-4-0j)
>>> x,y=2j,3+2j
>>> x/y+a/b
(-0.07692307692307693+1.3846153846153846j)
144
𝑥=𝑦 x==y
"ABC" < "𝑋𝑌𝑍" "ABC" < "XYZ"
>>> x,y,z=1,5,9
>>> x<=y
True
>>> x>y
False
>>> x<=y and x<z #True as both relational expressions are true
True
>>> x<=y and x> z
False
>>> x+y <=x+2 #Arithmetic expressions are evaluated first
False
>>> x+y >=x+2
True
>>> x<=y<=z
True
>>> x==y
False
>>> #Strings are compared based on their characters' Unicode values
>>> "abc"<"ABC"
False
>>> "abc">"ABC"
True
>>> "क"< "ख" #Strings can consist of any Unicode characters
True
>>> "क" > "ख"
False
>>> "α" <"β" #Strings can consist of any Unicode characters
True
>>> "α" > "β"
False
A string expression combines string literals, string variables, and functions using
string operators (concatenation (+) and product (*)) and returns a string. The concatenation
operator (+) combines the left and right strings. For example, the expression "Python" +
145
"Programming" returns 'PythonProgramming'. Please note that there is no separator used
during concatenation. To properly concatenate strings, add a separator if required; for
example, "Python" +" "+ "Programming" evaluates to 'Python Programming'.
The product operator (*) repeats a string by a specified time. For example, the expression
"Python" * 3 returns 'PythonPythonPython'. We can use both concatenation and product
operators in an expression. For example, the expression "Python is " + "very "*3 + " good."
returns 'Python is very very very good.' Example 4.15 shows some examples of string
expressions.
146
Step 1: 4*5+2 (First operation: Multiplication (precedence level= 4))
Step 2: 20+2 (Second operation: Addition (precedence level = 5))
Step 3: 22
As can be seen from table 4.12, a group of operators has the same precedence level.
For example, the operators *, /, //, and % have the same precedence level. In this situation,
the order of evaluation of operators is decided by the associativity rule. The operator
associativity rule defines the direction of the evaluation of operators of a precedence level.
The direction of the evaluation of operators of the same level of precedence can be either
from left-to-right or from right-to-left. In the left-to-right associativity, the operator in the
left is evaluated first, whereas, in the right-to-left, the operator in the right is evaluated first.
The operators within the same precedence level will have the same associativity. The last
column of table 4.12 shows the associativity of the various precedence levels. For example,
in the expression 3 + 8 / 2 * 4, the precedence level of the division operator and the
multiplication operator is the same, but the associativity is from left to right. Hence,
division is performed before multiplication. The evaluation order of operators in the
expression is as given below:
The associativity can also to altered by using parentheses. For example, consider the
evaluation of the expressions 2**3**2 and (2**3) **2.
Step 1: 2**3**2 (First: The right exponent due the right-to-left associativity)
Step 2: 2**9 (Second: Exponent operator)
Step 3: 512
147
Step 1: (2**3)**2 (First: The left exponent operation due parenthesis)
Step 2: 8**2 (Second: Exponent operator)
Step 3: 64
148
>>> 5*2/3 #Order: *,/ due to the left to right associativity
3.3333333333333335
>>> 10 * 3 + (10 % 2) ** 3 #Order: %, **, *, +
30
>>> 45 % 2 - 5 / 2 + ( 9 * 3 - 2 ) #Order: *, -, %,/,-,+
23.5
>>> 5 + 24 / 2 * 4 #Order: /,*,+
53.0
>>> (2**3)**2 #Order: left ** and then right **
64
>>> 2**3**2 #Order: Right ** and then left **
512
149
'__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold',
'center', 'count', 'encode', 'endswith', 'expandtabs', 'find',
'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii',
'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric',
'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust',
'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix',
'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition',
'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip',
'swapcase', 'title', 'translate', 'upper', 'zfill']
>>>
Function Description
abs(num) It returns the absolute value of a number. It can be used for all numeric
data: integer, float, and complex numbers. For example, abs(-10)
returns 10, and abs(3+4j) returns 5.0.
all(itr) It returns True if all items in an iterable object are true. For example,
all([1,2,3,4,5]) returns True, whereas all([1,2,0,4,5]) returns False. It can
be used with all the collection data types: lists, tuples, sets, and
dictionaries.
any(itr) It returns True if any item in an iterable object is true, for example,
any([1,0,0,0,5]) returns True, whereas any([False,"",0,{}]) returns False.
It can be used with all the collection data types: lists, tuples, sets, and
dictionaries.
ascii(obj) It returns the readable ASCII version of any object, such as strings,
tuples, lists. The non-printable or invisible characters such as tab,
carriage return, form feed, and non-ASCII characters such as α, b, P
are replaced with equivalent escape sequence characters. For example,
ascii('α is a Greek symbol.') returns "'\\u03b1 is a Greek symbol.'",
where \\u03b1 is the escape sequence of α. Similarly, ascii(['α', 'β','γ'])
returns "['\\u03b1', '\\u03b2', '\\u03b3']" and ascii('\t\n\f\v\b')
returns "'\\t\\n\\x0c\\x0b\\x08'".
bin(num) It returns the binary representation of an integer number in a string
format. For example, bin(13) will return '0b1101'. The argument can be
given in any integer representation, such as decimal integer, octal
150
integer, hexadecimal integer, and binary integer. For example,
bin(0xFF) returns '0b11111111', bin(0o10) returns '0b1000', and
bin(0b1010) returns '0b1010'.
bool(obj) It converts an object into an equivalent Boolean value, i.e., True or
False. In python, 0, 0.0, 0+0j, an empty string, None, an empty list, an
empty tuple, an empty dictionary , an empty set and an empty range
are equivalent to False and all other values are True. Thus, bool(""),
bool(0), bool([]), bool(()), bool({}) and bool(None) all return False.
Whereas, bool("a"), bool(1), bool([1,2]), bool((1,4))and bool({1,2,3}) all
return True.
bytearray(obj) It returns an equivalent bytearray of an object. A bytearray is a mutable
array of bytes. In Python, the byte is an integer that can have a value
in the range 0 <= x < 256. Any value outside this range is an error.
The bytearray() method has the following three forms:
1. bytearray(integer): When we pass an integer argument, the
method returns a bytearray of the specified number of bytes and
the value of each byte is set to zero. For example, bytearray(4)
returns bytearray(b'\x00\x00\x00\x00'). The value of each byte is
shown in hexadecimal format.
2. bytearray(obj): When we pass a list, a tuple, a set, or a dict of
integer numbers, the method returns a bytearray of the items of
the object. For example, bytearray([1,2,3]) returns
bytearray(b'\x01\x02\x03').
3. bytearray(string, encoding): When we pass a string and its
encoding, the method returns a bytearray of the ASCII values of
the characters of the string. For example, bytearray('abcαβγ','utf-
8') returns bytearray(b'abc\xce\xb1\xce\xb2\xce\xb3')
151
bytes(obj) It is similar to bytearray, but it returns an immutable array of bytes,
i.e., we cannot modify the returned array elements. However, we can
access individual items. Similar to the bytearray() method, the bytes()
method can also be used in the three forms. See the following
examples:
152
(3+6j)
>>> #Error: the order of real and imaginary part is
important in case of string
>>> complex("4j+3")
Traceback (most recent call last):
File "<pyshell#148>", line 1, in <module>
complex("4j+3")
ValueError: complex() arg is a malformed string
>>> complex(3+4j) #Convert an expression to a complex
number
(3+4j)
>>> complex(4j+3) #The order of real and imaginary parts
is not important
(3+4j)
dict(data) It creates a dictionary object from data. The data can be given in the
form of a list (or a tuple) of tuples containing pairs of key-value pairs.
If there is no argument given, it returns an empty dictionary object. See
the following examples:
153
divmod(arg1, Returns the quotient and the remainder when the first argument is
arg2) divided by the second argument. It can handle both real and integer
arguments. See the following examples:
(0, 'P')
(1, 'y')
(2, 't')
(3, 'h')
(4, 'o')
(5, 'n')
>>> #The counter starts from 5
>>> for i in enumerate("Python",5):
print(i)
(5, 'P')
(6, 'y')
(7, 't')
(8, 'h')
(9, 'o')
(10, 'n')
eval(string) Evaluates a string argument as python expressions and returns the
result. For example, eval("10+3*4-2") returns 20, x=2;
eval("2*x**2+2*x-3") returns 9, and eval("1+2,3+4,5*6") returns (3, 7,
30).
154
exec(string) Executes Python codes given as a string. For example,
exec("a=2;b=3;print(a+b)") creates variables a and b and print their
sum.
filter(fun, itr) It is used to select those items from a collection that returns True when
processed by a specified fun. The function can be used for every type
of collection and sequence, such as list, tuple, set, dictionary, string,
range. In the following example, vowels in a string and a list are
selected and printed.
o
o
a
i
>>> #Create a filter to separate vowels in a list
>>> for ch in filter(isVowel,['a','b','c','d','e','f']):
print(ch)
a
e
float(obj) Converts its argument to an equivalent floating point number. For
example, float("1231.4") returns 1231.4 and float(10) returns 10.0.
format(val) It is used to format a value as per a specified formatting string. See
chapter 3, section 3.8.2.
frozenset(itr) It converts an iterable data in a frozenset. A frozen set is similar to a
set, but it is immutable, i.e., it freezes the iterable objects and makes
155
them unchangeable. The function first removes duplicate items and
then converts the iterable in a frozen set. See the following example:
156
None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-
in)>, 'fruit': <class '__main__.fruit'>, 'a': 2, 'b': 3, 'i': (5, 'n'), 'x': 2}.
hasattr(obj, It returns True if the specified object has the specified attribute
attrib) (property/method). For example, hasattr(list(),"append") returns
True, whereas hasattr(tuple(),"append") returns False.
hash(obj) It returns the hash value of an immutable object, such as numeric
literals, strings, tuples, range. A hash value is a numeric value of fixed
length that uniquely identifies data. For example, hash("abc") returns
224187216707242117; hash(12.3) returns 691752902764109836, and
hash((1,2,3)) returns 529344067295497451. Hashing is widely used for
searching data in a collection.
help(obj) It is used to display the documentation of modules, functions, classes,
and keywords. See the following example:
bin(number, /)
Return the binary representation of an integer.
>>> bin(2796202)
'0b1010101010101010101010'
157
id(obj) It returns the id of an object in the memory. In Python, every created
object is assigned a unique integer ID. For example, a=10; id(a) returns
2213301873232.
input(string) Reads and returns a line of string from the console. For example,
>>>input("Enter a string:")
Enter a string: Python Program
The function returns 'Python Program'
int(arg, base) It converts the first argument to an integer. It accepts a number or a
string as its argument. The second parameter is the base of the number
system in which the first argument is given. The default base is 10, i.e.,
the decimal system. See the following examples:
158
False
iter(obj) It creates an iterable object from a collection object, such as a list, tuple,
string, set, dictionary, range. For example, vowels_iter=iter("aeiou")
create an iterable object. It can be iterated using the function next ().
For example, next(vowels_iter) returns 'a' and the next time
next(vowels_iter) returns 'e', and so on.
len(obj) It returns the number of elements in a collection object, such as a string,
list, tuple, set and dictionary. For example, len("abc") returns 3 and
len([1,2,3,4]) returns 4.
list(obj) It creates a list from a collection object. The argument could be any
collection object, such as a tuple, string, set, dictionary, range. If no
argument is given, it creates an empty list. For example, list("abc")
returns ['a', 'b', 'c'], list((1,2,3)) returns [1, 2, 3] and list() returns [], i.e.
an empty list.
map(fun, itr) It evaluates the function specified as the first argument over a
collection object specified as the second argument. For example,
list(map(lambda x:x%2==0,[1,2,3,4,5])) returns [False, True, False,
True, False].
Also, see the following example:
1
4
9
max(itr) It returns the largest item in an iterable object. For example,
max([1,2,4,3,5,0]) returns the element with the maximum value, i.e. 5,
max({1:1,2:4,3:9,4:16}) returns the maximum key value, i.e. 4, and
max("abc") returns the character with the maximum ASCII value, i.e.
'c'
159
min() It returns the smallest item in an iterable object. For example,
min([1,2,4,3,5,0]) returns the element with the smallest value, i.e. 0,
min({1:1,2:4,3:9,4:16}) returns the smallest key value, i.e. 1, and
min("abc") returns the character with the smallest ASCII value, i.e. 'a'
next() Returns the next item in an iterable object. See the following example:
160
pow(x,y) It returns the value of x raised to the power of y, i.e., xy. For example,
pow(2,3) returns 8. It can handle complex arguments. For example,
pow(2+3j,3+4j) returns (-0.204552921794176+0.8966232598799766j).
print() It prints the value of arguments to the standard output device. For
example, print(10+2, 'ABC') prints 12 ABC on the console. See chapter
3.
property() It binds the getter, setter, and deleter functions of a class with a single
attribute name. Then, depending on the use of the attribute, the
corresponding function is called, automatically. For example, when
the attribute is assigned a value, the setter function is called, and if the
attribute is used in an expression, the getter function is called. See the
following example:
161
end value. By default, start=0 and step=1. All the arguments should be
integer only. Negative integers can be used. If we cannot reach from
start to end with the given step value, an empty range object is created.
The range function creates the definition of the range objet in the
memory. To get the individual item, we need to convert it to either into
a list or other collection. We can also get the individual item of the
range by iterating it using a for loop. See the following examples:
162
>>> list(reversed("abcd")) #String’s reversed iterator
['d', 'c', 'b', 'a']
>>> list1=reversed([1,2,3,4]) #List’s reversed iterator
>>> for x in list1:
print(x,end=' ')
4 3 2 1
>>> list(reversed({1:2,3:4})) #Dict’s reversed iterator
[3, 1]
round(x,d) It rounds off x (a float number) to the number of digits, d, after the
decimal point. For example, round(2.3123,2) returns 2.31. If the second
argument is negative, the decimal portion is discarded, and the whole
number portion is rounded off up to the given number of digits. For
example, -1 rounds off to the nearest tenth, and -2 rounds off to the
nearest hundredth. Thus, round(377.77,-1) returns 380.0 and
round(377.7717,-2) returns 400.0.
set(obj) It creates a set object from a collection object. Duplicate entries are
removed. For example, set([1,2,3,4,1,2,3]) returns {1, 2, 3, 4}. If no
argument is given, an empty set is created.
setattr() It sets the value of the specified attribute of an object with a given
value. It is similar to obj.attrib=value. See the following example:
164
str(obj) It converts the argument to a string object. The argument can be any
Python object. See the following examples:
165
type(obj) It returns the class of an object. The argument can by any Python object.
See the following examples:
(1, 5)
(2, 6)
(3, 7)
166
4.6 Importing Mathematical Functions
Mathematical functions are common and frequently used in scientific and
engineering problems. Python has a built-in module, called math, that defines commonly
used mathematical functions and constants. To use the functions of a module, we have to
import the module into our programs, using the syntax import module_name. For example,
the statement import math will import the math module in the program. Once a module is
imported, its functions can be used using the dot notation. For example, to use the sin
function of the math module, we use the expression math.sin(x).
Alternatively, all the functions of a module can be imported into a program and
used directly without the module name, using the syntax form module_name import *. For
example, the statement from math import * imports all the functions of the math module.
These functions can be directly used without the object name, such as sin(x).
Instead of importing all the functions of a module, we can also import selected
functions from a module, using the syntax form module_name import fun1, …, fun2. For
example, the statement from math import sin, sqrt will import only two functions: sin and
sqrt, from the math module.
The math module consists of commonly used mathematical functions and accepts
only real and integer parameters. However, the equivalent functions that can handle
complex numbers can be imported from the cmath module. The functions of the math
module are listed in table 4.14, with their brief descriptions. Please note that all the
trigonometric functions of the math module accept angles in radians only. Table 4.15 lists
mathematical constants defined in the math module. The command dir(cmath) lists the
cmath module functions as given in example 4.18. Most of these functions are similar to
their corresponding functions in the math module but can process complex numbers and
return complex numbers. Table 4.16 discusses some of these functions, which are specific to
the cmath module.
If we import functions from two modules in a program, and there are functions with
the same name in both the modules, the functions of the last imported module will
overwrite the functions of the earlier imported modules. For example, if we write the
statement from cmath import * after the statement from math import *, the common
functions such as sin, cos, are available from the cmath module only.
167
Table 4.14: Mathematical functions
Function Description
math.ceil(x) It returns the smallest integer greater than or equal to x. For
example, math.ceil(5.3) returns 6.
math.copysign(x, y) It returns x with the sign of y. For example, math.copysign(3,-4)
returns -3.0.
math.fabs(x) It returns the absolute value of x as a float number. For example,
math.fabs(-5) returns 5.0
math.factorial(x) It returns the factorial of x. For example, math.factorial(5) returns
120.
math.floor(x) It returns the largest integer less than or equal to x. math.floor(5.7)
returns 5.
math.fmod(x, y) It returns the remainder when x is divided by y; x and y can be
real or float numbers. For example, math.fmod(7,3) returns 1.0
and math.fmod(5.5,2.5) returns 0.5.
math.frexp(x) It returns mantissa(m) and exponent(e) of a given value x such
that x== m*2**e. The mantissa is a floating point number, and the
exponent is an integer value. If x is zero, the mantissa=0,
otherwise 0.5 <= abs(m) < 1. For example, math.frexp(7.2) returns
(0.9, 3).
math.fsum(iterable) It returns the sum of values in an iterable. For example,
math.fsum([1,2,3,4,5]) returns 15.0.
math.isfinite(x) It returns True if x is neither an infinity nor a NaN (Not a
Number). For example, math.isfinite(10) returns True, whereas
math.isfinite(inf) and math.isfinite(nan) returns False.
math.isinf(x) It returns True if x is infinite. For example, math.isinf(10) returns
False and math.isinf(math.inf) returns True.
168
math.isnan(x) It returns True if x is a NaN. For example, math.isnan(math.nan)
returns True and math.isnan(10) returns False.
math.ldexp(m, e) It returns a number form mantissa (m) and exponent(e) using the
expression m * (2**e). For example, math.ldexp(0.9,3) returns 7.2.
math.modf(x) It returns the fractional and integer parts of x. For example,
math.modf(7.2) returns (0.20000000000000018, 7.0).
math.trunc(x) It returns the truncated integer value of x. For example,
math.trunc(7.8) returns 7.
math.exp(x) It returns the value of 𝒆𝒙 . For example, math.exp(.5) returns
1.6487212707001282.
math.expm1(x) It returns the value of 𝒆𝒙 -1. For example, math.expm1(0.5) returns
0.6487212707001282.
math.log(x, It returns the logarithm of x to the base b (the default base is e).
[b=math.e]) For example, math.log(10) returns 2.302585092994046 and
math.log(10,10) returns 1.0.
math.log1p(x) It returns the natural logarithm (i.e. the base is e) of 1+x. For
example, math.log1p(1) returns 0.6931471805599453.
math.log2(x) It returns the logarithm of x with base 2. For example,
math.log2(10) returns 3.321928094887362.
math.log10(x) It returns the logarithm of x with base 10. For example,
math.log10(10) returns 1.0.
math.pow(x, y) It returns x raised to the power y, i.e., xy. For example,
math.pow(2,3) returns 8.0.
math.sqrt(x) It returns the square root of x. For example, math.sqrt(4) returns
2.0.
math.acos(x) It returns the arc cosine of x in radians. For example,
math.acos(0)*180/math.pi returns 90.0.
math.asin(x) It returns the arc sine of x in radians. For example, math.asin(1)
returns 1.5707963267948966.
math.atan(x) It returns the arc tangent of x in radians. For example,
math.atan(1)*180/ math.pi returns 45.0.
169
math.atan2(y, x) It returns atan(y / x). For example, math.atan2(1,2)*180/ math.pi
returns 26.56505117707799.
math.cos(x) It returns the cosine of x. The x should be in radian. For example,
math.cos(math.pi/4) returns 0.7071067811865476.
math.hypot(x, y) It returns the length of the hypotenuse of a right-angle triangle,
i.e., Euclidean norm, sqrt(x*x + y*y). For example,
math.hypot(3,4) returns 5.0.
math.sin(x) It returns the sine of x. For example, math.sin(math.pi/2) returns
1.0.
math.tan(x) It returns the tangent of x. For example, math.tan(math.pi/4)
returns 0.9999999999999999.
math.degrees(x) It converts an angle x from radians to degrees. For example,
math.degrees(math.pi/2) returns 90.0.
math.radians(x) It converts an angle x from degrees to radians. For example,
math.radians(90) returns 1.5707963267948966.
math.acosh(x) It returns the inverse hyperbolic cosine of x; x must be greater
than or equal to 1. For example, math.acosh(1) returns 0.0.
math.asinh(x) It returns the inverse hyperbolic sine of x. For example,
math.asinh(1) returns 0.8813735870195429.
math.atanh(x) It returns the inverse hyperbolic tangent of x; x must lie between
-0.99 to 0.99. For example, math.atanh(.9) returns
1.4722194895832204.
math.cosh(x) It returns the hyperbolic cosine of x. Mathematically, cosh(𝑥) =
𝑒 𝑥 +𝑒 −𝑥
.
For example, math.cosh(1) returns 1.5430806348152437 ,
2
and (math.exp(1)+ math.exp(-1))/2 returns 1.5430806348152437.
math.sinh(x) It returns the hyperbolic sine of x, which is equivalent to sinh(𝑥) =
𝑒 𝑥 −𝑒 −𝑥
. For example, math.sinh(1) returns 1.1752011936438014.
2
170
math.erf(x) It returns the value of the Gaussian error function at x.
2 𝑥 2
Mathematically erf(𝑥) = 𝜋 ∫0 𝑒 −𝑡 𝑑𝑡 . For example, math.erf(.5)
√
returns 0.5204998778130465.
math.erfc(x) It returns the complementary error function at x. Mathematically,
erfc(x) = 1-erf(x). For example, math.erfc(.5) returns
0.4795001221869534, and 1- math.erf(.5) returns
0.4795001221869535.
math.gamma(x) It returns the value of the Gamma function at x. For positive
integers, gamma(x)=factorial(x-1). For example, math.gamma(5)
returns 24.0, and math.factorial(5-1) returns 24.
math.lgamma(x) It returns the natural logarithm of the absolute value of the
Gamma function at x. For example, math.lgamma(5) returns
3.178053830347945, and math.log(24) returns
3.1780538303479458.
math.tau Tau is a circle constant and is defined as the ratio of the circumference to
the radius of a circle. It is equal to 2π. For example, math.tau returns
6.283185307179586.
math.nan It is a floating-point NaN value. NaN stands for not a number. It is used
to represent any value that is undefined or unpresentable as a real
number. For example, 0/0, ∞/∞, square root and log of a negative
number, inverse sine, and cosine of a number greater than 1 or less than
-1 are all undefined as a real number; therefore, they are represented as
171
NaN. All the functions of the math module will raise errors in such
situations. For example, math.inf/ math.inf returns nan; 1/ math.nan
returns nan; 1* math.nan returns nan.
>>>dir(cmath)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh',
'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj',
'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj',
'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
cmath.isclose() It checks whether two complex values are close or not, within a
specified tolerance values. This method uses a relative tolerance
(rel_tol) and an absolute tolerance (abs_tol) to determine the closeness
using the following formula: abs(a-b) <= max(rel_tol * max(abs(a),
abs(b)), abs_tol). The default value of rel_tol=1e-09 and abs_tol=0.
Examples:
>>> cmath.isclose (2+3j,2+3.0001j)
False
>>> cmath.isclose (2+3j,2+3.0000000001j)
True
cmath.phase() It returns the phase angle of a complex number. The phase angle of a
complex number is the angle between the vector representing the
complex number and the positive x-axis. The returned value is
between -𝜋 and 𝜋.
Examples:
>>> cmath.phase(2+3j)
0.982793723247329
172
>>> cmath.phase(2-3j)
-0.982793723247329
cmath.polar() It converts a complex number to the polar coordinate form. In the
polar coordinate form, a complex number is defined by modulus and
phase angle. Thus, the function returns modulus and phase angle.
Example:
>>> cmath.polar(2+3j)
(3.605551275463989, 0.982793723247329)
cmath.rect() It converts a complex number given in the polar form into the
rectangular form. The parameters of the function are phase and
modulus. The method is equivalent to modulus * (math.cos(phase) +
math.sin(phase)*1j).
Syntax:
cmath.rect(modulus, phase)
Examples:
>>>cmath.rect(3.605551275463989, 0.982793723247329)
(2+2.9999999999999996j)
Program 4.1: Read a float number from the keyboard and print the last two digits of the
integral part of the number.
Solution steps:
1. Read the input number and convert it to a float.
2. Convert the float into an integer.
3. Get the last digit using modulus operator.
4. Remove the last digit by floor division.
5. Get the last digit using the modulus operator.
Program
173
d=y%10 #Modulus with 10 returns the last digit of y
print("Original number: ",x)
print("The integral part of the number: ",y)
print("The last digit of the integral part: ",d)
y=y//10 #Floor division with 10 removes the last digit of y
d=y%10 #Get the last digit of y
print("The second last digit of the integral part: ",d)
Output
Program 4.2: Write a program to find the volume and surface area of a sphere. Print the
result up to only three decimal digits.
Solution steps:
1. Read the radius of the sphere.
4
2. Calculate the volume using the formula 𝑣 = 𝜋𝑟 3 .
3
3. Calculate the surface area using the formula 𝑠𝑎 = 4𝜋𝑟 2 .
Program
import math
r=float(input("Enter radius of the sphere:"))#Read radius
v=(4/3)*math.pi*r**3 #Calculate volume
sa=4*math.pi*r**2 #Calculate surface area
print("Volume={:8.3f}\nSurface area={:8.3f} ".format(v,sa))
Output
174
Enter radius of the sphere:3
Volume= 113.097
Surface area= 113.097
Program 4.3: Write a program to convert the body temperature given in Fahrenheit to
Celsius.
Solution steps:
1. Read the temperature in Fahrenheit (F).
5
2. Use the formula 𝐶 = 𝑥 (𝐹 − 32) to convert to Celsius.
9
Program
Output
Solution Steps:
1. Read the coefficients a, b, and c.
−𝑏+√𝑏2 −4𝑎𝑐 −𝑏−√𝑏2 −4𝑎𝑐
2. Calculate roots using the formula 𝑥1 = and 𝑥2 = .
2𝑎 2𝑎
175
#Read the coefficients a, b and c
a, b, c=eval(input("Enter the values of coefficients a, b, and c: "))
#The cmath.sqrt() function can process negative numbers
#Hence, the following formulas can find real and complex roots
x1=(-b + cmath.sqrt(b*b - 4*a*c))/(2*a)
x2=(-b - cmath.sqrt(b*b - 4*a*c))/(2*a)
print("x1=", x1)
print("x2=", x2)
Outputs
Program 4.5: Write a program to calculate economic order quantity (EOQ), when
demand per unit time (D), unit holding cost per unit time (H) and setup cost per order
(S) are given.
Solution Steps:
1. Read D, H and S
2𝐷𝑆
2. Calculate EOQ using the formula 𝐸𝑂𝑄 =√
𝐻
from math import sqrt #Import the sqrt function from the math module
#Read D, H and S
d =float(input("Enter demand rate: "))
h =float(input("Enter unit holding cost per unit time: "))
s =float(input("Enter setup cost: "))
176
#Calculate EOQ
eoq = sqrt(2*d*s/h)
print("EOQ=", round(eoq,0))#Round to the nearest whole number
Outputs
Chapter Summary
177
10. A compound assignment operator combines another operation with an
assignment. For example, x+=5 is equivalent to x=x+5.
11. A membership operator checks the presence or absence of data in a
collection.
12. In Python, we can refer to the same data with more than one variable.
13. An expression is a combination of variables, functions, constants, and
operators that evaluates to a value.
14. An arithmetic expression combines numeric and Boolean values and
arithmetic operators and returns a numeric value.
15. A logical expression combines relational expressions and other values with
logical operators (and, or and not) and returns either True or False.
16. In Python, 0, 0.0, 0+0j, an empty string, an empty list, an empty tuple, an
empty set, an empty range, and an empty dict are considered False, and all
other values are considered True in a logical expression.
17. A string expression combines string literals, string variables, and functions
using string operators (concatenation (+) and product (*)) and returns a
string.
18. The precedence rule is similar to the BODMAS rule of evaluating arithmetic
expressions, which guides the order in which operations are processed in
an expression.
19. The direction of the evaluation of operators, called associativity rule, of the
same level of precedence can be either from left-to-right or right-to-left. In
the left-to-right associativity, the operator in the left is evaluated first,
whereas, in the right-to-left, the operator in the right is evaluated first.
20. A statement is a programming construct that does something, for example,
an assignment statement, conditional and branching statement, looping
statements. Whereas, an expression is a combination of values and
operators and always returns a value.
178
(a) Relational
(b) Bitwise
(c) Increment
(d)Membership
2. Which of the following operation is not supported in Python?
(a) Addition of two complex numbers
(b) Addition of an integer and a complex number
(c) Addition of Boolean value and complex number
(d) None of the above
3. Which of the following cannot be an operand in an arithmetic expression?
(a) Boolean
(b) Integer
(c) Complex
(d) String
4. Which of the following is the correct order of precision up-gradation in
Python?
(a) Boolean, float, integer, and complex
(b) Boolean, integer, float, and complex
(c) Integer, Boolean, float, and complex
(d) Boolean, integer, complex, float
5. What is the type of the value of the expression True+10*2.5?
(a) bool
(b) int
(c) float
(d) None of the above
6. What is the type of the value of the expression True+10*2.5+ (3+4j) -(5+4j)?
(a) bool
(b) int
(c) complex
(d) float
7. Which of the following is the correct output of the expression -7//3?
(a) -2
(b) -3
(c) -2.33
(d) None of the above
179
8. Which of the following is the correct output of the expression -7%3?
(a) -1
(b) -2
(c) 2
(d) 1
9. Which of the following is the correct output of the expression 5.2%2.5?
(a) 0.0
(b) 0.2
(c) Invalid expression
(d) None of the above
10. Which of the following is the correct output of the expression 5.2//2.2?
(a) 2.0
(b) 2.3636363636363633
(c) Invalid expression
(d) None of the above
11. Which of the following is an invalid arithmetic expression?
(a) 2.3 % 1.3
(b) 2.3 // 1.3
(c) (2+4j) % (1+2j)
(d) All of the above
12. Which of the following is an invalid expression?
(a) 10+'10'
(b) (2+4j) // (1+2j)
(c) (2+4j) % (1+2j)
(d) All of the above
13. Which of the following is an invalid expression?
(a) 10+True
(b) (2+4j) * (1+2j)
(c) (2+4j) / (1+2j)
(d) None of the above
14. How many relational operators are there in Python?
(a) 7
(b) 6
(c) 5
(d) 4
180
15. Which of the following is the correct not equal to operator in Python?
(a) <>
(b) !=
(c) ~=
(d) ><
16. Which of the following is an invalid expression in Python?
(a) 2+3j==2+3j
(b) 2+3j !=2+3j
(c) 2+3j <=2+3j
(d) All of the above
17. Which of the following logical expression returns False?
(a) bool("")
(b) bool(set())
(c) bool(0)
(d) All of the above
18. What is the output of the expression 0 or 3+4 in Python?
(a) 0
(b) 7
(c) True
(d) None of the above
19. Which of the following is not a valid chained logical expression?
(a) x<y<z
(b) x<y>z
(c) x<=y!=z
(d) x<=y=z
20. The maximum number of bits to store an integer in Python?
(a) 16
(b) 64
(c) 128
(d) Not fixed
21. What is the output of the expression 7&11?
(a) 1
(b) 2
(c) 3
(d) 4
181
22. What is the output of the expression 7|11?
(a) 13
(b) 14
(c) 15
(d) 16
23. What is the output of the expression 7<<2?
(a) 14
(b) 28
(c) 1
(d) 15
24. Which of the following is an invalid assignment in Python?
(a) x, y, z=1, 2, 3
(b) x=1, 2, 3
(c) x, y, _=1, 2, 3
(d) x, y = 1, 2, 3
25. Which of the following is a valid expression in Python?
(a) "Python" + "Programming"
(b) "Python" + "Programming"*3
(c) "Python" + "Programming"*len("ABC")
(d) All of the above
26. Which of the following is the correct order of the evaluation of operators in
the expression 3 + 8 / 2 * 4?
(a) / , * ,+
(b) + , / , *
(c) +, *, /
(d) None of the above
27. What is the value of the expression 22 // 3 + 3 / 3?
(a) 8
(b) 8.0
(c) 8.333
(d) None of the above
28. What is the value of the expression 2 + 9 / 3 *3 - 8 / 4 ?
(a) 9.0
(b) 3.0
(c) 8.0
182
(d) None of the above
29. The operators is and is not are _______.
(a) Identity Operators
(b) Comparison Operators
(c) Membership Operators
(d) None of the above
30. What is the output the expression 0xD + 0xE + 0xF?
(a) Error: Invalid expression
(b) 0xDEF
(c) 0X22
(d) 42
31. Which of the following is not a complex number?
(a) 2 + 3j
(b) complex(2,3)
(c) 2 + 3i
(d) None of the above
Review Questions
183
q) The frozenset is mutable.
r) The statement from math import * imports all the functions of the math
module.
2. Describe various arithmetic operators.
3. Explain various membership and identity operators.
4. Outline various bitwise operators.
5. Discuss chaining of relational operators.
6. Describe truth tables of various logical operations.
7. Explain precedence and associativity rules of operators evaluation.
8. Describe string operators.
9. List 10 built-in methods and explain them with examples.
10. Write Python expressions for the following:
(a) 𝑥 − 𝑦 + 𝑥𝑦
(b) (𝑥 + 𝑦)(𝑥 − 𝑦)
𝑥𝑦
(c)
𝑥+𝑦
(d) 4𝑦 2 + 2𝑥𝑦 − 5
𝑥 𝑦
(e) 𝑦 + 𝑧
𝑧
(f) 𝑧 𝑥 +
𝑦
11. Write the Python statements for the following equations:
(a) 𝑎 = 𝜋𝑟 2 + 2𝜋𝑟ℎ
2𝑚𝑛
(b) 𝑇 = 𝑚+𝑛 𝑔
(c) 𝑠 = √𝑥 2 + 𝑦 2 + 2𝑥𝑦𝑐𝑜𝑠(𝑎)
𝑣2
(d) 𝐸 = 𝑚 [𝑎ℎ + ]
2
𝑋𝑌 𝑋
(e) 𝐴 = 𝐶+10 − 8(𝑍+𝑌)
12. Remove the unnecessary brackets from the following expressions and give
the values of the expressions:
(a) ((5-(7/5) + 8) %3) +25
(b) ((10-5)*4)+8
(c) (5*6) + (-5/2)
(d) 5/(3*6)
13. Find out the values of the following logical expressions, with x=2, y=3, and
z=-5:
(a) x>y and z<x
(b) x>y or z<x
184
(c) x<y>z
(d) x<y<z
14. Determine the values of the following expressions:
(a) 3 in [1,2,3,4,5]
(b) 3 not in [1,2,3,4,5]
(c) bin(10)
(d) hex(20)
(e) oct(10)
15. Determine the values of the following expressions, with a=65; b=65; c=97:
(a) a is b
(b) a is not c
(c) chr(a)
(d) ascii(a)
16. Determine the output of the following expressions, with a=3+4j and b=3-4j:
(a) a+b
(b) a-b
(c) a*b
(d) abs(a)
17. Determine the output of the following expressions:
(a) bool(None)
(b) bool(False)
(c) bool("ABC")
(d) bool(0x0)
(e) bool(set())
(f) bool([0,0,0])
(g) bool(range(6,3))
18. Determine the output of the following expressions, with a=5 and b=7:
(a) a&b
(b) a|b
(c) a^b
(d) ~a
(e) a<<2
(f) b>>2
19. Determine the value of x after the executing the following, with x=5:
(a) x+=3
(b) x-=3
(c) x%=3
(d) x&=3
185
(e) x>>=1
20. Determine the output of the following:
(a) bin(10)+bin(15)
(b) bool([1,2,3])+bool(-1)
(c) chr(945)
(d) complex(3,5)
(e) hex(255)
(f) len([1,2,3,4])
(g) max("Python")
(h) oct(20)
(i) ord('a')
(j) round(377.77,-1)
(k) sum([1,2,3,4])
21. Determine the output of the following:
(a) math.copysign(3,-4)
(b) math.fabs(-5)
(c) math.fmod(5.5,2.5)
(d) math.trunc(7.8)
(e) cmath.phase(2+3j)
(f) cmath.polar(2+3j)
(g) cmath.rect(3, 1)
Programming Exercises
1. Given two strings s1= “Python” and s2= “Programmers”, Print the length of s1
and s2, and display the output after concatenating the two strings s1 and s2.
2. Read a distance in meter and convert it into inch.
3. Input radius of a circle and compute radius and circumference of the circle.
4. Input an integer number and calculate its factorial using the library function.
5. Reads the sides (a, b and c) of a triangle. Calculate area of the triangle. (Hint:
𝑎+𝑏+𝑐
formula for area calculation is area= √𝑠(𝑠 − 𝑎)(𝑠 − 𝑏)(𝑠 − 𝑐) , and 𝑠 = 2
.
186
7. Read the initial velocity (u), acceleration (a) and time of travel (t) of a body. Then
calculate the distance (s) traveled by the body (Hint: use the formula s = ut +
at2
2
)
8. Read the principal amount (p), rate of interest (r) and period of investment (n).
𝑟
Calculate the amount (a) received at the maturity.(Hint: 𝑎 = 𝑝(1 + 1000)𝑛 )
9. Write a program to calculate the number of seconds in a leap year. (Hint: A leap
year has 366 days)
10. Read coordinates of two points and calculate the distance between them.
11. Read a complex number and calculate its magnitude and phase. (Hint: use
library functions)
12. Write a program to read a numeric list from the keyboard and find the sum of
its elements. (Hint: Use eval() function).
187
Chapter 5
Learning Outcomes:
The normal order of execution of the statements of a program is in the order in which
they are written in the program, i.e., statements are executed sequentially from top to
bottom. However, there are many situations in a program where we need to alter this
normal execution sequence, such as choosing a different set of statements based on some
conditions or repeating a set of statements. For example, to find the roots of a quadratic
equation (𝑎𝑥 2 + 𝑏𝑥 + 𝑐 = 0), two situations can occur based on the values of its coefficients:
real roots or complex roots. Hence, after reading the values of the coefficients, a set of
statements are executed for real roots and another set of statements for complex roots.
Figure 5.1 shows a flowchart to find the roots of a quadratic equation. As shown in the
flowchart, two different execution paths are followed: (1) the left path for the real roots and
(2) the right path for the complex roots. In computer programming, choosing a different
execution sequence based on a specified condition is called decision making and
branching. Python has the following decision making and branching statements:
1. if statement
2. if-else statements
3. nested if statements
4. if-elif ladder
5. Conditional expression
5.1 if Statement
An if statement is used to execute a block of code if a specified condition evaluates to
True, otherwise the block is skipped. Figure 5.2 shows this situation with a flowchart. The
syntax of the if statement is given below:
188
if condition:
Statement 1
Statement 2
⋮
Statement n
Shorthand if statement: As a special case, if there is only one statement in the True
block, the following syntax may be used, also called a shorthand if statement:
if condition: Statement1
Also note, expressions 0 == False, 0.0 == False and 0.0+0.0j == False all returns True.
Thus, the statement if 0 == False: print("Hello") prints Hello in the console. However,
if we directly test for the equality of any empty value or None (given above) with False,
the result is False. For example, "" == False evaluates to False. Thus, the statement if
""==False: print("Hello") prints nothing. But if we convert an empty value to a Boolean
value and then equate, it returns True. For example, bool("")==False evaluates to True.
Thus, the statement if bool("")==False: print("Hello") prints Hello in the console.
Further, condition can be a simple relational expression, such as a>b, a==b, a<=b,
or can be a compound expression, such as a>b and a<c, a>b and c. The above points
about the condition expression are valid for all the decision and branching statements
in Python.
189
Start
Read a, b, c
d = b2-4ac
Real root branch Complex root branch
yes no
d >= 0
r1 = (-b+√d)/2a rp = -b/2a
r2 = (-b-√d)/2a ip = √(-d)/2a
Stop Stop
False
Condition
True
190
Example 5.1(a): If statement
Enter a number: 12
The square root of 12.0 = 3.4641016151377544
Enter a number: -12
The square root of 12.0 = 3.4641016151377544
Enter a number: 12
The square root of 12.0 = 3.4641016151377544
Enter a number: -12
The square root of 12.0 = 3.4641016151377544
191
5.2 if-else Statement
There are many situations where we want to execute a block of codes if a certain
condition evaluates to true, otherwise a different block of codes. The if-else statement is
used in such situations. Figure 5.3 shows a flowchart of the if-else statement. From the
flowchart, it is clear that when the specified condition evaluates to true, the true block is
executed; otherwise, the false block is executed. After executing one of the two blocks, the
statement written after the if-else block is executed. The syntax of the if-else block is given
below:
if condition:
Statement 1
Statement 2
⋮
Statement n
else:
Statement 1
Statement 2
⋮
Statement n
Shorthand if-else statement: As a special case, if the number of statements in the true
block and the false block is one, the following syntax can be used. This special case is called
the shorthand if-else statement.
if condition: Statement 1
else: Statement 1
Example 5.2(a) uses an if-else statement to find real and complex roots of a quadratic
equation, and example 5.2(b) uses a shorthand if-else statement to tell if the given number
is positive or negative.
192
False
Condition
True
193
Output
Enter a value: 10
The given number is positive
194
if condition:
#Level 1
Statement 1
⋮
if condition:
#Level 2
Statement 2
⋮
if condition:
#Level 3
Statement 1
⋮
Statement n
else:
Statement 1
⋮
Statement n
⋮
Statement n
else:
Statement 1
⋮
Statement n
⋮
Statement n
else:
#Level 1
Statement 1
⋮
if condition:
#Level 2
Statement 1
⋮
Statement n
else:
Statement 1
⋮
Statement n
⋮
Statement n
195
False
Condition
True
Statements Statements
Nested if
True
Condition
False Statements
Statements
196
print(a)
else:
print(c)
else:
if b> c: #Inner if
print(b)
else:
print(c)
Output
if condition1:
Statements
elif condition2:
Statements
⋮
else:
statement
197
Shorthand ladder-if statement: If there is a single statement in a block, the
shorthand form can be used. The shorthand form and standard form can be mixed as given
below:
if condition1: Statement1 #Shorthand form
elif condition2: #Standard form
Statements
⋮
else:
statement
As shown in the flowchart (figure 5.4), the conditions are tested sequentially from
the top to the bottom. Once a true condition is found, the remaining part of the ladder-if is
skipped. Hence, the sequence of the conditions in the if-elif-else statement is critical and
should be carefully chosen. Example 5.4(a) uses an if-elif-else ladder construct to predict the
grade of a student.
The ladder-if statement gives cleaner and more efficient code than the equivalent
nested if statement or the simple if statement. Example 5.4(b) and 5.4(c) use simple if and
nested-if statements, respectively, for the above student grading problem.
198
True
Condition Statements
False
True
Condition Statements
False
True
Condition Statements
False
Statements
199
elif marks>=45:print("Your grade: Second")
elif marks>=35:print("Your grade: Third")
else:print("Your grade: Fail")
Output
Enter your marks: 65
Your grade: First
200
Enter the marks: 49
Your grade: Second
201
Enter the marks: 41
Your grade: Third
Enter numbers:3,4
The minimum of 3 and 4 is 3
Enter numbers:7,3
The minimum of 7 and 3 is 3
202
Example 5.5(b): Ternary operator with functions
Nesting of ternary operators: Python allows nesting of ternary operators. We can write
another ternary operator in on_true_expression and/or on_false_expression. Example
5.5(c) illustrates the nesting of ternary operators.
203
print(m)
Output
Enter an integer:20
Positive
Enter an integer:-20
Negative
Enter an integer:0
Zero
Implied ternary operator: The implied ternary operator (also called tuple ternary
operator) selects either the first item or the second item of a two-item collection, such as
a tuple, list, and dict, based on a condition. For example, (x, y)[condition] returns x if
condition is false; else returns y. In Python, True == 1 and False == 0, and Hence, (x,
y)[False] is equivalent to (x,y)[0] and (x, y)[True] is equivalent to (x,y)[1]. This
construction can be used with lists, strings, and dicts also. For example for x=2 and y=3,
[10,20][x<y] returns 20, "AB"[x<y] returns "B" and {0:"First",1:"Second"}[x<y] returns
"Second". For a dictionary, the keys should be 0 and 1.
However, this construction is not encouraged as it is slow and confusing. First, it is
slow as both the collection items are evaluated to create the collection before selecting.
Second, it is confusing as the true condition returns the second item, whereas the false
condition returns the first item. Therefore, we should carefully put the true value and
the false value correctly in the collection. Hence, it is recommended to use the if-else
ternary operator as in this, only one value is evaluated depending on the condition.
Example 5.5(d) illustrates the above concepts.
#Using tuple
# (if_test_false,if_test_true)[test]
# Note the order of true and false values.
204
print(f"Tuple: The maximum of {a} and {b} is ", (a, b) [a < b] )
#Using list
# [if_test_false,if_test_true][test]
# Note the order of true and false values.
print(f"List: The maximum of {a} and {b} is ", [a, b] [a < b] )
#Using Dictionary.
#Order of elements is not important as indexing is through keys
print(f"Dictionary: The maximum of {a} and {b} is ",{1: a, 0: b}
[a > b])
Output
205
print(f"Ascending order:{a},{b}")
Output
Problem 5.1: Write a program to read three numbers and arrange them in ascending
order.
Solution Steps:
1. Read numbers
2. Swap the first two number if they are not in ascending order. Then, swap the last
two numbers if not in the ascending order
3. Swap the first two numbers if they are not in the ascending order.
x = int(input("Enter the first number: "))
y = int(input("Enter the second number: "))
z = int(input("Enter the third number: "))
206
Enter the second number: 7
Enter the third number: 1
Ascending order: 1 3 7
Problem 5.2: Write a program to read X and Y coordinates of a point and determine
in which quadrant the point lies
Solution Steps:
1. Read x and y
2. Use for following decision matrix:
Second quadrant: First quadrant:
x<0 and y>0 x>0 and y>0
Third quadrant: Fourth quadrant:
x>0 and y<0 x>0 and y<0
Problem 5.3: Write a program to determine if the given year is a leap year or not.
Solution Steps:
1. Read the year.
2. If the year is divisible by 4 but not by 100 or is divisible by 400, it is a leap year;
otherwise it is not a leap year.
years= int(input("Enter the year to check: "))#Read year
208
Problem 5.4: Write a program to read the number of units consumed by a consumer
and calculate the amount to be paid by the consumer as per the following tariff plan:
Solution Steps:
1. Read the unit consumed
2. Find out the slab in which the consumed unit fall, using a ladder-if statement
3. Calculate the billing amount
units= int(input("Enter the consumed units: "))
Output
Enter the consumed units: 150
Billing amount: 300
209
Enter the consumed units: 854
Billing amount: 2316.0
Problem 5.5: Write a program to read an integer number between 0 and 99 and print
the number in word.
Solution steps:
1. Read and validate the number
2. Create the following three dictionaries:
dict_ones={0:"Zero",1:"one",2:"Two",3:"Three",4:"Four",5:"Five",6:"Six",7:"Seve
n",8:"Eight",9:"Nine",10:"Ten"}
dict_tens={20:"Twenty",30:"Thirty",40:"Forty",50:"Fifty",60:"Sixty",70:"Seventy
",80:"Eighty",90:"Ninty"}
dict_special={11:"Eleven",12:"Twelve",13:"Thirteen",14:"Fourteen",15:"Fifteen"
,16:"Sixteen",17:"Seventeen",18:"Eightteen",19:"Ninteen"}
3. if the number is less than 11, use the number as a key to get the corresponding word
from the dictionary dict_ones.
4. if the number is between 11 and 19, use the number to get the corresponding word
from the dictionary dict_special.
5. for the number between 20 and 99, get the digit at the ones position and then floor
the number to the nearest tens. Use the floored number as key to get the
corresponding words from the dictionary dict_tens and then get the corresponding
word for the digit at one’s position.
dict_ones={0:"Zero",1:"one",2:"Two",3:"Three",4:"Four",5:"Five",6:"S
ix",7:"Seven",8:"Eight",9:"Nine",10:"Ten"}
dict_tens={20:"Twenty",30:"Thirty",40:"Forty",50:"Fifty",60:"Sixty",
70:"Seventy",80:"Eighty",90:"Ninty"}
210
dict_special={11:"Eleven",12:"Twelve",13:"Thirteen",14:"Fourteen",15
:"Fifteen",16:"Sixteen",17:"Seventeen",18:"Eightteen",19:"Ninteen"}
Chapter Summary
1. The normal order of execution of the statements of a program is in the order
in which they are written in the program, i.e., statements are executed
sequentially from top to bottom.
2. Choosing a different execution sequence based on a specified condition is
called decision making and branching.
211
3. An if statement is used to execute a block of code if a specified condition
evaluates to True, otherwise the block is skipped
4. Shorthand if statement is a special case of if statement where there is only
one statement in the True block and the complete statement can be written
in one line.
5. The if-else statement is used when we want to execute different blocks of
codes depending on the outcome of a condition.
6. If an if statement is written inside the body of another if statement, it is called
a nested if statement.
7. If multiple conditions are tested sequentially until a true condition is met,
the ladder-if is used.
8. The ternary operator, also called conditional expression, implements a
shorthand if-else statement, which assigns different values to a variable
based on the outcome of a condition.
9. The pass statement is a placeholder statement and does nothing.
212
4. Which of the following is equivalent to False?
(a) set()
(b) list()
(c) tuple()
(d) All of the above
7. For a=3, b=4, and c=5, which of the following statement will print Hello
in the console?
(a) if a<b<c: print("Hello")
(b) if b<c>a: print("Hello")
(c) if a<b and b<c: print("Hello")
(d) All of the above
213
10. Which of the following statement is not true about an if-elif-else
statement?
(a) conditions are evaluated sequentially from the top
(b) else block is essential
(c) all the conditions may not be evaluated
(d) if-elif-else statements cannot be nested.
11. For a=2, what is the value of x after executing the statement x= 1 if a>2
else 2 if a<3 else 3
(a) 1
(b) 2
(c) 3
(d) None of the above
12. With a =2 and x = (1,2), What is the output the expression x[a<2]?
(a) 1
(b) 2
(c) It is an error
(d) None of the above
(a) 0
(b) 5
(c) 10
(d) 20
214
a=int(True)
b=int(False)
if a+b==0:
n=1
elif a+b==1:
n=2
else:
n=3
print(n)
(a) 1
(b) 2
(c) 3
(d) None of the above
15. With a =2 and x = {1: "One", 0: "Zero"}, What is the output the
expression x[a<=2]?
(a) One
(b) Zero
(c) It is an error
(d) None of the above
16. What is the value of the expression bool ("1") + bool ("2") + bool ([1]) +
bool (None)?
(a) 3
(b) 4
(c) It is an error
(d) None of the above
Review Questions
Programming Exercises
Marks Scholarship(in
obtained (in % of tuition fee)
percentage)
95% and 100%
above
85% to 95% 90%
75% to 85% 75%
70% to 75% 25%
Below 70% 0
If the tuition fee is Rs 50000, write a program to read the marks obtained out of 500
and compute the net fee to be paid by a student.
9. Read the net taxable salary of an employee and compute his income tax according
to the following table:
Annual Salary Income tax percentage
Below 2.5 lakh 0
Between 2.5 to 5 10
Between 5 to 8 15
Above 8 20%
217
218
Chapter 6
A loop has two parts: header and body. The header of a loop consists of a looping
construct and the loop control condition. It controls the number of iterations a loop
performs. The body of a loop is a block of code that is repeated during the looping.
Python has the following two looping constructs: while loop and for loop. The
while loop executes the loop's body till the specified looping condition is true. In contrast,
the for loop iterates over each collection item. Both the while loop and the for loop are the
top-controlled looping. There is no built-in statement for the bottom controlled looping in
Python.
219
Condition
Body of the loop
False
True
Here, condition may be any expression that evaluates to True or False. In Python, any non-
zero value and any non-empty collection are considered True. The body of a loop may
consist of a single statement or a block of statements. When the looping condition evaluates
to False, the looping process ends, and the statement written below to the loop's body is
executed. Figure 6.2 shows a flowchart of a while loop. Here, it is important to note that the
body of a while loop may never execute if the condition evaluates to False on the very first
time. Example 6.1(a) finds the sum of digits of an integer number using a while loop.
220
Shorthand while loop: As a special case, when there is only one statement in the body of a
while loop, the statement can be written in the same line after the colon of the loop. This
special case of a while loop is called a shorthand while loop and has the following syntax:
We can combine many statements with a semi-colon (;) to make a single compound
statement. The Python interpreter treats a compound statement as a single statement.
Example 6.1(b) illustrates a shorthand while loop.
False
Condition
True
Statements
Example 6.1(a): The sum of the digits of a number using a while loop
221
while n>0:
#Start of the body of the loop
d=n%10
print(d)
s=s+d
n=n//10
#End of the while loop
#The statement to be executed at the end of the loop
print("The sum of digits is",s)
Output
Infinite while loop: An infinite loop is a loop that never terminates. A while loop can be
made to loop infinitely by using a conditional expression that always evaluates to true, such
as any non-zero constant, non-empty collection, or True. However, there should be some
mechanism to break such loops to make them useful in practice. Example 6.1(c) uses an
222
infinite loop to read numbers from the console, print their squares and terminate the
program when a negative number is given (the break statement is discussed later in the
chapter).
The infinite while loop with a termination condition at the bottom of the loop body
can be effectively used to substitute the do-while loop of many programming languages.
Python does not have the do-while type construct. Example 6.1(d) illustrates the above.
Enter a number:2
2.0 4.0
Enter a number:3
3.0 9.0
Enter a number:5
5.0 25.0
Enter a number:-1
Aborting the loop: a negative number entered
223
1,2,3,
Where items is a collection, such as a list, tuple, string, set, dictionary, or range, and item is
a variable that holds the current item of the sequence. By default, the for loop starts with
the first item in the collection and terminates after processing the last item.
Figure 6.3 shows a flowchart of the for loop. Example 6.2 for loops to traverse
various collection objects of Python.. It is important to note that the set object may return
items in a different order than the order in which they are created.
Statements
224
Blank loop: It is syntactically valid to have only the pass statement in the body of a loop,
called a blank loop. For example, the following for loop is valid:
for items in [1,2,3,4,5]:
pass #Doing nothing
print("\nIterating a list")
mylist = [1,2,3,4,5]
for item in mylist:
print(item*item,end=", ")
print("\nIterating a tuple")
mytuple = (1,2,3,4)
for x in mytuple:
print(1/x, end=", ")
print("\nIterating a set")
myset = {1,3,2,5,4}
for x in myset:
print(x, end=", ")
print("\nIterating a dictionary")
mydict = {1:"One",2:"Two",3:"Three"}
for key in mydict:
print(key,":",mydict[key], end=", ")
Output
Iterating a string
P, y, t, h, o, n,
Iterating a list
1, 4, 9, 16, 25,
225
Iterating a tuple
1.0, 0.5, 0.3333333333333333, 0.25,
Iterating a set
1, 2, 3, 4, 5,
Iterating a dictionary
1 : One, 2 : Two, 3 : Three,
while condition1:
statement1
⋮
if condition2:
statements
break #Premature exit from the loop
⋮
Statementn
When condition1 evaluates to False, the loop terminates normally, but when condtion2
evaluates to True, the loop terminates prematurely. The statements written after the break
statement will not be executed. Writing a break statement without a condition is possible,
but that is meaningless as the loop breaks in the first iteration. Example 6.3(a) uses a break
statement to find the sum and average of positive numbers entered by the user until he
enters a negative number.
226
Normal exit Condition
False True
Statements
True
Premature exit Condition
False
Statements
Statements
if count==0:
227
print("You have not entered any positive number")
else:
print("Sum=", total , " and average=", total/count)
Output
We can also prematurely exit from a for loop using a break statement (see figure
6.5). Following is the syntax of a for loop with a break statement.
Example 6.3(b) uses a for loop with a break statement to iterate characters of a string till it
finds a digit in it. The program uses the isdigit() method of the string object to test the
presence of a digit.
Statement2
True
False
Premature exit Condition
Statements
When condtion2 evaluates to True, the loop starts the next iteration without executing the
remaining statements of the loop, i.e., the statements written after the continue statement
are skipped. Writing a continue statement without a condition is valid, but this will make
the statements written after it irrelevant and never get executed. Example 6.4 (a) uses a
continue statement to find the sum and average of only positive numbers entered by the
user. The negative numbers are ignored. Example 6.4 (b) prints a pattern shown in figure
6.7, using a single loop.
Condition
False True
Statements Early next
iteration
True
Condition
False
Statements Normal next
iteration
Statements
230
Example 6.4(a): continue statement
#Find the sum and average of the first three positive numbers
#entered by the user, in a list of positive and negative numbers
count=0
total=0
while(count<3):
n=float(input("Enter a number: "))
if n <0: continue #Skip the statements below, if the condition is true
total+=n
count+=1
if count==0:
print("You have not entered any positive number")
else:
print("Sum=", total , " and average=", total/count)
Output
Enter a number: 2
Enter a number: -1
Enter a number: 5
Enter a number: -2
Enter a number: 2
Sum= 9.0 and average= 3.0
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
Figure 6.7: A triangular pattern
231
Example 6.4(b): Printing a patter using continue statement
#Generate the pattern shown in figure 6.7, using a single while loop
n=int(input("Enter the number of lines in the pattern:"))
col_no = 0
row_no = 1
while(row_no <= n ):
if col_no < row_no: #Print stars in the same line
print("* ", end = "")
col_no += 1
continue
if (col_no == row_no): #Start a new line
print("")
row_no += 1
col_no = 0
Output
By default, a for loop executes the complete body of the loop, starting with the first
statement to the last statement. However, there may be a situation when we need to skip
the remaining statements of the loop's body and begin executing the next iteration of the
loop. The continue statement is used for such a situation in a for loop. There can be more
than one continue statement in a for loop. Following is the syntax of a for loop with a
continue statement.
while condition1:
statement1
⋮
if condition2:
statements
break
⋮
Statementn
else:
Statements
The else part of the loop is only executed on the normal termination of the loop; otherwise,
this part is skipped. Example 6.5(a) uses a while-else loop to print all the prime numbers
between a given range of positive integers.
#Print all the prime numbers between n1 and n2. n1<n2, n1>0
n1=int(input("Enter the value of n1:"))
n2=int(input("Enter the value of n2:"))
print("Prime numbers between", n1, " and ", n2, ":")
while n1 <= n2:
c=2
m=n1//2
while c <= m:
if n1%c==0: #Check divisibility
break
233
c+=1
else:
print(n1, sep=" ", end=" ") #Print in case no divisor found
n1=n1+1
Output
Condition1?
False
True
Statement2
False
Condition2
True Premature
termination
else block: Statements
Normal
termination
Statements
234
for-else loop: Similar to the while loop, a for loop can also have an else statement, which
will be executed only when the loop terminates normally. The else block is not executed if
the loop terminates prematurely. Figure 6.9 shows a flowchart of the for-else loop statement.
The syntax of the for loop with an else statement is as follows:
Statement2
False
Condition
True
Premature
Normal else block: Statements termination
termination
Statements
235
Example 6.5(b) uses a for loop with an else block to test whether a string contains a digit or
not.
237
Outer loop
Condition
True
Body of the inner loop
Statements
Statements
238
while i<=10: #Generate a multiplication table row
print("{0:5d}".format(n1*i), end=" ") #Print a table element
i=i+1
#inner loop ends
n1=n1+1
print() #Go to a new line
#Outer loop ends
Output
for i in range(5):
for j in range(5):
print(i*j, end=" ")
if i*j == 8:
print("\nProgram terminated by the exit() method.")
exit() #Terminate the program execution
print("")
Output
00000
01234
02468
Program terminated by the exit() method.
6.8 Solved Examples
Program 6.1: Write a program to read an integer number from the keyboard and reverse
its digits.
Solution Steps:
1. Read the number and initialize the reversed new number with 0
239
2. Get the last digit of using modulus with 10
3. Remove the last digit using floor division by 10
4. Multiply the new number by 10 and add the last digit
5. Repeat the above process till the original number is greater than 0.
Output
Program 6.2: Write a program to generate the following Fibonacci series up to the nth
term and also find the sum of the series:
1, 1, 2, 3, 5, 8, 13, 21, …
Solution Steps:
1. Read the number of terms
2. Initialize the first two terms, say t1=1 and t2=1 and s=2 (sum of the first two terms)
3. Calculate the next term using t3=t1+t2
4. Update the last two terms using t1=t2 and t2=t3
5. Add the new term to the previous sum
6. Repeat the steps from step 3 and stop if the desired number of terms is generated.
240
t1=t2 #Update the second last terms
t2=t3 #Update the last term
i=i+1 #Increment the loop control variable
print("\nSum of the series: ",s) #Print the final sum
Output
Program 6.3: Write a program to generate the following pattern, up to the specified
number of rows (The column width for both the columns is 10. The first colum left
justified and the second column right justified).
1 1
22 21
333 321
4444 4321
55555 54321
Solution Steps:
1. Read the number of rows
2. For each row, initialize the left and right numbers with the current row number.
3. Start a decreasing counter from the current row number till 1, and for reach counter,
perform the following:
Left_number=Left_number*10+Row_number
Right_number=Right_number*10+counter
4. Print the left and right numbers. Use the left alignment for the left number and the
right alignment for the right number.
241
print(f"{s1:<10d}{s2:10d}")#Left-align s1 and right-align s2
else:
print("Invalid entry")
Output
Enter a digit(1-9): 9
1 1
22 21
333 321
4444 4321
55555 54321
666666 654321
7777777 7654321
88888888 87654321
999999999 987654321
Program 6.4: Write a program to calculate the value of sin(x), accurate up to three
decimal places, using the following sine series:
sin(x) = x – x3/3! + x5/5! – x7/7! …
Solution Steps:
1. Read the value of the angle, x, and convert it to radian
2. Initialise the sum, s=x, and the first term Tn=x
3. Calculate the next term using the following formulae
Tn+1 = - Tn * x * x / ((2n+1) * 2n)
4. Add the new term to the s
5. Repeat steps 3 and 4 till the desired accuracy is attained.
import math
x=float(input("Enter angle, in degree:"))
xd=x
x=x*math.pi/180 #Convert into radian
i=1
tn=x #Initialise the first term of the series
s=x
if x !=0:
242
tnp=-tn*x*x/((2*i+1)*(2*i)) #Calculate the next term of the
series
if abs(tnp/s) < 0.000005: break #Check accuracy
s=s+tnp #Add the new calculated term to the previous sum
tn=tnp #Update the current term for the next iteration
i=i+1 #Increment the loop counter
print(f"Calculated using the series: sin({xd})={s}")
print(f"Calculated using math.sin(): sin({xd})={math.sin(x)}")
else:
print(x)
Output
Program 6.5: Write a program to print the binomial coefficients table. The formula for
the binomial coefficients is
𝑛!
𝐵(𝑛, 𝑚) =
(𝑛 − 𝑚)! 𝑚!
Solution Steps:
1. Read the number of rows, r.
2. Print the heading
3. For each n in the range 0 to r, repeat the following:
3.1 Initialise the binomial coefficient, b=1, and print it.
3.2 For each m in the range 1 to n, repeat the following:
3.2.1 Calculate the next coefficient using the formula b = b(n-m+1)/m
3.2.2 print the next coefficient
3.3 Print a line break
import math
r=int(input("Enter the value of rows(<=10):"))
print(" n\m", end='')
for n in range(r+1): #Print heading
print(f"{n:4d}",end='')
print("")
for n in range(r+1): #Iterate over each row
243
b=1 #Initialize the binomial coefficient for the row
print(f"{n:4d}{b:4d}",end='')
for m in range(1,n+1): #Iterate over each coefficient in the row
b=int(b*(n-m+1)/m) #Calculate the next coefficient
print(f"{b:4d}", end='') #Print
print("")
Output
Program 6.6: Write a program to print a histogram using asterisks to visualize the
following employee's data.
Group No. of employees
Group-1 10
Group-2 15
Group-3 25
Group-4 20
Group-5 12
Solution Steps:
1. Read the histogram data
2. Normalise the histogram data on a scale of 50. For this, divide the histogram data by
the maximum value into the data and then multiply by 50.
2. Generate a string containing asterisks in proportion to the value of the group.
3. Print the histogram strings
244
#Read the number of groups
g=int(input("Enter the number of groups:"))
list1=[]
m=-1
#Read the histogram data
for n in range(g):
x=int(input(f"Enter the number of employees in Group-{n}: "))
list1.append(x)
if m<x: m=x
list2=[]
#Normalise the histogram data
for n in range(g):
list2.append(int(list1[n]*50/m))
Output
Program 6.7: Write a program to graphically print the shape of a sine wave, a sin(t), for
0<=t<=2p in a step 0.25, in the console.
Solution Steps:
1. Read the sine wave amplitude, a, and initialise time, t=0
245
2. Repeat till t <= 2p
2.1 Calculate the value of wave, y, at time t
2.2 If y > 0
2.2.1 Add spaces up to the center line
2.2.2 Add a center mark, #
2.2.3 Add a hyphon up to the wave value
2.2.4 Add an asterisk at the value of the wave
2.3 Else
2.3.1 Add spaces up to the wave value
2.2.2 Add an asterisk at the wave value
2.2.3 Add a hyphon up to the center line
2.2.4 Add a center line mark, #
2.4 Increment t
Output
246
Program 6.8: Write a program to read a list of numbers from the console and find their
mean, µ, and standard deviation, s, using the following formulae:
𝑛
𝜇 = ∑ 𝑥𝑖
𝑖=0
∑(𝑥𝑖 − 𝜇)2
𝜎=√
𝑛
Solution steps:
1. Read the total number of data and read them and store them in a list.
247
2. Calculate the sum and mean
3. Calculate standard deviation
import math
n=int(input("Enter number of data: "))
data=[]
for i in range(n): #Read data
x=float(input("Enter data: "))
data.append(x)
s= sum(data) #Find the sum
avg = s/n #Find mean
sd=0
for i in range(n):
sd=(data[i]-avg)**2
sd=sd/n
sd=math.sqrt(sd) #Find standard deviation
print("Mean=",avg,"Standard deviation=", sd)
Output
Chapter Summary
248
4. The number of iterations in a while loop depends on the looping condition. In
contrast, the number of iterations in a for loop is decided by the number of
elements in the collection.
5. In Python, any non-zero value and any non-empty collection are considered
True. Otherwise, it is deemed to be False.
6. When there is only one statement in the body of a while loop, the statement can
be written in the same line after the colon of the loop. This form of the for loop
is called the shorthand while loop.
7. We can combine many statements with a semi-colon (;) to make a single
compound statement. The Python interpreter treats a compound statement as
a single statement.
8. An infinite loop is a loop that never terminates. For example, a while loop can
be made to loop infinitely by using a conditional expression that always
evaluates to true, such as any non-zero constant, non-empty collection, or True.
However, there should be some mechanism to break such loops to make them
useful in practice.
9. A for loop iterates over each item of a collection or a sequence.
10. The break statement is used for premature exit from a loop.
11. The continue statement is used in a loop to skip the remaining part of the loop's
body
12. We can write the pass statement to create a blank loop body.
13. Both while loop and for loop can have an else block that executes when the loop
ends normally. In other words, the else block does not execute if the loop
terminates prematurely by a break statement.
14. Python allows using a loop inside another loop, called the nesting of loops.
249
c. Multi-way
d. All of these
5. Which of the following statement is used to start the next iteration of the loop?
a. next
b. break
c. continue
d. None of these
250
8. Which of the following terminates the execution of a program?
(a) break
(b) pass
(c) exit
(d) None of the above
9. The statement for x in range (5): print ("Hello") will print Hello how many
times?
(a) 4
(b) 5
(c) 0
(d) None of the above
10. What is the output of the statement for x in range (1,5): print (x, end=" ")?
(a) 1 2 3 4
(b) 1 2 3 4 5
(c) 0 1 2 3 4
(d) None of the above
(a) -1, 0, 1, 2
(b) -1
(c) -1 0 1 2
(d) None of the above
251
(b) 5
(c) 6
(d) 7
(a) 5
(b) 4
(c) 9, 5
(d) 10, 5
(a) 5
(b) 4
(c) 3
(d) None of the above
(a) 4
252
(b) 5
(c) 6
(d) None of the above
i=1
for x in range(1,3):
for y in range(1,3):
i=i*2
print(i)
(a) 8
(b) 16
(c) 32
(d) None of the above
(a) 4
(b) 5
(c) 20
(d) None of the above
253
19. What is the output of the following program?
for x in range(10):
for y in range(2,x//2):
if x%y==0 : break
else: print(x)
(a) 0,1,2,3,4,5,7,
(b) 0,1,2,3,5,7,
(c) 1,2,3,5,7,
(d) None of the above
20. To traverse each item of a list containing ten items, which of the following
range() expression would generate the correct list indices?
(a) range(1,10)
(b) range(10)
(c) range(0,9)
(d) range(1,11)
21. How many iterations the for loop in the following program will perform?
a=[1,2,3,4]
i=4
for x in a:
print(x)
i=i+1
a.append(i)
(a) 4
(b) infinite
(c) 3
(d) None of the above
Review Questions
for i in range(1,50,3):
print(i)
12. Replace the inner for loop with an equivalent while loop in the following
program
for x in range(10):
if x==0: continue
for y in range(2,x//2+1):
if x%y==0 : break
else: print(x, end=',')
13. Write the outputs of the following program:
numbers = [2, 3]
items = ["Chair", "Table"]
255
for x in numbers:
for y in items:
print(x*y)
14. Write the outputs of the following program:
for c in 'Python':
if c == 'o':
pass
print(c, end=", ")
15. Write the outputs of the following program:
for num in range(5, 10):
for i in range(2, num):
if num%i == 1:
print(num)
break
16. Write the outputs of the following program:
x=0
while (x < 20):
x+=2
print(x)
17. Write the outputs of the following program
x=5
for i in range(5):
for j in range(2, 10, 1):
if x % 2 == 0:
continue
x += 1
x+=1
else:
x+=1
print(x)
18. What is the output of the following program?
x=0
for i in range(10):
for j in range(-1, -10, -1):
x += 1
print(x)
19. There are five syntax errors in the following program. Find these errors.
256
x=5
for i=0 in range(5)
for j in range(2, 10, 1);
if x % 2 = 0:
continue
x += 1
x+=1
else:
x+=1
print(x)
20. There is a logical error in the following prime number generation program. Find
the error.
for x in range(1,20):
for y in range(2,x//2):
if x%y==0 : break
else: print(x)
Programming Assignments
1. Write a program to read a list of numbers and create and print another list containing numbers
divisible by ten from the original list.
2. Write a program to read a tuple of numbers. Iterate over the tuple and stop printing numbers on
the first occurrence of 7 in the tuple.
3. Write a program to display characters present at the even positions of the string "Wonderful
World". (Note: a space is a character in a string.)
4. Write a program to find the factorial of a number using a loop.
5. Write a program to read a string and print the count of character 'a' in the string ( For example,
if the input string is 'alphabet', the count of 'a' is 2)
6. Write a program to read a string consisting of capital letters, small letters, numbers, and other
characters and print their counts.
7. Write a program to read a list of n numbers. Iterate over the list and print the division of
consecutive numbers of the list. However, if the division by zero occurs, break the loop.
8. Print the following pattern:
54321
4321
257
321
21
1
259
260
Chapter 7
User-defined Functions
Learning Outcomes
7.1 Introduction
Certain operations or calculations, such as finding factorials of a number, are
repeatedly used at different points in a program, and it is valid that we can repeat the same
code at different places. However, a better design approach is writing functions and calling
them at places where they are needed. Example 7.1(a) shows a program to find the value of
nCr for given values of n and r, without using a function, whereas example 7.1(b) shows a
program to find nCr using a function. As can be seen from these two programs, the program
using a function is more compact and modular than the program without a function.
#Calculate n!
factn=1
for i in range(1,n+1):
factn=factn*i
#Calculate r!
factr=1
261
for i in range(1,r+1):
factr =factr*i
#Calculate (n-r)!
factn_r=1
for i in range(1,n-r+1):
factn_r =factn_r*i
#Calculate nCr
ncr=factn/(factr*factn_r)
print("nCr=", ncr)
Output
#main program
n,r=eval(input("Enter values of n and r"))
print("nCr=", ncr)
Output
Enter values of n and r5,2
262
nCr= 10.0
One of the main reasons for the popularity of Python is the availability of many
built-in functions and a large number of functions in the form of modules that can be
imported and used. We have already used functions from the math and cmath modules in
chapter 4. Despite a huge collection of Python functions, sometimes we need to create our
functions, called user-defined functions. Functions are classified as built-in functions,
module functions, and user-defined functions.
Built-in functions: Built-in functions, such as print (), range (), int (), are part of the Python
interpreter, and they do not require importing any module. They are available in every
program.
Module functions: Module functions are defined in modules, and the respective module
must be imported into a program before using these functions. Examples of module
functions are math.sqrt(), math.sin().
Figure 7.1 shows a flowchart of the program given in example 7.1(b). As shown in
the flowchart, on a function call, the program flow control goes to the function (shown in
dashed curves) and executes it. After completing the function execution, the program
control returns back to the calling program's next instruction.
263
fact(n)
Start
r=1
Input n, r i=2
factn=fact(n)
If i<=n
No
factr=fact(r) Yes
r=r*i
Factn_r=fact(n-r)
i=i+1
nCr=factn /(factr * factn_r)
Input n, r Return r
Stop
(a) Flow chart for nCr (main program) (b) Flow chart for factorial (Called function)
Figure 7.2 shows the modular programming approach using functions, where a
large program uses many small functions. In figure 7.2, the program is divided into six
modules: the main program and five functions. In this approach, a function can be called
by different functions; for example, function 4 is being called by the main program and
function 3. When a function calls itself, it is called a recursive function. Following are some
advantages of using functions in computer programming:
264
Since the code in a sub-program is short, it is simple and easy to understand. Further, it
is easy to maintain such programs. It is also easy to identify errors as they are localized
to a function.
2. Since the code of a function is not repeated in the calling program, the overall size of the
program is smaller.
3. Once a function is defined and tested, it can be reused in other programs also.
Main program
Function 1
Function 2 Function 3
Function 5
Function 4
1. Function definition begins with the def keyword followed by the function name
followed by parentheses ( ). After the parentheses, a colon (:) is written. The
statement starting from def and up to the colon is called the header of the function.
2. A function can have zero or more input parameters. The input parameters of the
function are written inside a parenthesis, separated by commas.
265
3. The statements below the function header are known as the body of the function.
All the statements of the body are indented.
4. It is a good programming practice to document the basic details of a function.
Python uses the first string literal written just below the function header as a
docstring. This docstring is shown when a user seeks help for a function. However,
the docstring is optional.
5. Normally, the last statement of a function body is return [expression], which ends
the function and returns the expression value to the calling program. The expression
in a return statement is optional. If no expression is given, the function returns None.
The return statement is optional. In this situation, the function automatically returns
None. Further, we can have more than one return statement in a function. The
execution of a function will end at the first return statement.
In Python, a function can be defined anywhere in a program, but the function must
be defined before its first use (call). A function can also be defined on the command prompt.
Example 7.2(a) shows a function to sum two numbers on the prompt. Example 7.2(b) shows
a function to print "Hello World. I love Python" five times on the console.
>>> mysum(2,3)
5
>>> help(mysum)
Help on function mysum in module __main__:
mysum(a, b)
mysum(a,b) returns total of two numbers
>>>
266
Example 7.2(b): Defining and using a function
#Main program
for i in range(5):
print_hello() # Calling the function
Output
Hello World. I love Python
Hello World. I love Python
Hello World. I love Python
Hello World. I love Python
Hello World. I love Python
The term parameter is used when defining a function and is the name of an input
variable of a function. On the other hand, the term argument is used when we call a function
in a program, i.e., arguments are the values passed to the function during calls. For example,
in example 7.2 (a), the function has two parameters, namely a and b. When we call the
function, the arguments are 2 and 3, corresponding to the parameters a and b. In example
7.2(b), the function has no parameter and no argument. However, in most of the text, the
terms parameter and argument are used interchangeably, including this book. Python
supports the following types of input parameters to a function:
1. Positional parameters
2. Parameters with default values
3. Keyword arguments
267
4. Variable number of parameters
Positional parameters are the parameters that are mapped to the arguments
according to their positions. There is one to one mapping between the parameters and
arguments in order of their positions, i.e., the first argument's value is assigned to the first
parameter, the second argument's value to the second parameter. In other words, the
arguments passed to a function are in the same order as they are defined in the function. If
the number of parameters does not match the number of supplied arguments, an error is
generated. Example 7.3(a) illustrates the concept of positional parameters. The missing
positional argument error is generated in case of a mismatch between parameters and
arguments.
>>> myfun(2,3,4)
10
>>> myfun(2,3)
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
myfun(2,3)
TypeError: myfun() missing 1 required positional argument: 'c'
>>>
268
>>> def greet(name="Ram", msg="Hello"):
print(msg,",",name)
return
>>> greet("Ram")
Good morning Ram
>>> greet("Ram", "Good Afternoon")
Good Afternoon Ram
>>> def greet1(msg="Good morning", name):
The values to the positional arguments of a function are passed on in the sequence
they are written in the function definition. However, Python allows to call a function to pass
arguments in any order by using the name of the function parameters as keywords and
assigning values to them during function calling. For example, consider the header of a
function def myFun(a, b):, the parameters a and b of the function are keywords and the
function can be called as myFun(b=10, a=5), which is equivalent to myFun(5, 10). This way
of calling a function is called key-value pair mechanism to call a function.
269
This key-value pair mechanism to call a function can be used for parameters with or
without default values. The key-value and positional arguments can also be used together,
but key-value arguments must follow all the positional arguments. It is valid to pass values
some as positional arguments, some as keyword arguments, and remaining with default
values. Example 7.3(d, and e) shows some examples of keyword arguments.
270
7.3.4 Variable Number of Parameters
Syntax 1:
Syntax 2:
def function_name([formal_args,] **var_kargs):
"function docstring"
Statements
return [expression]
Here, formal_args are the positional arguments, and they must precede the variable
number arguments. In syntax 1, the parameter *var_args accepts a variable number of
arguments and converts them into a tuple. It is similar to positional arguments, and the
values of the arguments are available in the order they are given in the function call.
Whereas, in syntax 2, the parameter **var_kargs accepts a variable number of keyword
arguments and converts them into a dict object. It is similar to the key-value pair
arguments, and the values of the arguments can be accessed as key-value pairs. Please note
the use of single and double asterisks in variable number arguments. Example 7.3(f)
illustrates the concepts of the variable number of positional arguments, and example 7.3(g)
shows the variable number keyword arguments. It is valid to combine formal positional
arguments, variable arguments, and variable keyword arguments in a function definition.
However, we have to give arguments in the following sequence: (1) formal arguments, (2)
variable number positional arguments, and (3) variable number keyword arguments.
Example 7.3(h) illustrates the above.
271
Example 7.3(f): Variable length positional arguments
>>> mySum(1,2)
3
>>> mySum(1,2,3,4)
10
>>> mySum(1,2,3,4,5,6,7)
28
>>> myFun(name="Ram")
name == Ram
>>> myFun(name="Ram",age="10")
name == Ram
age == 10
>>> myFun(name="Ram",age=10)
name == Ram
age == 10
>>> myFun(FirstName="Ram", SecondName="Singh", age=20, weight=60.5)
FirstName == Ram
SecondName == Singh
age == 20
weight == 60.5
>>>
272
Example 7.3(h): Using different types of arguments together
In Python, we can pass any data type, such as float, int, complex number, string, list,
tuple, dict, as arguments to a function, and it will be available as the same type in the
function. Example 7.4(a) illustrates this.
273
Example 7.4(a): Calling a function with different types of data
>>> myFun([1,2,3],(4,5,6),{"a":7,"b":8},{1,2,3})
<class 'list'> : [1, 2, 3]
<class 'tuple'> : (4, 5, 6)
<class 'dict'> : {'a': 7, 'b': 8}
<class 'set'> : {1, 2, 3}
>>>
When a function has only positional arguments without default values, the number
of simple and expanded arguments passed must match the number of parameters of the
function; otherwise, an error will be generated (see example 7.4(d).
274
Example 7.4(b): Expanded list, tuple, and dictionary as function arguments
Example 7.4(c): A function with a few positional parameters and a variable number
parameter
275
>>> myFun(*[1,2,3],*(4,5),6,7)
1 2
3 4 5 6 7
>>>
Example 7.4(d): A function with only positional parameters and function calling with
simple and expanded arguments
>>> myFun(*[1,2,3])
1 2 3
>>> myFun(1,*[2,3])
1 2 3
>>> myFun(*[1,2])#Error due to less number of arguments
Traceback (most recent call last):
File "<pyshell#53>", line 1, in <module>
myFun(*[1,2])
TypeError: myFun() missing 1 required positional argument: 'c'
>>> myFun(*[1,2,3,4]) #Error due to excess number of arguments
Traceback (most recent call last):
File "<pyshell#54>", line 1, in <module>
myFun(*[1,2,3,4])
TypeError: myFun() takes 3 positional arguments but 4 were given
>>>
276
Example 7.5: Local and global functions
print(fun1(1,2,3))
print(fun2(4)) #Calls global function
Output
Using local function
Using local function
Using local function
12
Using global function
16
277
Example 7.6(a): Local Variables
>>> myFun(5)
15
>>> print(a) #a is not available here
Traceback (most recent call last):
File "<pyshell#98>", line 1, in <module>
print(a)
NameError: name 'a' is not defined
>>> print(x) #x is not available here
Traceback (most recent call last):
File "<pyshell#99>", line 1, in <module>
print(x)
NameError: name 'x' is not defined
>>> myfun(20)
10 20
10 20
278
Example 7.6(c): Global Variables
>>> myFun(5)
15
>>> print(a) #Using a global variable in the main program
10
However, to change the value of a global variable inside a function, we need to use
the global keyword (see example 7.6(d).
Without the global keyword, the interpreter will create a new local variable with the
same name, which will shadow the global variable in the function, and any change in the
variable will not affect the global variable. Further, once a local variable is created in a
function, a global variable with the same name cannot be used directly, even before the
point of creation of the local variable (see example 7.6(e)).
279
Example 7.6(e): Global Variable
>>> print(a)
10
>>> myFun(5)
Traceback (most recent call last):
File "<pyshell#132>", line 1, in <module>
myFun(5)
File "<pyshell#129>", line 2, in myFun
print(a+b)
UnboundLocalError: local variable 'a' referenced before assignment
However, we can access and modify a global variable and a local variable with the
same name in a function using the globals() built-in method simultaneously. The globals()
method returns all the global variables as a dictionary. The global variable is used as a global
directory item, and the local variable is used directly. After returning from the function, the
global variable can be used directly (see example 7.6(f)).
Example 7.6(f): Local and global variables with the same name
Normally, a global variable once created remains in the memory until the program's
execution. However, we can delete a variable using the del keyword. Once a variable is
deleted, it is no more available in the program; see example 7.6(g)
280
Example 7.6(g): Deleting a global variable
281
memory is allocated to it. Thus, a variable with an immutable value passed as an argument
of a function will never change its original variable in the calling program. See example
7.7(a), where an immutable argument is passed to a function. Please note the ids of the
argument and its corresponding variable in the function. As can be seen, the ids of the
arguments and the related variables are the same before the assignment (behaves like pass-
by-reference), but after the assignment, they are different (behaves like pass-by-value).
>>>
>>> x,y,z=10,(1,1,1),"David"
>>> print(x,id(x),"\n", y,id(y),"\n", z, id(z))
10 2105591622224
(1, 1, 1) 2105632687232
David 2105632753904
>>> myFun(x,y,z)
Values and ids before assignment:
10 2105591622224
(1, 1, 1) 2105632687232
David 2105632753904
282
When we pass a mutable object, such as a list, a dictionary, and a set, it is treated as
a pass-by-reference argument. If the function modifies its parameters, the corresponding
argument in the calling program is also updated with the new value; see example 7.7(b).
>>> a=[1,2,3]
>>> print(a,id(a))
[1, 2, 3] 2422402427904
>>> myFun(a)
[1, 2, 3] 2422402427904
[1, 2, 3, 4] 2422402427904
>>> print(a,id(a))
[1, 2, 3, 4] 2422402427904
>>>
However, if we assign a new mutable object to the passed argument in the function,
the corresponding calling variable is unaffected. Hence, it behaves like a call-by-value
argument; see example 7.7(c).
Example 7.7(c): Calling a function with a list and performing assignment operations
>>> a=[1,2,3]
>>> print(a, id(a))
[1, 2, 3] 2422407557824
>>> myFun(a)
[1, 2, 3] 2422407557824
[4, 5, 6] 2422407690112
>>> print(a, id(a))
[1, 2, 3] 2422407557824
>>>
283
Further, if we are using a compound assignment operator, the behavior of the
passed argument is again like a pass-be-reference, and changes are available in the calling
program; see example 7.7(d). The same is true for sets and dictionaries; see example 7.7(e).
The set and dictionary do not support compound assignment operators.
Example 7.7(d): Calling a function with a list and performing compound assignment
operations
>>> s={1,2,3}
>>> d={1:"One",2:"Two"}
>>> print(id(s),s,id(d),d)
2422407519808 {1, 2, 3} 2422407726784 {1: 'One', 2: 'Two'}
>>> myFun(s,d)
2422407519808 {1, 2, 3} 2422407726784 {1: 'One', 2: 'Two'}
2422407519808 {1, 2, 3, 4} 2422407726784 {1: 'One', 2: 'Two', 3:
'Three'}
>>> print(id(s),s,id(d),d)
2422407519808 {1, 2, 3, 4} 2422407726784 {1: 'One', 2: 'Two', 3:
'Three'}
284
The change in a calling variable by a function is known as the function side effect.
If it is not desirable, we can pass a shallow copy of a variable to a function. A shallow copy
of a variable can be created using a colon operator; for example, for a list variable x=[1,2,3,4],
a shallow copy of x is created as x[:]. Example 7.7(f) illustrates the above concepts.
Example 7.7(f): Passing a shallow copy to a function to avoid the function side effect
>>> a=[1,2,3]
>>> print(a, id(a))
[1, 2, 3] 2930492433344
>>> myFun(a[:]) #Passing a shallow copy of a list
[1, 2, 3] 2930487176512
[1, 2, 3, 4, 5, 6] 2930487176512
>>> print(a, id(a)) #The original list is not affected
[1, 2, 3] 2930492433344
>>>
>>> s=mySum(10,20)
>>> print(s)
30
>>> a,b=10,20
>>> a,b= swap(a,b)
285
>>> print(a,b)
20 10
If no expression is written with the return statement, the None value is returned to
the calling program (see example 7.8(b)). Even if we are not writing a return statement in a
function, the function returns the None value to the calling function (see example 7.8(c)).
As stated earlier, a function may return multiple values to the calling program. The
returned values may be of any data type and may be assigned to variables in the calling
functions or ignored. If multiple returned values are assigned to a single variable, the values
are stored as a tuple. However, if returned values are assigned to different variables, the
number of variables should be equal to the number of returned values. The miss-match in
numbers (either less or more) raises unpacking errors. The unpacking error is avoided using
286
dummy variables (typically, an underscore, _ , is used as a dummy variable name) to match
the number of returned values and the variables. Example 7.8(d) illustrates various
situations of multiple values returned from a function.
>>> a,b,c=10,20,30
>>> x=cycle(a,b,c) #Returned as a tuple
>>> print(x, type(x))
(20, 30, 10) <class 'tuple'>
A function can return any data type, such as numbers, strings, lists, tuples, sets,
dictionaries. Example 7.8(e) illustrates returning values of various data types by a function.
287
Example 7.8(e): Returning different types of values from a function
>>> a,b,c,d,e=myFun()
>>> print(a,type(a))
[1, 2, 3] <class 'list'>
>>> print(b,type(b))
(1, 2, 3) <class 'tuple'>
>>> print(c,type(c))
{1, 2, 3} <class 'set'>
>>> print(d,type(d))
{1: 'One', 2: 'Two'} <class 'dict'>
>>> print(e,type(e))
Python <class 'str'>
>>>
288
>>> a,b=10,20
>>> compute(mySum, a,b) #The first argument is a function object
30
>>> compute(myProd, a,b)#The first argument is a function object
200
>>> fact(5)
120
289
When we call the fact function (example 7.10) with a positive integer, it calls itself
recursively. Each time argument is decreased by 1. The recursive call ends when the
argument reaches 1. There is no further recursive call at the base condition, and the function
starts to return value to its previous call and reaches the first call, and returns the factorial
value of the passed number. The whole process is illustrated below:
The recursive function has many advantages, such as reducing a complicated task
into simpler repetitive subtasks, which reduces the requirement of nested iterations. The
recursion makes codes simpler and compact. However, a recursive function takes a lot of
memory and has a significant function calling overheads. A recursive function usually is
challenging to debug.
where p1, p2, …, pn are the function parameters, and expression is a valid python
expression. Example 7.11(a) creates a lambda function to evaluate the expression
𝑓(𝑥, 𝑦) = 𝑥 2 + 𝑦 2 + 𝑥𝑦
290
As can be seen from Example 7.11(a), there is no function name in a lambda function,
and there is no return statement. Since only one expression is permitted in a lambda
function, its value is returned. A lambda function can be used anywhere a function is
required. They are frequently used with built-in functions, such as filter, map, and reduce.
A lambda function can be used with the filter function to select the elements of a list
which returns a true value from the lambda function. For example, to get all the even
numbers from a list of integers, see example 7.11(b). The filter function evaluates the
specified Lambda function iteratively for each element of the list and returns the true
elements as a filter object. The list function can be used to convert a filter object back into a
list.
Similarly, a Lambda function can also be used with the map function to evaluate the
function for all the elements of lists. For example, to get a list that consists of the sum of the
corresponding elements of two lists (See example 7.11 (c)).
>>> a=[1,2,3,4,5]
>>> b=[6,7,8,9,10]
>>> #Calling the function for each pair of the lists
>>> c=list(map(lambda x,y:x+y, a,b))
>>> c
[7, 9, 11, 13, 15]
>>>
n += 1
print('This is printed second')
yield n #The second call returns from here
n += 1
print('This is printed at last')
yield n #The Last call returns from here
Output
This is printed first
10
This is printed second
11
This is printed at last
12
Traceback (most recent call last):
File "D:/akv/akv/Python_book/Chapter 4/se5.py", line 20, in <module>
print(next(gen_obj)) #Error: Trying to access element beyond the
last element
StopIteration
292
The generator function differs from the normal function in the following ways:
i. When we call a normal function, it starts executing its code immediately; whereas a
generator function only creates a generator object. On calling the next method, the
code of the generator function gets executed.
ii. The normal function returns values using the return statement; whereas the
generator function uses a yield statement to return value. A generator function can
have more than one yield statement. We can iterate from one yield to the next yield
statement using the next () method. Once a generator function yields a value, the
function is paused and the control is transferred to the calling program.
iii. Local variables and their states are remembered between successive calls in a
generator function; whereas a normal function kills its local variables on returning
from the function.
We can use a generator function in a for loop to directly get the values generated by the
function. The next () method is automatically called during the looping. Example 7.12(b)
uses a generator function to generate a sequence of numbers.
2
5
8
>>>
293
operating system are known as command line arguments. For example, the command
D:\>python test_program.py 1 2 3 4 5 runs the program test_program.py from the
command line and 1, 2, 3, 4 and 5 are the command line arguments.
We can access the command line arguments using the variable sys.argv of the sys
module. The sys.argv is a list and contains all the command line arguments, in the sequence
given at the command line. The first item, i.e., sys.argv[0], is the name of the python
program. Other items are the arguments. We can use len(sys.argv) to get the total number
of arguments including the name of the script. Example 7.13 illustrates the processing of
command line arguments of a program. The program prints the command line arguments
and find the sum of the arguments passed.
# Arguments passed
print("\nName of Python program:", sys.argv[0])
# Addition of arguments
Sum = 0
for i in range(1, n):
Sum += int(sys.argv[i])
Output
D:\>python test_program.py 1 2 3 4 5
Total number of arguments passed: 6
294
3
4
5
Solution steps:
1. Define the function cyl_vol_sa (r, h):
1.1 Calculate volume, vol, using the formula 𝑣𝑜𝑙 = 𝜋𝑟 2 ℎ
1.2 Calculate surface area, sa, using the formula 𝑠𝑎 = 2𝜋𝑟(ℎ + 𝑟)
1.3 Return vol and sa
2. Read the radius, r, and height, h, of the cylinder.
3. Call the function cyl_vol_sa
import math
#Define function
def cyl_vol_sa (r, h):
""" The cyl_vol_sa(r,h) function calculates volume
and surface area of a solid cylinder"""
#main program
r =float(input("Enter radius of the cylinder: "))
h =float(input("Enter height of the cylinder: "))
295
Program 7.2: Write a function to list all the prefect numbers up to a given number. A
perfect number is a positive integer that is equal to the sum of its proper positive divisors,
that is, the sum of its positive divisors excluding the number itself.
Solution steps:
1. Define the function perfect_numbers (n):
1.1 for each number x in the range 1 and n:
1.1.1 find the divisors of x and sum them
1.1.2 if x is equal to the sum, add number to the list of perfect numbers
1.2 return the list
#Function definition
def perfect_numbers(m):
if m < 0: return "Invalid number"
list_perfect=[]
for n in range(1,m):
sum = 0
for x in range(1, n):
if n % x == 0: #Evaluates to true if x is a factor of n
sum += x
#Add the prefect number into the list
if sum == n: list_perfect.append(n)
#main program
n= int(input("Enter the upper limit:"))
print("Perfect numbers between 1 and ", n," are:", perfect_numbers(n))
Output
Enter the upper limit:1000
Perfect numbers between 1 and 1000 are: [6, 28, 496]
Solution steps:
1. Define the function isPalindrome(word):
1.1 Convert all the characters of word to the lower case
1.2 Initialize the left index to 0 and the right index to the last character.
1.3 while left index < right index:
296
1.3.1 if characters at the left index is different than the character at the right index
Return False
Else
Increment the left index by one
Decrement the right index by one
1.4 Return True as no mismatch found
#Function definition
def isPalindrome(word):
word=word.lower()
left_pos = 0 #Index of the first character
right_pos = len(word) - 1 #Index of the last character
while right_pos >= left_pos:
#Mismatch of characters means not a palindrome.
if not word[left_pos] == word[right_pos]:
return False
left_pos += 1 #Increment the left index
right_pos -= 1 #Decrement the right index
return True #No mismatch found, hence palindrome
#Main program
word=input("Enter the word to check for palindrome: ")
print(f"The word {word} is ", "a palindrome"
if isPalindrome(word)else "not a palindrome")
Output
Enter the word to check for palindrome: Madam
The word Madam is a palindrome
Program 7.4: Write a generator function, genFibonacci (t1, t2, n), to generate a Fibonacci
series starting with t1 and t2 up to the nth term.
Solution steps:
1. Define the function genFibonacci (t1, t2, n):
1.1 Yield the first and the second terms
1.2 while the number of terms < n:
1.2.1 Calculate the next term using t3= t1 + t2
1.2.2 Yield the new term
1.2.3 Update the last two terms using t1=t2 and t2 =t3
3. Call the function, such as genFibonacci (1, 1, 10)
297
#Function definition
def genFibonacci (t1,t2,n):
yield t1 #return the first term
yield t2 #return the second term
i=2
while i < n: #Repeat till nth term
t3=t1 + t2 #Calculate the next term
yield t3 #return the next term
t1=t2 #Update the last two terms
t2=t3
i=i+1 #Increment the loop counter
#Main program
print("Using the function as an iterator")
for x in genFibonacci(1,1,10): #Use the function as an iterator
print(x, end=' ')
Output
Using the function as an iterator
1 1 2 3 5 8 13 21 34 55
Using the function as a normal function
2 5 7 12 19 31 50 81 131 212
Program 7.5: Write a program using lambda function to segregate positive numbers from
a list of numbers and find their sum.
Solution steps:
1. Use the filter method and a lambda function to segregate the positive numbers.
list1= [2,-4,6,2,-6,3] #Original list
#A lambda function used in the filter method
list2 = list(filter( lambda x : x>0, list1)) #Segregated list
print("Original list: ", list1)
print("Segregated list: ",list2)
print("Sum of the positive numbers: ", sum(list2))
298
Output
Original list: [2, -4, 6, 2, -6, 3]
Segregated list: [2, 6, 2, 3]
Sum of the positive numbers: 13
Program 7.6: Write a recursive function to sum the first nth term of the following series:
𝑥 𝑥2 𝑥3 𝑥4
𝑒𝑥 = 1 + + + + +⋯
1! 2! 3! 4!
Solution steps:
1. Define the function myExp (x, n):
1.1 Declare num and denum as global variable
1.2 if n = 0, return 1
1.3 else
1.3.1 r = myExp(x,n-1)
1.3.2 num = num*x
1.3.3 denum = denum * n
1.3.4 return r + num/denum
2. Initialise variables num=1 and denum=1
3. Call the function myExp(3,15)
# Recursive Function to calculate e^x
def myExp(x, n) :
global num, denum #Global variables
#Main program
num = 1.0 # global variable num
denum = 1.0 # global variable denum
x = float(input("Enter value of x: "))
n = int(input("Enter the number of terms to sum: "))
print(f"Using the recursive function: exp({x})=",myExp(x, n))
import math
print(f"Using the math library function: exp({x})=",math.exp(x))
299
Output
Enter value of x: 3
Enter the number of terms to sum: 15
Using the recursive function: exp(3.0)= 20.08553443097081
Using the math library function: exp(3.0)= 20.085536923187668
Program 7.7: Write a function currency2words(currency) that convert the given currency
value (999999999.99) into words using the Indian system.
Solution steps:
1. Read the currency value
2. Separate whole and fraction parts
3. For the whole part, extract numbers at tens (last two digits), hundreds (next one
digit), thousands (next two digits), lakhs ((next two digits) and crores (next two digits).
4. Convert the extracted numbers into words.
5.
# Main Logic
#1 to 9
ones = ('Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven',
'Eight', 'Nine')
#10,11,12,...19
twos = ('Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen',
'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen')
#20,30,40, ...,100
tens = ('Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy',
'Eighty', 'Ninety', 'Hundred')
300
r=number%10 #Get digit at unit position
if r > 0:
word=word + "-" + ones[r] #Combine tens and unit position
words
return word
word=""
if whole == 0 : word = "Zero" #If the whole part is zero
else:
teens= whole%100 #Get the last two digits of the whole part
if teens : word= getWord99(teens) #Convert the last two digits
into words
word1 =getWord99(fraction)
return "Rs " + word + " and " + word1 + " Paisa" #Combine the whole
and fraction parts
#Main program
301
num = float(input("Enter the currency value : "))
print(currency2words(num))
Output
Enter the currency value : 99.23
Rs Ninety-Nine and Twenty-Three Paisa
Chapter Summary
302
7. In Python, functions support the following types of input parameters:
Positional parameters, Parameters with default values, Keyword arguments,
and a Variable number of parameters.
8. In Python, we can pass any data type, such as float, int, string, list, tuple, dict,
as arguments to a function, and it will be available as the same type in the
function.
9. When a function is defined inside another function, it is called a local or nested
function. A function defined outside any other function is called a global
function and is available throughout the code.
10. The variable's scope refers to the parts of a program where the variable is
accessible, and the lifetime of a variable is the period between the time of
variable creation and its killing.
11. A variable created in a function is a local variable, and its accessibility is limited
to the function codes. A variable declared outside any function is a global
variable, and it is accessible (below the point of definition) throughout the
program and every function
12. In pass-by-value, an independent copy of the argument is passed to the
function. Any changes made to that copy have no impact on the original
argument variable. There are separate memories for the argument and the
parameter variables.
In pass-by-reference, the memory reference of the argument variable is passed
to the function. Any changes made to it in the function are available in the
calling function. In other words, the argument variable and the parameter
variable refer to the same data in the memory.
13. In Python, arguments to a function are passed as pass-by-object-reference. In
the pass-by-object-reference, the behavior of the argument changes with
context. The same argument behaves like pass-by-value or pass-by-reference
depending on the way argument is used in the function or the type of the
argument value.
14. A function may return one or more values to the calling function.
15. When a function calls itself, it is called a recursive function
16. An anonymous function, a function without a name, is created with the lambda
keyword in Python. A lambda function can take any number of arguments but
can have only one expression in its body.
303
17. A generator function generates a series of outputs. The function maintains its
last state and, in the next call, continues from there. In other words, it behaves
like an iterator.
304
(c) Arguments can be given in any order
(d) None of the above
9. For the function def myFun (a, b, c): print (a, b, c), which of the following is an
incorrect way to call it?
(a) myFun (1, 2, 3)
(b) myFun (*[1, 2, 3])
(c) myFun (1, *(2,3))
(d) None of the above
10. For the function def myFun (a, b, c): print (a, b, c), which of the following is the
correct way to call it?
(a) myFun (a=1, c=3, b=2)
(b) myFun (*[1, 2, 3])
(c) myFun(**{"a":1,"b":2,"c":3}).
(d) All of the above
305
(c) Inside a function
(d) All of the above
13. In Python, objects are passed to a function using which of the following
mechanism
(a) pass by value
(b) pass by reference
(c) pass by object reference
(d) None of the above
17. A lambda function can be used with which of the following function?
(a) map
(b) filter
(c) reduce
306
(d) All of the above
18. Which of the following is not true for a generator function in Python?
(a) Can have multiple yield statements
(b) Can have a return statement at the end of the function
(c) Can be used with a for loop
(d) None of the above
def myFun(a):
a=100
a=50
print(myFun(a))
(a) 50
(b) 100
(c) None
(d) None of the above
def myFun(a):
a=100
a=50
myFun(a)
print(a)
(a) 50
(b) 100
(c) None
(d) None of the above
307
22. What is the output of the following program?
def myFun(x):
global a
a=100
a=50
myFun(a)
print(a)
(a) 50
(b) 100
(c) None
(d) None of the above
x=10
def myFun():
x=x+10
return x
print(myFun()
(a) 10
(b) 20
(c) Error: local variable 'x' referenced before assignment
(d) None of the above
def genFun(end):
i=0
while(i<=end):
yield i
i=i+1
for x in genFun(3):
print(x,end=' ')
(a) 0 1 2
308
(b) 1 2 3
(c) 0 1 2 3
(d) None of the above
25. Which of the following is the correct way to call the following function?
Review Questions
309
p. A Python function always returns a value.
q. We can pass a function as an argument to a function.
r. Python does not support recursive functions.
s. A lambda function can have only one parameter and one expression.
t. A generator function maintains its last state.
u. We can pass arguments to a program at the command line.
z= lambda x: (x,2*x)
print(z(2))
z=lambda x: x, 2*x
310
print(z(2))
x = 10
def f ():
x = x + 10
print(x)
f()
def myFun(*var):
return sum(var)
print(myFun(1,2,3,4,5))
def myFun(x):
while(1):
yield x
x=x+1
311
for a in myFun(2):
print(a)
Programming Assignments
1. Write a Python function to calculate the area of a hexagon with given side length.
3. Write a Python function that takes 2 positive integer values and returns the
highest common factor of the numbers.
4. Write a Python function that takes two numbers as its arguments and returns
sum and multiplication of these numbers.
7. Write a Python function to calculate nCr. Define an inner factorial function in the
function.
9. Write a Python function to accept three arguments and check whether the last
argument falls within the range of the first two arguments.
10. Write a Python function that accepts a string and counts the number of upper-
case, lower-case letters, digits and other symbols.
11. Write a Python function that returns a new list with distinct elements from the
argument list.
12. Write a Python function to checks whether the given number is prime or not.
312
13. Write a Python function that returns all the prime numbers between a given
range.
14. Write a Python function to check whether a number is "Perfect" or not. A perfect
number is a positive integer that is equal to the sum of its factors excluding the
number itself.
15. Write a Python function that checks whether a given word is a palindrome or
not. A palindrome is a word that reads the same backward as forward, e.g.,
madam.
16. Write a Python function to check whether a given string is a pangram or not. A
pangram is a string that contains every letter of the alphabet at least once. For
example: "The quick brown fox jumps over the lazy dog.". It may contain other
symbols also.
17. Write a Python function that accepts variable number of arguments and find
their average.
18. Write a Python function that takes a string and check whether the given string is
a valid email address without using any library. Use the following check rules:
• Must contain at least 1 character before the @ symbol
• Must contain an @ symbol
• Must have at-least 1 character after the @ symbol and before the period(.)
• Must contain at least 1 character after the last period(.).
• Maximum 256 characters
• Must start with a letter or a number
313
314
Chapter 8
Lists
Learning Outcomes
A list is a built-in data structure used to store several Python objects, for example, list1=
[1, 2, 3, 4]. The individual item of a list can be of different types, for example, list2= [1,
"Python", [1,2,3], (4,5,6)], which consists of an integer, a string, a list, and a tuple. A list of
lists is called a nested list, for example, [ [1,2,3], [4,5,6], [7,8] ]. Since a list is an ordered
sequence of items, individual items can be accessed with an index. For example, list2[1] will
return the second element of the list, i.e., "Python". In Python, the index starts with zero,
i.e., the index of the first element of a list is 0. A list is dynamic and mutable in nature, as
items in the list can be inserted, deleted, and modified at any time in the program.
315
Example 8.1(a): Lists from data
The built-in list () function converts sequence data, such as a string, a tuple, a range,
a set, into a list. The syntax of the function is as given below:
list_var=list(sequence)
where sequence is any iterable data or variable, such as a string, a tuple, a list, a set, a
dictionary, a range. When a string is passed to a list function, it returns a list of its characters.
When a tuple is passed as the argument of a list function, the function returns a list of its
items/elements. When a dictionary object is passed to a list function, the function returns a
list of the keys of the dictionary object, and the values are ignored. If we pass non-iterable
data, such as an integer, a float, a complex, an error is generated. For example, the
316
expression list(10) generates TypeError: 'int' object is not iterable. Example 8.1(b)
illustrates the list () function to convert the various types of iterable objects into lists.
Example 8.1(b): Convert the various types of iterable objects into lists
>>> string="Python"
>>> list1=list(string) #Convert a string into a list of its characters
>>> print(list1)
['P', 'y', 't', 'h', 'o', 'n']
>>> tuple1=(1,2,3)
>>> list2=list(tuple1) #Convert a tuple into a list
>>> print(list2)
[1, 2, 3]
>>> set1={1,2,3,4,1} #Convert a set into a list
>>> list1=list(set1)
>>> print(list1)
[1, 2, 3, 4]
>>> dict1={1:"One",2:"Two"} #Convert a dictionary into a list of its
keys
>>> list1=list(dict1)
>>> print(list1)
[1, 2]
>>> range1=range(1,5)
>>> list1=list(range1) #Convert a range object into a list
>>> print(list1)
[1, 2, 3, 4]
>>> list1=list(["One", "Two", "Three"]) #Convert a list into a list
>>> print(list1)
['One', 'Two', 'Three']
>>> c=2+3j
>>> c
(2+3j)
317
>>> list(c) #Error: cannot pass atomic data
Traceback (most recent call last):
File "<pyshell#37>", line 1, in <module>
list(c)
TypeError: 'complex' object is not iterable
>>>
where input_seq is the original collection of items, exp_x is an expression of x. The value of
exp_x is added to the new output_list only if the conditional expression x-condition
evaluates to true. The if condition block is optional. If it is not specified, then the values of
exp_x corresponding to all the elements of input_seq will be added to the output_list. In
example 8.1(e), a list is generated containing the squares of the elements of the given list.
318
Example 8.1(d): Selecting some elements from a list using the list comprehension
Example 8.1(e): Generating a list consisting of the squares of the elements of a list
The list comprehension can be used with other sequence data also. Example 8.1(f)
shows list comprehensions with different types of sequence data.
319
list3=[x for x in range(50) if x%2==0 and x%5==0]
print("A list from a range:", list3)
Output
A list from a string: [80, 121, 116, 104, 111, 110]
A list from a range: [0, 10, 20, 30, 40]
A list from a tuple: [1, 4, 2, 5]
A list from a set: [2, 6]
A list from a dictionary [[1, 'One'], [2, 'Two']]
A string can be split into a list of its word using the split method of the str object.
For example, the expression "I love Python".split() evaluates to a list ['I', 'love', 'Python'].
Example 8.1(g) reads a string from the keyboard and counts the number of words in it.
320
Example 8.1(g): Count the number of words in a text
Output
Enter the string:I love Python Programming. It is very simple but
powerful.
The number of words in the string is: 10
Forward index 0 1 2 3 4
List 10 20 30 40 50
Backward index -5 -4 -3 -2 -1
List_object[index]
321
Where List_object is a list object and index is an integer. If the index is a positive integer,
forward indexing is used; otherwise, backward indexing is used. Example 8.2(a) shows how
an element of a list is accessed. The number of elements in a list is obtained by the built-in
function len(list_obj). The maximum value of the valid index value is equal to
len(list_object) -1.
>>> list1=[10,20,30,40,50]
>>> list1[0] #Accessing the first element of a list
10
>>> list1[1] #Accessing the second element of a list
20
>>> list1[-1] #Accessing the last element of a list
50
>>> list1[-2] #Accessing the second last element of a list
40
>>> list1[-5] #Accessing the first element of a list
10
>>> list1[4] #Accessing the last element of a list
50
>>> list1[5] #Error: trying to access out of the range of a list
Traceback (most recent call last):
File "<pyshell#45>", line 1, in <module>
list1[5]
IndexError: list index out of range
>>> len(list1) #Number of elements in the list
5
322
We can traverse each element of a list using a for loop. Items are returned in
sequence from the list. In example 8.2(b), a list of numbers is traversed from the beginning
to the end, and the square of each number is printed in the console.
list1=[1,5,2,6,8,7]
for item in list1: #Traversing a list
print( f"The square of {item} = {item*item}")
Output
The square of 1 = 1
The square of 5 = 25
The square of 2 = 4
The square of 6 = 36
The square of 8 = 64
The square of 7 = 49
We can traverse a list in the reverse order by first reversing the list and then
traversing it. Example 8.2(c) illustrates the reverse traversal of a list.
list1=[1,5,2,6,8,7]
list1.reverse() #Reversing the order of list items
for item in list1: #Traversing a list
print( f"The square of {item} = {item*item}")
Output
The square of 7 = 49
The square of 8 = 64
The square of 6 = 36
The square of 2 = 4
The square of 5 = 25
323
The square of 1 = 1
We can also use a while loop to traverse a list. Example 8.2(d) illustrates the
traversal of a list using a while loop.
list1=[1,5,2,6,8,7]
index=0 #Initialising index
while index < len(list1): #Traversing a list
print( f"The square of {list1[index]}={list1[index]*list1[index]}")
index+=1 #Incrementing index
Output
The square of 1 = 1
The square of 5 = 25
The square of 2 = 4
The square of 6 = 36
The square of 8 = 64
The square of 7 = 49
Where List_object is a list, the slice starts from the start_index and ends at the end_index
with a step size of step_size. All the parameters are optional. If start_index is not specified,
zero is assumed. If end_index is not specified, the end index of the list is assumed. And if
step_size is not specified, a step size of 1 is used. Negative indices are allowed. If the
324
end_index cannot be reached from the start_index using the specified step_size, an empty
list is returned. Further, if the specified range is outside the size of the specified list, the
extra range is ignored. For example, for a list with ten elements, any end_index value
greater or equal to 10 is ignored. Similarly, any start_index value equal to -10 or less is
ignored. Example 8.3(a) illustrates various ways in which a slice operator can be used.
325
>>> #Sub-list from the start to the 5th from the end of the list
>>> list1[:-5]
[1, 2, 3, 4, 5]
>>> #Sub-list from the 5th from the end up to the end of the list
>>> list1[-5:] [6, 7, 8, 9, 10]
>>> list1[::-1]# All the elements in the reverse order of the list
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> a[-30:] #The start_index is out of range, in the lower side
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> #Start_index =-1. It means the last element of a list and the
default end-index is also the last element. Hence the last element.
>>> a[-1:]
[10]
>>> #The start_index and end_index both are more than the maximum
possible index value, i.e., 9. Hence an empty list.
>>> a[10:20] # This returns a blank list
[]
>>> a[-10:10] #Equal to a[0:10]as start index =-10 is equal to 0
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[-20:10] #Equivalent to a[0:10],i.e., an index < -10 is ignored.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[0:20] #Equivalent to a[0:10], i.e. index > 9 is ignored.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Similar to the list traversal, we can traverse sliced list using a for loop. Example
8.3(b) illustrates traversing a list slice.
326
Example 8.3(b): Traversing a sliced list
list1=[1,5,2,6,8,7]
for x in list1[2:4]: #Traversing a sliced list
print(f"{x}:{x*x}", end=',')
print("\Traversing in reverse order")
for x in list1[-1:0:-1]: #Traversing in reverse order
print(f"{x}:{x*x}", end=',')
Output
2:4,6:36,
Traversing in reverse order
7:49,8:64,6:36,2:4,5:25,
For a list of strings, strings are compared in the alphabetic order, letter-by-letter from
the beginning, based on their ASCII values/ Unicode values. For example, in "abc" and
"abd", the second string is larger than the first string as "d" has a higher ASCII value (100)
than that of "c" (99). Also, note, up to the first two characters, both the strings are the same.
Hence they are differentiated based on the third character. Similarly, "Acd" is smaller than
"abc", as the ASCII value of "A" is 65 and that of "a" is 97. Strings are compared based on
the first mismatching character. Example 8.4(a) illustrates the use of the functions listed in
Table 8.1.
327
Table 8.1: Commonly used built-in function for lists
Function Description
max It returns the maximum value of a list consisting of homogeneous data only,
i.e., all real numeric elements or all string elements. For a heterogeneous list
or a list of iterables, we have to specify the second parameter of the function,
i.e., key.
min It returns the minimum value of a list consisting of homogeneous data only.
Similar to the max() function, for a heterogeneous list or a list of iterables,
we must specify the function's second parameter, i.e., key.
sum It returns the sum of all the list elements consisting of only numeric data,
both real and complex. If the list contains non-numeric data, an error is
raised.
328
>>> print(sum(list1)) #Sum of all the elements of a numeric list
15
>>> print(sum(list2)) #Error: sum is not defined for non-numeric lists
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
print(sum(list2))
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> list4=[{1:"One",2:"Two"},{3:"Three",4:"Four"}] #List of
dictionaries
>>> len(list4)
2
>>> max(list4) # Error: Max is defined only for numeric and string
lists
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
max(list4)
TypeError: '>' not supported between instances of 'dict' and 'dict'
>>> list5=[True, False, 1,2] #True and False are considered as numeric
>>> len(list5)
4
>>> max(list5)
2
>>> sum(list5) #True=1 and False=0 is used in calculations
4
>>> list6=[True, False, 1,2, None] #Heterogeneous list
>>> len(list6)
5
>>> max(list6) #Error: max not defined for heterogeneous lists
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
max(list6)
329
TypeError: '>' not supported between instances of 'NoneType' and 'int'
list7=[1,2,"Three",4,5] #Heterogeneous list
>>> max(list7) #Error: max, min and sum are not defined for
heterogeneous lists
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
max(list7)
TypeError: '>' not supported between instances of 'str' and 'int'
8.4.1 The max() and min () Functions for a List of Lists or Iterables
For a list of iterables, such as lists, tuples, we have to specify the second parameter
of the max() and min () functions, i.e., key. The parameter key accepts a function that
processes each inner list and returns a numeric or string value. These values are used to
decide the maximum or minimum of the outer list. For example, max( [[1, 8, 3],[4, 0, 6],[7, 2,
6]], key=sum) returns [7, 2, 6] as the sum of the elements of [7, 2, 6] is the maximum out of
the three inner lists. Here, the sum of each sublist is computed first and then max() is
applied. Similarly, max( [[1, 8, 3],[4, 0, 6],[7, 2, 6]], key=max) returns [1, 8, 3] as the
maximum value in [1, 8, 3] is the maximum of the three inner lists. Similarly, min( [[1, 8,
3],[4, 0, 6],[7, 2, 6]], key=sum) returns [4, 0, 6], as the sum of the elements of [4, 0, 6] is the
minimum out of the three inner lists.
The key parameter can also accept a user-defined function. For example, max( [[1, 8,
13],[4, 10, 6],[7, 2, 0]], key=lambda x: x[0]) returns [7, 2, 0] as the user-defined lambda
function returns the first element of each inner list. Similarly, min(["adc","abc","aBc"], key=
lambda x : x[1]) returns 'aBc', as the lambda function returns the second character of each
string, and 'B' is the smallest out of the second characters, 'd', 'b' and 'B'. The above concept
is valid for the list of tuples, sets, dictionaries, and other iterables. Example 8.4(b) illustrates
the above concept.
Example 8.4(b): The max() and min() functions with nested lists and lists of iterables
330
>>> max(list1,key=max) #The maximum based on the maximum of elements
[1, 0, 10]
>>> max(list1,key=min) #The maximum based on the minimum of elements
[5, 4, 7]
>>> max(list1,key=lambda x : x[2]) #The maximum based on the third
element of each sub list
[1, 0, 10]
>>> min(list1,key=sum) #The minimum based on the sum of elements
[1, 0, 10]
>>> min(list1,key=min) #The minimum based on the minimum of elements
[1, 0, 10]
>>> min(list1,key=max) #The minimum based on the maximum of elements
[5, 6, 4]
>>> min(list1,key=lambda x : x[2]) #The minimum based on the third
element of each sub list
[5, 6, 4]
>>> list2=[(4,2,6),(8,1,5),(3,7,9)] #A list of tuples
>>> max(list2, key=sum) #The maximum based on the sum of elements
(3, 7, 9)
>>> min(list2, key=sum) #The minimum based on the sum of elements
(4, 2, 6)
>>> list3=[{4,2,6},{8,1,5},{3,7,9}] #A list of sets
>>> min(list3, key=sum) #The minimum based on the sum of elements
{2, 4, 6}
>>> list4=[range(5),range(3,6),range(10)] #A list of ranges
>>> max(list4, key=sum) #The maximum based on the sum of elements
range(0, 10)
>>> list5=[(4,2,6),{8,1,5},[3,7,9]] #A list of heterogeneous iterators
>>> max(list5, key=sum) #The maximum based on the sum of elements
[3, 7, 9]
331
8.4.2 The max () and min () Functions with a List of Complex Numbers
Similar to the list of iterators, the max() and min() functions also require the key
parameter to handle a list of complex numbers. Without the key parameter, these functions
raise an error. A list of complex numbers can be compared based on their absolute values,
real parts, imaginary parts, or any other user-defined function. For example, max([2+3j, 4-
2j, 3+4j], key =abs) returns (3+4j), based on the absolute values of the complex numbers.
Example 8.4(c) illustrates the above.
Example 8.4(c): The max() and min() functions with lists of complex numbers
• In the reference copy, the same memory references are used by the original list and
the copied list.
• In the shallow copy, the original and the copied lists use different memory
references, but their nested elements use the same memory references.
• In the deep copy, the original list and the copied list use different memory
references. The nested elements also use separate memory references.
Example 8.5(a) illustrates these concepts. Notice the IDs of the lists and nested lists.
R1
Original List 1 2 R2 6
R2
Reference Copied List
3 4 5
R3
Shallow Copied List 1 2 R2 6
R5
3 4 5
Figure 8.2: Memory model of reference, shallow and deep copy of a list
333
Example 8.5(a): Various methods to copy a list
>>> #Id of the list copied using the reference is same as that of
>>> #the original list but different for the shallow and deep copies.
>>> print(id(list1),id(list2),id(list3), id(list4))
2406062644096 2406062644096 2406103484224 2406103483712
>>> #Ids of a nested elements are same for reference and shallow copies
>>> #but different for a deep copy
>>> print(id(list1[2]),id(list2[2]),id(list3[2]), id(list4[2]))
2406071688256 2406071688256 2406071688256 2406103483520
In a reference copy of a list, the copied list is an alias of the original list. Both the lists
refer to the same memory object. Any modification, addition, or deletion in the original list
is also reflected in the copied list and vice versa. A reference copy is created by using the =
operator (assignment). However, if we assign new data to the original list or the copied list,
the other list is unaffected. Hence, the reference copy should be used with care. Example
8.5(b) illustrates the above.
334
>>> print(list1,list2) #Changes are reflected to both.
[5, 2, 3, 4] [5, 2, 3, 4]
>>> list2=[1,2] #Assigning a new list will not affect the other list
>>> print(list1,list2)
[5, 2, 3, 4] [1, 2]
335
8.5.2 Shallow Copy
In the shallow copy of a list, the atomic items (such as integers and floats) and string
items are duplicated in the copied list, but collection items (such as lists, tuples, sets, and
dictionaries) are not duplicated, and their references are added. In other words, a new
memory is allocated to the new list in the shallow copy, but no separate memory is assigned
to the nested objects; only their references are added to the new list. Any change in a nested
object in the original list will also appear in the copied list. However, the changes in the
non-nested elements in one list do not affect the other list. Also, adding a new element
(either nested or non-nested) in one list does not affect the other. A shallow copy is created
using the copy method of the list or the copy method of the copy module. Example 8.5(c)
illustrates the behavior of shallow copies.
>>> #Any change in a non-nested element does not affect the copied list
>>> list2[0]=10
>>> print(list1,list2)
[1, 2, 3] [10, 2, 3]
336
>>> list4[1].append(10)# Changes in a nested element affect the other
list
>>> print(list3,list4)
[1, [2, 3, 4, 10]] [10, [2, 3, 4, 10]]
>>> #A new assignment to a nested element does not affect the other
list.
>>> list4[1]=[1,2]
>>> print(list3,list4)
[1, [2, 3, 4, 10]] [10, [1, 2]]
>>> list5=[1,[2,3,4]]
>>> list6=list5.copy()
>>> print(list5,list6)
[1, [2, 3, 4]] [1, [2, 3, 4]]
>>> #Appending an element does not affect the other list
>>> list5.append((5,6))
>>> print(list5,list6)
[1, [2, 3, 4], (5, 6)] [1, [2, 3, 4]]
>>> #Appending an element does not affect the other list
>>> list6.append([8,9])
>>> print(list5,list6)
[1, [2, 3, 4], (5, 6)] [1, [2, 3, 4], [8, 9]]
>>> list6.remove(1) #Removing an element does not affect the other list
>>> print(list5,list6)
[1, [2, 3, 4], (5, 6)] [[2, 3, 4], [8, 9]]
>>> #Removing an element does not affect the other list
>>> list6.remove([2,3,4])
>>> print(list5,list6)
[1, [2, 3, 4], (5, 6)] [[8, 9]]
>>>
337
8.5.3 Deep Copy
In a deep copy of a list, a completely independent copy of the original list is created.
All the nested elements are also duplicated in the new list and have their separate memory.
Once created, there is no link between the original list and the new list. Any change made
in one list does not affect the other. For the deep copy, we use the deepcopy method of the
copy module. Example 8.5(d) illustrates the above.
338
Table 8.2: List methods
Method Description
append(value) Adds value as an element at the end of the list. For example,
print(A.append(10)) results in [3, 2, 4, 2, 1, 10].
clear() Removes all the elements from the list. For example,
print(A.clear()) results in [].
count(value) Finds the number of occurrences of the specified value in the list.
For example, print( A.count(2)) results in 2.
extend(iterable) Adds each element of iterable at the end of the list as a separate
item. For example, A.extend(B); print(A) results in [3, 2, 4, 2, 1, 7,
8]
index(value) Returns the index of the first match of value in the list. For example,
print(A.index(4)) results in 2. If the specified value is not in the list,
a ValueError is generated.
insert(index, value) Adds the value as an element at the index position in the list. For
example, A.insert(1,20); print(A) results in [3, 20, 2, 4, 2, 1]. If the
index is more than the count of the list, the value is appended at the
end of the list. For example, A.insert(10,100); print(A) result in [3,
20, 2, 4, 2, 1, 100].
pop(index) Removes and returns the element at index position in the list. For
example, A.pop(2) results in 4, and the new A is [3, 2, 2, 1]. If the
specified index is more than the list length, an out-of-range error is
generated.
remove(value) Removes the first match of value from the list. For example,
A.remove(4); print(A) results in [3, 2, 2, 1]. If value is not in the list,
an error is raised.
339
reverse() Reverses the order of the list elements, i.e., the first element
becomes the last and vice versa. For example, A.reverse(); print(A)
results in [1, 2, 4, 2, 3].
sort() Sorts the elements of the list in ascending order. For example,
A.sort(); print(A) results in [1, 2, 2, 3, 4].
340
File "<pyshell#62>", line 1, in <module>
list1.index(100)
ValueError: 100 is not in list
>>> list1.insert(3,20) #insert 20 at index 3 in the list
>>> print(list1)
[1, 2, 3, 20, 4, 5, 6, 3]
>>> a=list1.pop(3) #Return the value of the element at index 3
>>> print(a)
20
>>> list1.pop(12) #Error, the specified index is out of range
Traceback (most recent call last):
File "<pyshell#59>", line 1, in <module>
list1.pop(12)
IndexError: pop index out of range
>>> list1.remove(4) #Remove the first occurrence of 4 from the list
>>> print(list1)
[1, 2, 3, 5, 6, 3]
>>> list1.reverse() #Reverse the list
>>> print(list1)
[3, 6, 5, 3, 2, 1]
>>> list1.sort() #Arrange the list in ascending order
>>> print(list1)
[1, 2, 3, 3, 5, 6]
>>>
341
(a) Using the random.shuffle method: The shuffle () method of the random module
shuffles the list elements in place, and the original list order is lost. Example 8.7(a) illustrates
the same.
(b) Using the random.sample method: The sample () method of the random module
returns a new list with shuffled elements, and keeps the original list order intact. The
sample () method takes two parameters: (1) the original list, and (2) the number of elements
to randomly draw from the original list, and returns the shuffled list. Example 8.7(b)
illustrates the above.
342
8.8 Using a List as a Matrix and an Array
A matrix is a rectangular arrangement of data or numbers. The horizontal entries in
a matrix are called rows, and the vertical entries are called columns. The size of a matrix is
specified as r x c, where r is the number of rows, and c is the number of columns. When the
number of dimensions of a grid of data is more than two, it is called an n-dimensional array
or simply an array. A matrix is a special case of it, with only two dimensions.
Python does not have built-in data structures for matrices and arrays, but lists can
be used to implement the concepts of matrices and arrays. The ability of a list to contain
another list as its elements is used to implement matrices and arrays. Further, Python has a
powerful module called NumPy(see chapter 14) to efficiently create and manipulate
matrices and arrays. However, in this section, we will discuss how lists are used to create
and process matrices and arrays.
A matrix is created as a nested list. The inner lists store the rows of a matrix. For
1 2 3
example, the list [ [1, 2, 3], [4, 5, 6], [7, 8, 9]] stores the following matrix: [ 4 5 6]. Example
7 8 9
8.8(a) shows how to create this matrix and perform some simple matrix operations. Figure
8.3 shows the memory model of how a matrix is constructed using lists:
343
print("\nThe matrix in the matrix form:") #Print the matrix
for i in range(len(matrix)):
print()
for j in range(len(matrix[0])):
print(matrix[i][j],end=" ")
matrix_transpose_row=[]
for j in range(len(matrix)):
matrix_transpose_row.append(matrix[j][i])
matrix_transpose.append(matrix_transpose_row)
Output
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Diagonal elements of the matrix:
1 5 9
The matrix in the matrix form:
1 2 3
4 5 6
7 8 9
344
The transpose of the matrix:
1 4 7
2 5 8
3 6 9
List1
1 2 3 List2
R1
R2 4 5 6 List3
R3
7 8 9 List4
Similar to matrix creation, higher-order arrays can be created using lists. Figure 8.4
shows the memory model of a 3D array with two planes, three rows and three columns.
Example 8.8(b) illustrates how to create a 3D array of size 3 x 3 x 3 which consists of a
number sequence starting from 1. The size of a 3D array is specified as p x r x c, where p is
the number of planes, r is the number of rows in each plane, and c is the number of columns
in each row. Another example where a small size array and matrices can be created directly
from the given data using a nested list is shown in example 8.8(c).
345
for p in range(np):
plane=[] #Initialise a plane
for r in range(nr):
row=[] #Initialize a row
for c in range(nc):
row.append(a) #Add a column to the row
a=a+1
plane.append(row)#Add a row to the plane
array3d.append(plane)#Add a plane to the array3d
print(array3d)
#Print the array in the grid format
for p in range(np):
print("plane:",p)
for r in range(nr):
for c in range(nc):
print(array3d[p][r][c], end=" ")
print()
Output
Enter size of the array(p,r,c):
3,3,3
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16,
17, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]]
plane: 0
1 2 3
4 5 6
7 8 9
plane: 1
10 11 12
13 14 15
346
16 17 18
plane: 2
19 20 21
22 23 24
25 26 27
List1
1 2 3 List3
R1
R2 4 5 6 List4
List0 R3
7 8 9 List5
P1
P2
List2 10 11 12 List6
R1
R2 13 14 15 List7
R3
16 17 18 List8
347
[4,5,6],
[7,8,9]
],
[#Plane 2
[10,11,12],
[13,14,15],
[16,16,18]
],
[#Plane 3
[19,20,21],
[22,23,24],
[25,26,27]
]
]
Output
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16,
16, 18]], [[19, 20, 21], [22, 23, 24], [25, 26, 27]]]
plane: 0
1 2 3
4 5 6
348
7 8 9
plane: 1
10 11 12
13 14 15
16 16 18
plane: 2
19 20 21
22 23 24
25 26 27
A matrix can be read from the keyboard, element-by-element, using the input
function. Elements can be read row-wise or column-wise. Since the input () function returns
the read data as an str object, we have to convert the input data to the appropriate type.
Example 8.8(d) shows how to read two float matrices from the keyboard and find their sum.
349
#Reading the second matrix from the keyboard
matrix2=[]
for r in range(nr):
row=[]
for c in range(nc):
print("Enter element matrix2[",r,"][",c,"]:", end=" ")
x=float(input())
row.append(x)
matrix2.append(row)
Output
Enter the number of rows:3
Enter the number of columns:3
Read the matrix element-by-element:
Enter element matrix1[ 0 ][ 0 ]: 1
Enter element matrix1[ 0 ][ 1 ]: 2
350
Enter element matrix1[ 0 ][ 2 ]: 3
Enter element matrix1[ 1 ][ 0 ]: 4
Enter element matrix1[ 1 ][ 1 ]: 5
Enter element matrix1[ 1 ][ 2 ]: 6
Enter element matrix1[ 2 ][ 0 ]: 7
Enter element matrix1[ 2 ][ 1 ]: 8
Enter element matrix1[ 2 ][ 2 ]: 9
Enter element matrix2[ 0 ][ 0 ]: 4
Enter element matrix2[ 0 ][ 1 ]: 2
Enter element matrix2[ 0 ][ 2 ]: 3
Enter element matrix2[ 1 ][ 0 ]: 4
Enter element matrix2[ 1 ][ 1 ]: 2
Enter element matrix2[ 1 ][ 2 ]: 5
Enter element matrix2[ 2 ][ 0 ]: 2
Enter element matrix2[ 2 ][ 1 ]: 3
Enter element matrix2[ 2 ][ 2 ]: 4
The First matrix:
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]
The Second matrix:
[[4.0, 2.0, 3.0], [4.0, 2.0, 5.0], [2.0, 3.0, 4.0]]
The sum matrix:
[[5.0, 4.0, 6.0], [8.0, 7.0, 11.0], [9.0, 11.0, 13.0]]
351
Output_list = [ [inner list comprehension] outer list comprehension]
Example 8.8(e) calculates the sum and multiplication of two matrices using list
comprehension. For calculating matrix multiplication, we first generate vectors of the
product of the pivot rows and columns and then, in the second step, the sum of these vectors
is calculated. We have to use two steps as an assignment is not permitted in the list
comprehension. The code using the list comprehension is very compact, but it is difficult to
understand.
Example 8.8(e): Sum and product of matrices using the list comprehension
A=[[1,2,3],[4,5,6],[7,8,9]] #Matrix A
B=[[4,2,3],[6,2,5],[6,1,2]] #Matrix B
print(A)
print(B)
print("Sum of A and B:")
print(S)
print("Product of A and B:")
print(M1)
Output
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[4, 2, 3], [6, 2, 5], [6, 1, 2]]
352
Sum of A and B:
[[5, 4, 6], [10, 7, 11], [13, 9, 11]]
Product of A and B:
[[34, 9, 19], [82, 24, 49], [130, 39, 79]]
The concatenation operator combines the two lists. For example, the expression
[1,2,3] + [4,5] evaluates to [1,2,3,4,5]. The repetition operator returns the replicated list. For
example, the expression [1,2,3] * 2 evaluates to [1,2,3,1,2,3]. The existence operator checks
whether the specified value exists in the list or not. If it exists, it returns True, otherwise
False. The identity operator is used to check whether two list variables refer to the same
list in the memory or not. And, the delete operator deletes elements or a slice from a list.
Example 8.9 illustrates the above.
>>> a=[1,2,3]
>>> b=[4,5,6]
>>> c=a+b #Concatenate two lists
>>> print(c)
[1, 2, 3, 4, 5, 6]
>>> d=a*3 #Replicate the list three times
>>> print(d)
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> 2 in a #Check the existence of a value in a list
353
True
>>> 5 in a #Check the existence of a value in a list
False
>>> a=[[1,2,3],[4,5,6],7,8]
>>> [1,2,3] in a #Check existence of a list in another list
True
>>> a=[1,2,3]
>>> b=a
>>> a is b #Check whether the two lists are the same object or not
True
>>> c=a.copy() #Shallow copy
>>> a is c
False
>>> del a[2] #Delete an element
>>> print(a)
[1, 2]
>>> del c[0:2] #Delete a slice of the list
>>> c
[3]
>>>
Solution steps:
1. Import the random module.
2. Read the size of the list.
3. Initialize the random number list.
354
4. Generate random numbers using the randint () function of the random module and
append them to the list.
5. Initialize the even and odd number lists.
6. Iterate the random number list, and append the even numbers to the even list and the
odd numbers to the odd list.
7. Find the sum of both lists and print them.
355
Even list: [94, 26, 84, 76, 32, 70]
Odd list: [75, 87, 37, 9]
Sum of even list: 382
Sum of odd list: 208
Program 8.2: Write a program to read a list of n integer numbers, and create the
frequency table of the list.
Solution steps:
1. Initialize the list.
2. Read numbers and add them to the list
3. Convert the list to a set to remove the duplicate entries.
4. Iterate over the set elements and get the count of each set element in the list using the
count () method.
#Read the number of data
n=int(input("Enter the number of items in the list "))
L1=[] #Create an empty list
s=set(L1) #Convert the list to a set. The duplicate entries are removed
print(format("Element", ">10s"),":", format("Frequency",">10s"))
for x in s: #Iterate the set and count the number of entries of an
element in the list
print(format(x,"10d"),":", format(L1.count(x),"10d"))
Output
Enter the number of items in the list: 10
Enter the value of element L[0]: 2
Enter the value of element L[1]: 1
356
Enter the value of element L[2]: 3
Enter the value of element L[3]: 1
Enter the value of element L[4]: 2
Enter the value of element L[5]: 5
Enter the value of element L[6]: 3
Enter the value of element L[7]: 2
Enter the value of element L[8]: 4
Enter the value of element L[9]: 6
Element : Frequency
1: 2
2: 3
3: 2
4: 1
5: 1
6: 1
Program 8.3: Write a program to read n integer numbers, and find their mean, median,
mode and standard deviation.
Solution steps:
1. Import the math module.
2. Read the numbers into a list.
3. Find the sum of list elements using the sum () method and find the mean.
(𝑥𝑖 −𝑥̅ )2
4. Find the standard deviation using the formula 𝜎 = √ 𝑛
.
357
6. If the size of the list is odd, the median value is the middle value of the list, else the
median is the average of the two middle values.
7. To calculate the mode, convert the list into a set and find the set element which has
the maximum count in the list.
import math #Import math library
n=int(input("Enter the number of data: "))
data1=[] #Create an empty data list
for i in range(n):
x=int(input(f"Enter the value of element data[{i}]: "))
data1.append(x)
358
if data1.count(x)> c:
c=data1.count(x)
mode=x
print("Sorted list:",data1)
print("Mean=", mean)
print("Standard deviation=", sd)
print("Mode=", mode)
print("Median=", median)
Output
Enter the number of data: 5
Enter the value of element data[0]: 1
Enter the value of element data[1]: 2
Enter the value of element data[2]: 3
Enter the value of element data[3]: 4
Enter the value of element data[4]: 2
Sorted list: [1, 2, 2, 3, 4]
Mean= 2.4
Standard deviation= 1.019803902718557
Mode= 2
Median= 2.0
Program 8.4: Write a program to read a list of n numbers and sort the list using the
bubble sort.
Solution steps:
1. Read the numbers into a list.
2. Repeat the following process n-1 times, where n is the number of elements in the list.
2.1 Iterate over the list items, if the adjacent items are not in order, swap them.
359
Step by step working of the bubble sort is illustrated below. The swapped items are
highlighted in red. As can be seen from the table, the largest element settles in its position
after the first outer iteration, the second largest after the second outer iteration and so on.
Hence, the span of the inner loop reduces after each outer loop iteration. The reduction
in the inner loop span is shown as gray color.
for i in range(n):
x=float(input(f"Enter the value of element data[{i}: "))
data.append(x)
#Bubble sorting
for i in range(n):
for j in range(n-i-1):
if data[j] > data[j+1]:#swap items if not in order
t=data[j]
data[j]=data[j+1]
data[j+1]=t
360
print("Sorted list:", data)
Output
Enter the number of data: 5
Enter the value of element data[0: 6
Enter the value of element data[1: 2
Enter the value of element data[2: 4
Enter the value of element data[3: 3
Enter the value of element data[4: 1
Sorted list: [1.0, 2.0, 3.0, 4.0, 6.0]
Program 8.5: Write a program to read n numbers and insert them in a list in ascending
order.
Solution steps:
1. Read the number of elements in a list.
2. Read a list item
2.1 Locate its proper position in the list
2.2 Insert the item at its position
361
break
else: #Append at the end of the list
ordered_list.append(x)
print("Sorted list: ", ordered_list)
Output
Enter the number of data: 5
Enter the data item[0]: 3
Sorted list: [3.0]
Enter the data item[1]: 1
Sorted list: [1.0, 3.0]
Enter the data item[2]: 6
Sorted list: [1.0, 3.0, 6.0]
Enter the data item[3]: 4
Sorted list: [1.0, 3.0, 4.0, 6.0]
Enter the data item[4]: 2
Sorted list: [1.0, 2.0, 3.0, 4.0, 6.0]
Program 8.6: Write a program to simulate push and pop operations of a stack.
Stack is a special type of queue where we can read and write data from the top only.
It uses the queue discipline last in fist out, LIFO. The pop operation removes one item
from the top of the stack, and the push operation writes one item at the top of the stack.
Solution steps:
1. Initialize the stack as an empty list.
2. Write an infinite loop:
2.1 Create the main menu - 1 for push, 2 for pop and 3 for ending simulation.
362
2.2 Get the choice of the user.
2.3 If choice is 1:
2.3.1 Read the item.
2.3.2 Add the item at the top of the stack.
2.3.3 Print the stack.
2.4 Else if choice is 2:
2.4.1 Get the last item of the stack, remove it from the stack and print it.
If there is no item in the stack, print the message that the stack is empty.
2.4.2 Print the stack.
2.5 Else if choice is 3:
2.5.1 break the infinite loop to end the simulation.
2.6 Else:
2.6.1 Print invalid choice, and show the main menu again.
stack=[] #Initialise the stack
while 1: #Infinite loop
#Show the main menu items
print("\n\n====== Main Menu =====\n1 for push an item\n2 for pop
an item\n3 end")
#Get the choice
choice=int(input("Enter your choice: "))
if choice == 1: #Implementing the push operation
x=input("Enter the item to push in the stack: ")
stack.append(x) #Add the new item at the end
print("\nStack values:", stack)
print("Item pushed successfully")
elif choice == 2: #Implementing the pop operation
if len(stack)==0: #There is no item in the stack
print("There is no item in the stack to pop.")
else:
#Remove the last item from the stack and return it.
x=stack.pop()
print("\nPopped item:",x)
print("Stack values:",stack)
363
elif choice ==3: #End the simulation
print("\nBreaking the simulation")
break
else: #Invlaid choice
print("\nInvalid choice")
Output
====== Main Menu =====
1 for push an item
2 for pop an item
3 end
Enter your choice: 1
Enter the item to push in the stack: 10
Popped item: 10
Stack values: []
364
Item pushed successfully
Popped item: 30
Stack values: ['20']
Popped item: 20
Stack values: []
365
Enter your choice: 2
There is no item in the stack to pop.
Chapter Summary
366
10. In the shallow copy, the original and the copied lists use different memory
references, but their nested elements use the same memory references.
11. In the deep copy, the original list and the copied list use different memory
references. The nested elements also use separate memory references.
12. Nested list means a list within another list. We can use nested lists to create
matrices and arrays.
5. What is the value of L1 after executing the following Python code snippet?
L1= [x for x in "hello"]
367
(a) [‘h’, ‘e’, ‘l’, ‘l’, ‘o’]
(b) ‘hello’
(c) [‘hello’]
(d) hello
6. What is the value of L1 after executing the following Python code snippet?
L1= [x+y for x in "abc" for y in "def"]
(a) ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']
(b) ['da', 'ea', 'fa', 'db', 'eb', 'fb', 'dc', 'ec', 'fc']
(c) [['ad', 'ae', 'af'], ['bd', 'be', 'bf'], ['cd', 'ce', 'cf']]
(d) None of the above
7. For the list A=[1,2,3,4,5], which of the following is incorrect way to get 3 from
the list?
(a) A[3]
(b) A[2]
(c) A[-3]
(d) None of the above
9. For the list L1= [1,2,3,4,5], which of the following is correct slicing operation?
(a) L1[0]
(b) L1[:2]
(c) L1[: -2]
d) All of the above
368
(c) It is an error
(d) None of the above
11. For the list L1= [1, 2, 3], What is the value of L2 after executing the following
code?
L2 = L1 * 2
(a) [2, 4, 6]
b) [1, 1, 2, 2, 3, 3]
c) [1, 2, 3, 1, 2, 3]
d) None of the above
12. Which of the following is the correct way to add an item at the end of a list,
L1?
(a) L1.append(item)
(b) L1.add(item)
(c) L1 + item
(d) All of the above
13. For L1 = [1,2,4,5], which of the following is the correct way to insert 3 between
2 and 4?
(a) L1.insert(2, 3)
(b) L1.insert(3, 2)
(c) L1.insert(3, 3)
(d) None of the above
14. For L1= ['Java', 'Pascal', 'Python'], What is the output of print (L1[-1][-1]) ?
(a) n
(b) Python
(c) Pascal
(d) None of the above
369
(a) 2
(b) 1
(c) 5
(d) None of the above
myFun(10)
myFun(20)
value = myFun(30)
print(value)
370
21. What is the output of the following program?
L1 = [1, 2, 3, 4]
L1.append([5,6])
print(len(L1))
(a) 6
(b) 5
(c) 4
(d) None of the above
L1 = [1, 2, 3, 4]
L1.exend([5,6])
print(len(L1))
(a) 6
(b) 5
(c) 4
(d) None of the above
L1 = [1, 2, 3, 4]
L1 +=[5,6]
print(len(L1))
(a) 6
(b) 5
(c) 4
(d) None of the above
371
(b) [0, 1, 2, 1, 2, 3]
(c) [[0, 1, 2], [1, 2, 3]]
(d) None of the above
(a) 12
(b) 6
(c) 5
(d) None of the above
Review Questions
372
n. We can join two lists using the + operator.
o. The expression L1.pop() removes the last element from L1.
p. The expression L1.push(10) adds 10 at the start of L1.
q. The expressions L1.append(L2) and L1.extend(L2) are the same.
2. What is a list in Python? Describe its advantages and disadvantages.
3. Describe different methods to create a list.
4. Describe list comprehension.
5. Describe list slicing.
6. Describe list indexing.
7. Describe methods to traverse a list.
8. Describe various methods of the list class.
9. Describe min and max built-in functions for lists.
10. Describe various methods to copy a list.
11. Differentiate among a reference copy, a shallow copy and a deep copy of a list.
12. Describe methods to randomly reshuffle elements of a list.
13. Describe methods to store matrices and arrays using lists.
14. Describe methods to read matrices from the console.
15. Describe nested list comprehension.
16. Describe various list operators.
17. Differentiate between the following:
a. pop() and remove() methods of list.
b. del statement and pop() method of list.
c. append() and insert() methods of list.
18. With L1 = [1,2,3,4], what is the output of the following:
a. max(L1)
373
b. min(L1)
c. sum(L1)
d. len(L1)
19. With L1 = [4, 6, 2, 7, 3, 5, 1], what is the output of the following:
a. L1[-1]
b. L1[: 3}
c. L1[:]
d. L1[: :-1]
e. L1[3:-1]
f. L1[-1:3]
g. L1[-1:3:-1]
h. L1[:-3:]
20. With L1 = [1,2,3], and L2 = [4,5], what is the output of the following:
a. L1+L2
b. L1*2+L2
c. L1*0
d. 3*L1
e. 2*L1+3*L2
f. L1*L2
g. L1-L2
h. L1/2
21. With L1 = [4, 6, 2, 7, 3, 5, 1], what is the value of L1 after executing the following:
a. L1.sort()
b. L1.append([8,9,10])
374
c. L1.extend([8,9,10])
d. L1.reverse()
e. L1.pop()
f. L1.clear()
g. L1.index(2)
h. L1.insert(3,4)
i. L1.remove(3)
Programming Assignments
1. Write a program to read a list of n numbers and create a list of valid numbers
from the list that fall within a given range.
2. Write a function that takes a list of integers and returns the list of even integers.
3. Write a function that takes a list of numbers and removes all the negative
numbers.
4. Write a program to read a list of n numbers and print the following statistics of
the list:
(a) the maximum, (b) the minimum, (c) average, (d) median and (e) standard
deviation.
5. Write a function that takes a list of numbers as its parameter and returns True if
the list is sorted, else returns False.
6. Write a function that takes a list and a positive integer as its parameters and
returns a list that consists of the n replication of each list item. For example, for
the list [1,2,3] and n=2, the desired list is [1,1,2,2,3,3].
7. Write a program to sort the elements of a list in ascending order using selection
sort.
375
8. Write a program to sort the elements of a list in ascending order using insertion
sort.
9. Write a program to read a list of n words and print the words that contains more
the two vowels.
10. Write a program to read two matrices and find their multiplication.
11. Write a program to read a 3x3 matrix and determine if it is the Lo Shu Magic
Square matrix.
Hint: The Lo Shu Magic Square matrix has the following properties:
• The sum of each row, each column, and each diagonal all add up to the same
number.
12. Write a program to create a random number square matrix of size n (use a 2D
list). The random numbers are between 1 and n.
13. Write a program to generate a square matrix of size n (use a 2D list) which
consists of rows of random permutations of 1 to n.
14. Read two lists of numbers and generate a list that contains the common numbers
of the lists.
15. Write a program to read an integer number and create a list of its digits and
generate the largest number using these digits.
376
Chapter 9
Strings
Learning Outcomes:
Strings are immutable, i.e. once a string is created, it cannot be edited. However, we
can access individual characters and can create substrings from a string. Strings are stored
as the str class. Hence, the expression, type("Python") will return <class 'str'>. The str class
has a large number of methods to perform common string processing operations.
In Python, there is no character data type. However, the character functionalities can
be achieved by storing a single character in a string object.
String literals are created by enclosing characters inside a single quote, double-
quotes, triple single quotes or triple double quotes. The single quote or double quote are
identical and used to create single line string literals. Whereas, triple quotes are used to
377
create multiline strings. See ` for more details about string literals. Example 9.1(a) shows
how to create a string variable using string literals.
The constructor of the str class can be used to create string literals from various data
types, which can be assigned to variables to create string objects. It simply returns the string
equivalent of the data. Example 9.1(b) shows how to convert various data types into strings.
>>> s="Python"
>>> len(s) #Find the number of characters in a string
6
>>> max(s) #Find the largest character in a string
'y'
>>> min(s) #Find the smallest character in a string
'P'
379
Positive index 0 1 2 3 4 5
String P y t h o n
Negative index -6 -5 -4 -3 -2 -1
>>> s="Python"
>>> s[0] #The first character
'P'
>>> s[-1]#The last character
'n'
>>> s[3] #The fourth character
'h'
>>> s[-3] #the third character from the last
'h'
>>> s[8] #Error: out of range
Traceback (most recent call last):
File "<pyshell#100>", line 1, in <module>
s[8]
IndexError: string index out of range
>>> s[-8] #Error: out of range
Traceback (most recent call last):
File "<pyshell#101>", line 1, in <module>
s[-8]
IndexError: string index out of range
>>>
380
Example 9.4(a): Traversing a string
All the slicing parameters are optional and the default value of step is 1. For a
positive value of step, the default value of start is 0, and the default value of stop is length
of the string. On the other hand, for a negative value of step, the default value of start is -1
and the value of stop is the minus value of the length of the string. The length of a string
381
can be calculated using len (string object). For example the slice 1:4 will generate the indices
1,2,3. Hence, for s="Python”, the expression s[1:4] will return 'yth'. Similarly, the slice 1:6:2
will generate indices 1,3,5 and the expression s[1:6:2] will return 'yhn'. Slicing can be done
with negative indices also. For example, the expression s[-1:-5:-1] will return 'noht' and the
expression s[-6:-1:1] will return 'Pytho'. If the step is positive, characters will be returned
in the forward direction, otherwise in the backward direction. The default value of start is
0 and the default value of end is the length of the string. For example, the expression s[::2]
will return 'Pto', i.e. alternate characters starting from the first character to the last character
of the string.
Slicing indices can also be generated by the construction of the slice object. The
syntax of the slice method is slice (start, stop, step), where the start, stop and step have the
same meaning as given above. For example, the s1 = slice(1,6,2) will return indices 1,3,5. A
slice object can be used as indices for getting substring from a string. For the string object
str1="Python" and the slice s1=slice(1,6,2), the expression str1[s1] will return 'yhn'.
Example 9.5 illustrates slicing operations on a string.
>>> s1="Hello"
>>> s2="World"
>>> s3=s1+s2 #Concatenate two strings
>>> s4=s1*3 #Repeat a string
>>> print(s4)
HelloHelloHello
>>> print(s3)
HelloWorld
>>> s1 in s3 #Check whether a string exists in the other string or not
True
>>> s1 in s2
False
>>> s1 not in s2 #Check whether a string exists in other string or not
True
>>>
Method Description
capitalize() Returns a new string with the first character converted to the upper
case.
>>> s1="python programming language"
>>> s2=s1.capitalize()
383
>>> print(s2) #Modified string
Python programming language
>>> print(s1) #Original string
python programming language
casefold() Returns a new string with all the characters converted to the lower
case.
>>> s1="Python Programming Language"
>>> s1.casefold()
'python programming language'
center(w,ch) Returns a new centered string in the specified width, w, by adding
the specified character, ch, in both sides. If the character is not
specified, space is used.
>>> s1="python programming language"
>>> s1.center(35,'$')
'$$$$python programming language$$$$'
>>> s1.center(35)
' python programming language '
count(value) Returns the number of times a specified substring value is found in
the string.
>>> s1="python programming language"
>>> s1.count('o')
2
>>> s1.count("python")
1
encode() Returns a binary encoded version of the string. The purpose of
encoding is to convert data into a form to properly use by other
system, for example, binary data for sending over email, or viewing
special characters on a web page. The following example converts s1
using ‘UTF-16’ encoding. Please note, the same encoding must be
used to get the string back properly. By default, Python uses ‘UTF-8’
encoding system.
>>> s2.isalnum()
True
>>> s3="Python3.8" #Contains a special character.
>>> s3.isalnum()
False
isalpha() Returns True if all the characters in the string are alphabets
>>> s2="Python"
>>> s2.isalpha()#Contains only alphabets
True
>>> s3="Python3"
>>> s3.isalpha() #Contains a digit
385
False
isdecimal() Returns True if all characters in the string are decimal digits only, i.e.
characters are from 0,1, 2…8,9.
>>> s2="1234"
>>> s2.isdecimal() #Contains only decimal digits
True
>>> s3="123.4"
>>> s3.isdecimal() #Contains a decimal point
False
isdigit() Returns True if all characters in the string are digits. It is the same as
isdecimal, above.
isidentifier() Returns True if the string is a valid identifier name.
>>> s2="abc"
>>> s2.isidentifier() #A valid identifier name
True
>>> s3="abc.32"
>>> s3.isidentifier() #An invalid identifier name
False
islower() Returns True if all the characters in the string are lower case.
>>> s1="Python"
>>> s1.islower() #All the alphabets are not in lower
case
False
>>> s2="python 3.8" #All the alphabets are in lower
case
>>> s2.islower()
True
isnumeric() Returns True if all characters in the string are digits only.
>>> s1="123.45"
>>> s1.isnumeric() #Contains a decimal point
False
>>> s2="123"
>>> s2.isnumeric() #Contains only digits
True
isprintable() Returns True if all the characters in the string are printable and does
not contain non-printable characters such as a newline, a tab, etc. A
space is a printable character.
>>> s1="Hello"
>>> s1.isprintable() #Contains only printable
True
>>> s2="Hello\n"
>>> s2.isprintable() #Contains non-printable, i.e. a
newline
False
386
>>> s3="Hello\tWorld" #Contains non-printable, i.e. a
tab
>>> s3.isprintable()
False
s4="Hello world"
>>> s4.isprintable() #A space character is printable
True
isspace() Returns True if all the characters in the string are spaces.
>>> s1=" "
>>> s1.isspace() #Contains only spaces
True
>>> s2="\t\t\\t" #Contains non-spaces
>>> s2.isspace()
False
istitle() Returns True if the string is in the title case. The title case means that
the first letter of each word is capitalized, except for short
prepositions and articles.
>>> s1="Python Programming Language"
>>> s1.istitle() #Each word of the string is
capitalised
True
>>> s2="Python programming language"
>>> #Each word of the string is not capitalised
>>> s2.istitle()
False
isupper() Returns True if all the alphabet characters in the string are in the
upper case.
>>> s1="Python 3.0"
>>> s1.isupper() #Contains small case letters
False
>>> s2="PYTHON 3.0"
>>> s2.isupper() #All the alphabets are in the upper
case
True
join(iterable) Joins the elements of an iterable consisting of stings, using the string
as the separator.
>>> list1=["One", "Two", "Three"]
>>> s1="-sep-"
>>> s1.join(list1) #Joint the list items
'One-sep-Two-sep-Three'
>>> tuple1=("Hello","World")
>>> s1=" "
>>> s1.join(tuple1) #Join tuple elements
'Hello World'
387
>>> dict1={"One":1,"Two":2}
>>> s1.join(dict1) #Keys will be used during join
'One Two'
ljust(w, ch) Returns the left aligned version of the string within a specified
width, w, using a specified character, ch, as the filler character. The
default filler character is a space.
>>> s1="Python"
>>> s1.ljust(20) #Left aligned string
'Python '
>>> #Left aligned string using # as filler
>>> s1.ljust(20,"#")
'Python##############'
lower() Returns the lowercase version of the string, by converting all the
upper case alphabets to the corresponding lower case alphabets.
>>> s1="PYTHON 3.0"
>>> s1.lower()
'python 3.0'
lstrip(ch) Returns a string after removing all the specified characters, ch, from
the lift side of the string. The default is the space character.
>>> s1=" 1234.34 "
>>> s1.lstrip() #Remove all leading spaces
'1234.34 '
>>> s1="000001234.4500"
>>> s1.lstrip('0') #Remove all leading 0s
'1234.4500'
>>>
partition(value) Returns a tuple of three strings. The first element consists of the part
of the string where the first match of the specified value is found.
The second element contains the specified string and, the third
element contains the remaining part of the string.
>> s1="PythonProgrammingLanguage"
>>> s1.partition("Programming")
('Python', 'Programming', 'Language')
replace(s1,s2,n) Returns a string after replacing the first n occurrences of s1 by s2 in
the string. By default, the value of n is all occurrences.
>>> s1="I ate one banana. The banana was very tasty"
>>> #Replace banana with apple
>>> s1.replace('banana','apple')
'I ate one apple. The apple was very tasty'
>>> #Replace the first occurrence of banana with apple
>>> s1.replace('banana','apple',1)
'I ate one apple. The banana was very tasty'
rfind(value) Returns the last index of the specified value found in the string.
388
>>> s1="I ate one banana. The banana was very tasty"
>>> s1.rfind('banana') #Find a string from the backward
22
>>> s1.rfind('apple') #In case no match found
-1
rindex(value) Searches the value in the string, and returns the index of the last
match where it was found. If no match is found, it generates an error.
>>> s1="I ate one banana. The banana was very tasty"
>>> s1.rindex('banana') #Index of the last match
22
>>> s1.rindex('apple') #Error: No match found
Traceback (most recent call last):
File "<pyshell#178>", line 1, in <module>
s1.rindex('apple')
ValueError: substring not found
rjust(w,ch) Returns the right aligned version of the string within a specified
width, w, using a specified character, ch, as the filler character. The
default filler character is space.
>>> s1="Python"
>>> s1.rjust(20) #Space padded right aligned string
' Python'
>>> s1.rjust(20,'#')#Hash padded right aligned string
'##############Python'
rpartition() Returns a tuple of three strings. The first element consists of the part
of the string where the last match of the specified value is found. The
second element contains the specified string, and the third element
contains the remaining part after the string.
>>> s1="I ate one banana. The banana was very tasty"
>>> s1.rpartition('banana') #Partition from end
('I ate one banana. The ', 'banana', ' was very tasty')
rsplit(sep) Splits the string at all the locations where the specified separator is
present (default is a space), and returns the substrings as a list.
Separators are not part of the returned substrings.
>>> s1="I ate one banana. The banana was very tasty"
>>> s1.rsplit() #Prepare a list of all words
['I', 'ate', 'one', 'banana.', 'The', 'banana', 'was',
'very', 'tasty']
>>> s1.rsplit('.') #Prepare a list of sentences
['I ate one banana', ' The banana was very tasty']
rstrip() Returns a string after removing all the specified character, ch, from
the right side of the string. The default is the space character.
>>> s1=" Python "
>>> s1.rstrip()#Remove all the trailing spaces
389
' Python'
>>> s2="---Python----"
>>> s2.rstrip('-')#Remove all the trailing hyphens
'---Python'
split(sep) Splits the string at all the locations where the specified separator is
present (default is a space), and returns the substrings as a list.
Separators are not part of the substrings.
>>> s1="I ate one banana. The banana was very tasty"
>>> s1.split()#Returns list of all words
['I', 'ate', 'one', 'banana.', 'The', 'banana', 'was',
'very', 'tasty']
>>> s1.split('.')#Returns all the sentences
['I ate one banana', ' The banana was very tasty']
splitlines(flag) Splits the string at new line characters and returns the substrings as
a list. If the flag is true, the new line characters are retained in the
returned sublists, otherwise they are ignored. The default is False.
>>> s1="I ate one banana. The banana was very tasty"
#Split at new line characters and ignore the new line
characters
>>> s1.splitlines()
['I ate one banana. ', 'The banana was very tasty']
#Split at new line characters and retain the new line
characters
>>> s1.splitlines(True)
['I ate one banana. \n', 'The banana was very tasty']
startswith(value) Returns True if the string starts with the specified value, otherwise
False.
>>> s1="Python is very simple"
>>> s1.startswith("Python")#The string starts with
Python
True
>>> s1.startswith("simple")#The string does not start
with simple
False
strip(ch) Returns the string after removing all the occurrences of the specified
character from both leading and trailing ends of the string. The
default character is a space.
>>> s1=" Python "
>>> #Removes all leading and trailing spaces
>>> s1.strip()
'Python'
>>> s2="---Python----"
>>> #Removes all leading and trailing hyphens
>>> s2.strip('-')
390
'Python'
>>>
swapcase() Swaps the cases of all the alphabets in the string from the lower case
to the upper case and the upper case to the lower case, i.e. the upper
case alphabets become the lower case alphabets and the lower case
alphabets become the upper case alphabets.
>>> s1="Hello World"
>>> #Change the upper case characters to the lower case
and vice a versa
>>> s1.swapcase()
'hELLO wORLD'
title() Returns the string after capitalizing the first character of each word
of the string.
>>> s1="hello world. i love python"
>>> #Make first letter capital of each word
>>> s1.title()
'Hello World. I Love Python'
upper() Returns the string after converting all the lower case alphabets to the
upper case.
>>> s1='hello world. i love python'
>>> #Converts all the alphabets to the upper case
>>> s1.upper()
'HELLO WORLD. I LOVE PYTHON'
zfill(width) Returns the string after adding some leading zeros to make the string
length equal to the specified width.
>>> s1="123"
>>> s1.zfill(4)#Add leading zeros
'0123'
>>> s1.zfill(8)#Add leading zeros
'00000123'
Solution steps:
1. Read the string.
2. Initialize a blank string
2. Iterate over each character of the string
2.1 if the character is upper, convert to lower and then add to the blank string
391
2.2 else, convert to upper and then add to the blank string
str="Python Programming Language V3.11.4"
res = "" #Create a blank string
for ch in str: #Iterating each character of the string
if ch.isupper():
res += ch.lower() #Converting upper case character to lower
else:
res += ch.upper() #Converting lower case character to upper case
print(res)
Output
pYTHON pROGRAMMING lANGUAGE v3.11.4
Program 9.2: Write a program to remove all the punctuation symbols in a string.
Solution steps:
1. Create a string containing all the punctuation symbols to be removed
2. Read the string.
3. Iterate over each character of the punctuation string
3.1 Replace all occurrences of a punctuation symbol
#a string containing punctuation symbols
punctuation_str ='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
str = "Hello World! I am a Python enthusiast, and love programming."
print("Original String :\n\t",str)
for c in punctuation_str: #Iterate over each punctuation
str = str.replace(c,"") #Replace occurrences of a punctuation mark
print("After removing Punctuations :\n\t",str)
Output
Original String :
Hello World! I am a Python enthusiast, and love programming.
After removing Punctuations :
Hello World I am a Python enthusiast and love programming
392
Program 9.3: Write a program to convert an integer into equivalent binary, octal and
hexadecimal strings.
Solution steps:
1. Read the integer
2. Convert the integer into binary, octal and hexadecimal strings
3. Remove the first two characters from the binary, octal and hexadecimal intro strings
i = int(input("Input an integer: ")) #Read an integer
#Convert to octal and remove the first two characters
o = str(oct(i))[2:]
#Convert to hexadecimal and remove the first two characters
h = str(hex(i))[2:]
h = h.upper()
#Convert to binary and remove the first two characters
b = str(bin(i))[2:] d = str(i)
print("Decimal : ",d)
print("Octal : ",o)
print("Hexadecimal (capitalized) :",h)
print("Binary :",b)
Output
Input an integer: 26
Decimal : 26
Octal : 32
Hexadecimal (capitalized) : 1A
Binary : 11010
Program 9.4: Write a program to print the smallest and the largest words in a string.
Solution steps:
1. Read the string
2. Replace all punctuation marks with a space character
3. Iterate over the characters of the string and separate words
4. Find the smallest and largest words based on the lengths of the words
punct_str ='!,.;:-'
str = "Popular Programming Laguages:Python, Java,C++ and C"
print("Original Strings : ",str)
393
for ch in punct_str:
str=str.replace(ch,' ')# Replace punctuation marks
word = ""
all_words = [] #Empty word list
str = str + " "
for i in range(0, len(str)):
if(str[i] != ' '):
word = word + str[i] #Detect a word
else:
if len(word)!=0 : #Ignore zero length word
all_words.append(word) #Append the word to the list
word = ""
Output
Original Strings : Popular Programming Laguages:Python,Java,C++ and C
Smallest word: C
Largest word: Programming
Solution steps:
1. Read the string
2. Initialize a blank string
3. Iterate over the characters of the string
3.1 if the character is in the blank string then
ignore it
3.2 else
add the character in the blank string
394
s="Python Programming Language"
s1=""
for ch in s: #Iterate over each character of the string
if ch not in s1: #If the character is included in the new string,
ignore it
s1=s1+ch #Add character to the new string
print(s1)
Output
Python rgamiLue
Solution steps:
1. Read the string
2. Initialize a string with the first character of the original string as the target string
3. Take the first character of the string
4. Remove the first character of the original string
5. Iterate over the characters of the modified original string
3.1 if the character is equal to the previous character
ignore it
3.2 else
add the character in the target string
update the previous character
s='AAAABBBBCCCCAAAABBBBCCCC' #Original string
s1=s[0] # Create a string with the first character of the string
ch1=s[0]# Take the first character
s=s[1:] # Remove the first character from the original string
for ch in s: #Iterate over the modified original string
if ch != ch1:#Skip the character if it is equal to the previous
s1=s1+ch #Append the character in the new string
ch1=ch #Update the previous character
print(s1)
Output
ABCABC
395
Chapter Summary
(a) tho
(b) ytho
(c) th
(d) None of the above
396
3. What will be the output of below Python code?
str1="Python"
str2=str1.replace('y','Y')
print(str2)
(a) Python
(b) PYthon
(c) python
(d) None of the above
str1="Python"
str1.upper()
print(str1)
(a) Python
(b) PYTHON
(c) 'PYTHON'
(d) None of the above
7. Which of the following is not the correct way to access a character in a string?
(a) s[0]
(b) s[-1]
(c) s[1]
397
(d) None of the above
10. Which of the following is an incorrect Python statement, where s1 and s2 are
two string objects?
(a) s1+s2
(b) s1*s2
(c) s1 in s2
(d) s1 *3+s2
(a) 'AAAB'
(b) 'A3B'
(c) 'A^3B'
(d) None of the above
12. Which of the following is not a member function of the str class?
(a) capitalize
(b) len
(c) count
(d) center
398
13. What is the output of the following?
"abcd"[1:]
(a) a
(b) ab
(c) bcd
(d) dc
a) hello
b) \nhello
c) r\n hello
d) It is an error
(a) x\97A
(b) x\97\x41
(c) 97 41
(d) None of the above
399
18. What will be the output of the following Python code?
print (0xA + 0xB + 0xC)
(a) 0xA0xB0xC
(b) 0x22
(c) 33
(d) ABC
(a) on
(b) Python World
(c) ho
(d) None of the above
(a) Python
(b) Jython
(c) JPython
(d) It is an error
Review Questions
400
c. We cannot access individual character of a string using indexing.
d. We can use a triple single pair to create a string literal.
e. We cannot mix single and double quotes to create a string literal.
f. A str object can be created by assigning a string literal to a variable.
g. The max function returns the first character with the largest Unicode.
h. The statement s [-1] returns the second last character of the string s.
i. The statements s [-1] and s[len(s)] return the same character.
j. We cannot traverse a string in backward direction.
k. The slicing operator is used to extract a substring in a string.
l. We can use slicing with step of size 2 to get the alternate characters of s
string.
m. The + operator can be used concatenate two strings.
n. S1 in S2 return true if S1 is a sub string of S2.
o. S1 not in S2 return true if S1 is a sub string of S2.
p. S.capitalize() returns a corresponding string wilh all letters capitalized.
q. "ABC".center(7,"X") returns 'XXXABCXX'.
r. S.count('n') returns the number of characters in string S.
s. Is s.isdigit() and s.isdecimal() return the same output.
t. S.title() returns the string after making the first character of each word
capital of the string.
Programming Assignments
401
4. Write a program to print the frequency of each word in a given sentence.
5. Write a function to convert a given string to all uppercase if it contains at least 1
uppercase characters in the first 3 characters.
6. Write a program to sort characters of a string lexicographically, i.e. sorted in the
alphabetical order as used in dictionaries.
7. Write a program to check whether a string starts with a digit.
8. Write a function to return a leading zero padded string of specified width from a
given integer
9. Write a program to reverse each word in a string.
10 Write a program to convert a string into a list of words.
11. Write a program to print frequency of each vowel in a text.
12. Write a program to remove spaces and tabs from a given string.
13. Write a program to remove consecutive duplicate characters of a given string.
14 Write a program to count Uppercase, Lowercase, and digits in a given string
15 Write a function to get smallest and largest word in a given string.
16 Write a Python program to split a given paragraph into sentences.
402
Chapter 10
In addition to the list data type, Python has three other collection data types: tuple,
set and dictionary. Similar to the list, they can store heterogeneous data, i.e. their elements
can be of different types. They provide some special features to create more efficient
programs. This chapter describes these data types in more details.
10.1 Tuple
A tuple is an immutable collection of heterogeneous data. Example 10.1 shows some
examples of tuples consisting of different types of data. A tuple once created does not
permit to change the values of its elements (elements are read only) and addition/deletion
of elements, i.e. size of a tuple is fixed. Except for the immutable nature of the tuple, it is
very similar to the list. Since elements of a tuple is immutable, accidental modification of a
tuple is not possible. Hence, it is recommended to use a tuple in place of a list whenever the
collection is read only. Further, since a tuple is stored in a single block of memory, it is faster
than a list.
403
(1, 2, 3, 4)
>>> #Tuple of numbers and strings
>>> tuple2=(1,"Two", "Three",4)
>>> print(tuple2)
(1, 'Two', 'Three', 4)
>>> #Tuple of a list, a tuple, a set and a dictionary
>>> tuple3=([1,2],(1,3),{6,3},{1:"One",2:"Two"})
>>> print(tuple3)
([1, 2], (1,3), {3, 6}, {1: 'One', 2: 'Two'})
>>>
Placing all the data inside parentheses (), separated by commas, creates a tuple
literal and assigning it to a variable creates a tuple variable. For example, the statement t =
(1,2,3) creates a tuple. A tuple can have any number of items of different types (integer,
float, list, string, etc.). The parentheses are optional. Hence, assigning a set of values
separated by commas to a variable also creates a tuple. This is called the packing of values
as a tuple. For example, the statement t = 1,2,3 creates a tuple.
We can convert other data types into tuples by using the constructor of the tuple
class. Python permits conversion of other data into a tuple with the help of the tuple method
of the tuple class. For example, the statement t=tuple ([1,2,3]), converts a list into a tuple.
Example 10.2(b) illustrates the above concepts.
404
We can convert any collection data into a tuple. However, note the type of elements in
the returned tuple:
• When we convert a string into a tuple, all the characters of the string become
separate elements in the tuple.
• When we convert a list of strings into a tuple, the individual strings of the list
become the elements of the tuple.
• When we convert a dictionary into a tuple, the tuple consists of the keys of the
dictionary and values are ignored.
• In case of a range data, the tuple consists of series elements of the range as separate
elements in the tuple.
• Trying to convert atomic data, such as an int, a float, etc., will raise an error as the
tuple method can be used only with collections and sequences.
Similar to lists, tuples can also be created using the tuple comprehension from an
existing iterable data. Example 10.2(c) shows how to create a tuple of the even numbers
from a list using the tuple comprehension.
405
>>> tuple6=(1,"Two",(1,2)) #Heterogeneous tuple
>>> print(tuple6)
(1, 'Two', (1, 2))
>>> #Tuple with different types of data
>>> tuple7=([1,2],{4,5},{1:"One",2:"Two"})
>>> print(tuple7)
([1, 2], {4, 5}, {1: 'One', 2: 'Two'})
>>> list1=[1,2,3]
>>> tuple1=tuple(list1) #Convert a list to a tuple
>>> print(list1,tuple1)
[1, 2, 3] (1, 2, 3)
>>> s1="Python"
>>> tuple2=tuple(s1) #Convert a string to a tuple
>>> print(tuple2)
('P', 'y', 't', 'h', 'o', 'n')
>>> set1={1,2,3,2,3,4}
>>> tuple3=tuple(set1) #Convert a set to a tuple
>>> print(tuple3)
(1, 2, 3, 4)
>>> dict1={1:"One",2:"Two"}
>>> tuple4=tuple(dict1)#Convert a dict to a tuple
>>> print(tuple4)
(1, 2)
>>> r=range(3,6) #Create a range
>>> r
range(3, 6)
>>> tuple5=tuple(r)#Convert a range to a tuple
>>> print(tuple5)
(3, 4, 5)
>>> list1=["One", "Two", "Three"]
>>> x=enumerate(list1) #Create an enumerate object
>>> tuple6=tuple(x) #Convert an enumerate object to a tuple
>>> tuple6
((0, 'One'), (1, 'Two'), (2, 'Three'))
list1=[1,2,3,4,5,6,7,8]
#Tuple comprehension
tuple1=tuple(x for x in list1 if x%2==0)
406
print(tuple1)
Output
(2, 4, 6, 8)
sum The sum function sums all the elements if a tuple consists of
numeric values.
>>> tuple1=(1,2,3,4,5)
>>> sum(tuple1) #Sum all the elements
15
>>> tuple2=(2+3j,4-3j)#Can sum complex numbers
>>> sum(tuple2)
(6+0j)
>>> tuple3=(1,2.3,True)#Logical True=1 and False=0
>>> sum(tuple3)
4.3
>>> Tuple4=('a','b','c')
>>> sum(Tuple4)#Error: cannot sum non-numeric
Traceback (most recent call last):
File "<pyshell#54>", line 1, in <module>
sum(Tuple4)
TypeError: unsupported operand type(s) for +: 'int'
and 'str'
len The len method counts the number of elements in a tuple.
>>> tuple1=(1,2,3)
>>> len(tuple1) #Counts the number of elements
3
>>> tuple2=("Hello", "World")
>>> len(tuple2)
2
407
max The max function finds the maximum elements in a tuple.
>>> tuple1=(2,1,4,3,6,2)
>>> max(tuple1) #Find the maximum
6
>>> tuple2=('a','b','c','f','d')
>>> max(tuple2) #Find the character with maximum
Unicode value
'f'
>>> #Find the maximum string based on the dictionary
order
>>> tuple3=("Hello", "Hi", "Welcome")
>>> max(tuple3)
'Welcome'
>>> tuple4=(1,2,"Three",4)
>>> max(tuple4)#Error: mixing of strings and
integers are not allowed
Traceback (most recent call last):
File "<pyshell#67>", line 1, in <module>
max(tuple4)
TypeError: '>' not supported between instances of
'str' and 'int'
>>> tuple5=(1,2,True, False)#Integers and Booleans
are allowed together
>>> max(tuple5) #True=1 and False=0
2
min The min function finds the minimum of a tuple.
>>> tuple1=(2,4,2,6)
>>> min(tuple1) #Find minimum of a tuple
2
>>> tuple2=('a', 'b', 'c')
>>> min(tuple2)
'a'
>>> tuple3=("Hello", "World")
>>> min(tuple3)
'Hello'
>>> tuple4=(1,2,True, False)
>>> min(tuple4)
False
408
10.4 Indexing of Tuple Elements
Since a tuple is an ordered sequence of elements, an individual element of a tuple
can be accessed through an index. An index is given in a pair of square brackets and is
always an integer or a Boolean. Like lists, tuple elements can be accessed through positive
as well as negative indices. The positive indices start with 0, which refers to the first element
of the tuple. The negative indices start with -1, which refers to the last element of the tuple.
Figure 10.1 shows the positive and negative indexing schemes of a tuple. As can be seen
from figure 10.1, the same element can be accessed either using the positive indexing or the
negative indexing. For example, tuple1[0] and tuple1[-5] both will return the first element.
Similarly, tuple1[4] and tuple1[-1] will return the last element of tuple1. Example 10.4
illustrates the above concepts.
Forward index 0 1 2 3 4
tuple1 10 20 30 40 50
Backward index -5 -4 -3 -2 -1
>>> tuple1=(10,20,30,40,50)
>>> tuple1[0] #The first element of the tuple
10
>>> tuple1[-5] #The first element of the tuple
10
>>> tuple1[4] #The last element of the tuple
50
>>> tuple1[-1] #The last element of the tuple
50
>>> tuple1[0]+tuple1[-1] #Sum the first and the last element
60
>>> tuple1[True] #True is equal to 1
20
>>> tuple1[False] #True is equal to 0
10
>>> tuple
409
10.5 Slicing of Tuple
Similar to lists, multiple elements of a tuple can be obtained using a slicing
operation. A slicing operation on a tuple returns a tuple. Example 10.5 illustrates slicing
operations on a tuple.
>>> tuple1=(1,2,3,4,5,6,7,8,9,10)
>>> tuple1[:] #All elements of tuple1
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> tuple1[::2]#Alternative elements from start to end
(1, 3, 5, 7, 9)
>>> #Alternative elements from the second to ninth
>>> tuple1[1:9:2]
(2, 4, 6, 8)
>>> tuple1[::] #All the elements
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> tuple1[:4]#The first four elements
(1, 2, 3, 4)
>>> tuple1[-4:] #The last four elements
(7, 8, 9, 10)
>>> tuple1[::-1] #All the elements from end to start
(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
>>> tuple1[::-2] #Alternative elements from end to start
(10, 8, 6, 4, 2)
>>> tuple1[3:7] #All the elements from the forth to the seventh
(4, 5, 6, 7)
>>> tuple1[3:8:6] #Single element is also returned as a tuple.
(4,)
410
('Hello', 'World', 'I', 'Love', 'Python')
>>> tuple4=tuple1*2 #Repeat a tuple
>>> tuple4
('Hello', 'World', 'Hello', 'World')
>>> #Check presence of a value in a tuple
>>> 'Hello' in tuple1
True
>>> 'Hello' in tuple2
False
#Check absence of a value in a tuple
>>> 'Python' not in tuple1
True
tuple1=(1,2,3)
for t in tuple1: #Traversing a tuple
print(t, t*t)
Output
1 1
2 4
3 9
tuple1=(1,2,3)
for index in range(len(tuple1)): #Traverse using index
print(tuple1[index], tuple1[index]*tuple1[index])
Output
1 1
2 4
3 9
411
Example 10.7(c): Traverse using a while loop and an index
tuple1=(1,2,3)
n=len(tuple1)
index=0
while(index<n):#Traverse using a while loop
print(tuple1[index], tuple1[index]*tuple1[index])
index+=1
Output
1 1
2 4
3 9
tuple1=(1,2,3)
#Traverse using the enumerate function
for t in enumerate(tuple1):
print(t)
Output
(0, 1)
(1, 2)
(2, 3)
tuple1=((1,"One"),(2,"Two"),(3,"Three"))
for x,y in tuple1:#Unpacking while traversing
print(x,y)
Output
1 One
2 Two
3 Three
412
10.8 Sorting a Tuple
As discussed earlier, a tuple is an immutable sequence of data, hence it cannot be
sorted in place. However, we can convert a tuple into a list, which can be sorted and
converted back as a tuple. Example 10.8 illustrates the above process to get a sorted tuple.
tuple1=(1,6,4,2,8,9)
list1=list(tuple1)#Convert to list
list1.sort() #Sort the list
tuple2=tuple(list1) #Convert back to tuple
print("Original tuple:",tuple1)
print("Sorted tuple:",tuple2)
Output
Original tuple: (1, 6, 4, 2, 8, 9)
Sorted tuple: (1, 2, 4, 6, 8, 9)
tuple1=(1,2,3,4,5)
tuple2=('a', 'b', 'c', 'd', 'e', 'f', 'g')
zip1=zip(tuple1, tuple2)#Zipping tuples together
print(tuple(zip1))#Converting the zipped object into a tuple
Output
((1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'))
413
Example 10.9(b): Unzipping
>>> list1=[1,2,3]
>>> set1={7,8,9}
>>> dict1={1:"One",2:"Two"}
>>> #A tuple with a list, a set and a dict as its elements
>>> tuple1=(list1,set1,dict1)
>>> tuple1
([1, 2, 3], {8, 9, 7}, {1: 'One', 2: 'Two'})
>>> #Creating a new list with the same name does not change the tuple
>>> list1=['a','b']
>>> tuple1
([1, 3, 4], {9, 10, 7}, {1: 'One', 2: 'Two'})
>>> tuple1[0].append(5) #Mutable tuple element
>>> tuple1
([1, 3, 4, 5], {9, 10, 7}, {1: 'One', 2: 'Two'})
>>>
415
10.12 Tuple vs List
Both tuple and list can store heterogeneous data in an ordered sequence but there are
some differences in these two widely used data types, as given below:
a. A lists uses square brackets [] and a tuple uses parenthesis () to surround their
elements. For example, [1,2,3] is a list whereas (1,2,3) is a tuple.
b. A list is mutable in nature, i.e. we can edit, add/remove elements in a list, whereas
a tuple is immutable in nature, i.e., we cannot edit or modify a tuple once it is
created. If we try to edit a tuple, error will be generated as shown in example 10.12.
c. A list has variable length whereas a tuple has fixed length.
d. A tuple is stored in a single block of memory, whereas a list may be spread over
many blocks of memory. Due to this, tuples operations are faster as compared to
lists.
e. Lists has more built-in functions than that of tuple, therefore, there are many
additional functionalities associated with a list as compared to a tuple. For example,
we can perform sorting, reversal of elements in a list whereas these facilities are
unavailable in a tuple.
416
10.13 Sets
A set is an unordered collection of distinct items of various types. Since it is
unordered, it is unindexed, i.e. we cannot access elements with an index. Further, the
elements of a set are distinct. Hence a duplicate entry is not added into the set. In contrast
to the list, which is an ordered collection that maintains the elements in insertion order, the
set, being unordered collection of elements, does are not maintained any order. Hence,
traversal of a set may return items in a different order than the order of elements given
during creation. Example 10.13 illustrates the above.
a. Sets from data: By enclosing data within curly brackets, {}, separated by commas.
Non-hashable iterables, such as lists, dictionaries and sets are not allowed.
b. Sets from other data types: We can convert other iterable data types into sets by
using the set () method. The syntax is set_var = set(iterable_data).
c. Sets from the set comprehension: Similar to lists and tuples, the compression can
be used to create sets from an existing iterables.
Example 10.14(a) shows how to create sets from data, and example 10.14(b) shows how
to convert other types of iterables into sets. If there are duplicate entries in data or other
iterables, they are removed automatically. Further, order of the elements may change
during creation or conversion. If there is no element is a set, it is called an empty set, which
is denoted by set (). Please note, empty curly bracket, {}, represents an empty dictionary not
a set. An empty set is created by assigning set () to a variable. Example 10.14(c) shows how
to create a set using the set comprehension.
417
Example 10.14(a): Creating sets from data
list1=[1,2,3,4,5,6,7,8]
418
#Set comprehension
set1=set(x for x in list1 if x%2==0)
print(set1)
Output
{8, 2, 4, 6}
>>> set1={1,2,3}
>>> sum(set1) #Sum all the elements
6
>>> max(set1) #Find the maximum value in the set
3
>>> min(set1) #Find the minimum value in the set
1
>>> len(set1) #Count the number of elements in the set
3
>>> set2={"One", "Two", "Three", "Four"}
>>> max(set2) #Maximum based on the dictionary order
'Two'
>>> min(set2) #Minimum based on the dictionary order
'Four'
>>> sorted(set2) #Create a sorted list of the set elements
['Four', 'One', 'Three', 'Two']
>>> #Create an enumerated list of the set elements
>>> list(enumerate(set2))
[(0, 'Three'), (1, 'One'), (2, 'Four'), (3, 'Two')]
>>> set3={1,2, False}
>>> #Returns true if all the elements of the set are True
>>> all(set3)
False
>>> #Returns true if any element of the set is True
>>> any(set3)
True
419
10.16 Membership Operators: in and not in
Similar to other collection data types, sets also support in and not in operators to
check the existence of a value in a set. Example 10.16 illustrates their typical usages.
>>> set1={1,2,4,5,7}
>>> 2 in set1 #Check presence of a value in the set
True
>>> 2 not in set1 #Check absence of a value in the set
False
>>> set2={"Hello", "World"}
>>> "Hello" in set2 #Check presence of a value in the set
True
>>> "Hi" in set2 #Check presence of a value in the set
False
>>> set1={1,2,3}
>>> set1.add(4) #Add an element to the set
>>> set1
{1, 2, 3, 4}
clear() Removes all the elements from a set to make it an empty
set.
>>> set1={1,2,3}
>>> set1
{1, 2, 3}
>>> set1.clear() #Remove all the elements of
the set
420
>>> set1
set()
copy() Creates and returns a copy of the set
>>> set1={1,2,3}
>>> set2=set1.copy() #Create a copy of the
set
>>> set2.add(4)
>>> print(set1,set2)
{1, 2, 3} {1, 2, 3, 4}
difference(set2) Performs the set difference operation, i.e. to create and
return a set that contains the items that only exist in the
first set but not in the second set.
>>> set1={1,2,3}
>>> set2={1,2,5}
>>> set1.difference(set2) #Performs set1-set2
{3}
>>> set2.difference(set1) #Performs set2-set1
{5}
difference_update(set2) Removes the items from the set which are also in the set2.
It modifies the original set.
>>> set1={1,2,3}
>>> set2={1,2,5}
>>> #Remove the common elements from set1
>>> set1.difference_update(set2)
>>> set1
{3}
discard(value) Removes value from the set.
>>> set1={1,2,3,4}
>>> set1.discard(3) #Remove 3 from the set
>>> set1
{1, 2, 4}
intersection(set2) Performs the intersection operation of the set with set2
and returns the intersection set. The original sets are
unaffected.
>>> set1={1,2,3,4}
>>> set2={1,4,2,7}
>>> #Find intersection of the set with set2
>>> set1.intersection(set2)
{1, 2, 4}
421
#Find intersection of the set with set1
>>> set2.intersection(set1)
{1, 2, 4}
intersection_update(set2) Removes the items in the set which are not present in
set2. It updates the original set.
>>> set1={1,2,3,4}
>>> set2={1,4,2,7}
>>> #Remove elements from set1 which are not
in set2
>>> set1.intersection_update(set2)
>>> set1
{1, 2, 4}
isdisjoint(set2) Returns true if the set and set2 have no common values,
i.e. their intersection is an empty set.
>>> set1={1,2,3,4}
>>> set2={1,3,6,8}
>>> set3={5,6,7,8}
>>> #Check whether set1 and set2 are disjoint
set
>>> set1.isdisjoint(set2)
False
>>> #Check whether set1 and set3 are disjoint
set
>>> set1.isdisjoint(set3)
True
issubset(set2) Tests whether the set is a subset of set2, returns True if
so, otherwise returns False.
>>> set1={1,2,3}
>>> set2={1,2,3,4,5}
>>> set3={1,2,4,6}
>>> #Check whether set1 is a subset of set2
>>> set1.issubset(set2)
True
>>> #Check whether set1 is a subset of set3
>>> set1.issubset(set3)
False
issuperset(set2) Tests whether the set is a superset of set2, returns True if
so, otherwise returns False.
>>> set1={1,2,3,4,5,6}
>>> set2={2,4,5}
422
>>> set3={1,2,7}
>>> #Check if set1 is a superset of set2
>>> set1.issuperset(set2)
True
>>> #Check if set1 is a superset of set3
>>> set1.issuperset(set3)
False
pop() Removes an item from the set based on its internal
iterator and returns the removed value. The internal
iterator may return random values as a set is an
unordered and unindexed collection of items.
>>> set1={1,7,6,2,3}
>>> #Remove an item from set1
>>> set1.pop()
1
>>> #Remove an item from set1
>>> set1.pop()
2
remove(value) Removes value from the set.
>>> set1={1,2,3,4,5}
>>> #Remove 3 from set1
>>> set1.remove(3)
>>> set1
{1, 2, 4, 5}
symmetric_difference(set2) Returns the symmetric difference of the set and set2. The
symmetric difference of two sets A and B is the set (A –
B) ∪ (B – A).
>>> set1={1,2,3,5}
>>> set2={1,2,6,7}
>>> #Find the symmetric difference of set1
and set2
>>> set1.symmetric_difference(set2)
{3, 5, 6, 7}
symmetric_difference Updates the set with the symmetric difference of the set
with set2.
_update(set2)
>>> set1={1,2,3,5}
>>> set2={1,2,6,7}
>>> #Update set1 with the symmetric
difference of set1 and set2
>>> set1.symmetric_difference_update(set2)
423
>>> set1
{3, 5, 6, 7}
union(set2) Return the union of the set and set2. The original sets are
unaffected.
>>> set1={1,2,3,4}
>>> set2={3,4,5,6}
>>> set3=set1.union(set2) #Union of set1 and
set2
>>> set3
{1, 2, 3, 4, 5, 6}
>>> set1 #The original set unaffected
{1, 2, 3, 4}
update(set2) Adds all the elements of set2 into the set, ignoring the
already existing elements in the set.
>>> set1={1,2,3,4}
>>> set2={3,4,5,6}
>>> #Add all the elements of set2 into set1,
ignoring duplicates
>>> set1.update(set2)
>>> set1
{1, 2, 3, 4, 5, 6}
424
>>> for i,x in enm1: #Traversing a set using enumeration
print(x, end=" ")
(0, 'Three')
(1, 'One')
(2, 'Four')
(3, 'Two')
10.19 Frozenset
Python has added frozenset class that has the characteristics of a set, but it is
immutable, i.e. its contents cannot be modified after its creation. It is similar to a tuple and
can be used a key in a dictionary. Frozen sets are created using the frozenset () function.
The frozenset supports all the methods of the set class methods except the methods which
modifies the set itself. Example 10.19 shows how to create a frozenset and use it in a
dictionary.
10.20 Dictionaries
A dictionary in Python is basically an associative array, also called map, that holds
data in the form of key and value pairs. In this each key is associated with a value. It is
similar to a phone directory where we can find the phone number of a person based on his
name. Each key is unique and immutable in a dictionary. From Python 3.7, a dictionary is
an ordered and mutable collection of items. In the earlier versions of Python, dictionaries
are un-ordered collection. Example 10.20 shows examples of dictionaries.
a) From data: We can create a dictionary by placing key: value pairs within a pair of
curly brackets, {}, separated by commas. A key and the corresponding value is
separated by a colon, such as key1: value1. Keys must be immutable and hashable.
Hence, lists and sets cannot be used as keys. However, we can use tuples, strings,
integers, floats, complex numbers, Booleans as keys. In case of duplicate keys, the
value corresponding to the last duplicate key will be retained. In this way, we cannot
have duplicate keys in a dictionary. However, we can have duplicate values in a
dictionary. Example 10.21(a) illustrates the above.
426
b) From other collections: Other collections such as lists, tuples, sets can be converted
to dictionaries in a two-step process: First create a zip object of two iterables, the first
will work as keys and the other will work as values. In the second step, the function
dict() will be used to convert the zip object into a dictionary. Since, sets are
unordered collection, it is recommended not to use this method to convert sets into
dictionaries as keys and values are mapped randomly. Example 10.21(b) illustrates
the above process.
c) Dictionary comprehension: We can also create a dictionary using the dictionary
comprehension from existing collections. Example 10.21(c) illustrates the dictionary
comprehension.
d) From variables and values: The dict function can also be used with variables and
their values to create a dictionary. A dictionary can also be created using a list
consisting of tuples of key value pairs, using the dict function, see example 10.21(d).
427
Example 10.21(b): Create a dictionary using iterables
>>> list1=[1,2,3,4]
>>> list2=["One", "Two", "Three", "Four"]
>>> zip1=zip(list1,list2) #Zipping lists
>>> dict1=dict(zip1) #Convert a zipped object into a dictionary
>>> dict1
{1: 'One', 2: 'Two', 3: 'Three', 4: 'Four'}
>>> tuple1=(1,2,3,4)
>>> tuple2=("One", "Two", "Three", "Four")
>>> zip2=zip(tuple1,tuple2) #Zipping tuples
>>> dict2=dict(zip2)#Convert a zipped object into a dictionary
>>> dict2
{1: 'One', 2: 'Two', 3: 'Three', 4: 'Four'}
>>> set1={1,2,3,4}
>>> set2={"One", "Two", "Three", "Four"}
>>> zip3=zip(set1,set2) #Zipping sets
>>> dict3=dict(zip3) #Convert a zipped object into a dictionary
>>> dict3 #Note the randomness occurred due to sets
{1: 'Four', 2: 'Three', 3: 'Two', 4: 'One'}
>>> zip4=zip(list1,tuple2) #Zipping a list and a tuple
>>> dict4=dict(zip4) #Convert a hybrid zipped object into a dictionary
>>> dict4
{1: 'One', 2: 'Two', 3: 'Three', 4: 'Four'}
>>>
428
Example 10.21(c): Dictionary comprehension
>>> dict1
429
{'key0': 'Value0', 'key1': 'Value1', 'key2': 'Value2', 'key3':
'Value3', 'key4': 'Value4'}
>>> phone={"Amit":"12345678","Ram":"23412343","John":"32145643"}
>>> phone["Amit"] #Accessing through square brackets
'12345678'
>>> phone.get("Amit") #Accessing through the get method
'12345678'
430
10.24 Removing an Element from a Dictionary
An element of a dictionary can be removed by using del keyword. The syntax is del
dictionary[key]. Items in a Nested dictionary can also be deleted by using del keyword. If
we do not provide a key, the complete dictionary will be deleted. Example 10.24 illustrates
the above.
India
China
Japan
>>> for x in dict1: #The same as traversing through keys
print(x)
India
China
Japan
431
>>> for capital in dict1.values(): #Traversing for values
print(capital)
New Delhi
Beijing
Tokyo
>>> #Traversing for keys and values both
>>> for country, capital in dict1.items():
print(country,":", capital)
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> len(dict1) #Returns the count of the elements in the dictionary
4
>>> all(dict1) #Returns true if all the keys are True else False
True
>>> any(dict1) #Returns true if any of the keys are True else False
True
>>> dict2={0:"False",1:"True"}
>>> all(dict2) #Contains a False key
False
>>> any(dict2) #Contains a True key
True
>>> dict3={} #Empty dictionary
>>> all(dict3) #all() returns True for an empty dictionary
True
>>> any(dict3) #any() returns False for an empty dictionary
False
>>> sorted(dict1) #Returns a sorted list of all keys
['Four', 'One', 'Three', 'Two']
432
10.27 Methods of the Dict Class
The dict class has many methods to manipulate the elements of a dictionary object.
Table 10.4 list them and explains their usages with simple examples.
Method Description
clear() Removes all the elements from the dictionary and makes the dictionary
an empty dictionary.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> dict1.clear() #Remove all the elements of the
dictionary
>>> dict1 #An empty dictionary
{}
copy() Returns a shallow copy of the dictionary. For deep copy, use the
deepcopy method of the copy class.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> dict2=dict1.copy() #Shallow copy
>>> dict2
{'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}
>>> del dict2["Two"]
>>> dict1 #Original dictionary is not affected
{'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}
>>> dict2
{'One': 1, 'Three': 3, 'Four': 4}
fromkeys(keys, Returns a dictionary with the specified keys. Each key is assigned the
value) specified value. If the argument value is not given, the default value
None is assigned to all the keys.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> #Create a dictionary with the specified keys
>>> dict2=dict1.fromkeys(("One", "Three"))
>>> dict2 #Uses default value None
{'One': None, 'Three': None}
>>> dict2=dict1.fromkeys(("One", "Three"),2)
>>> dict2 #Uses the specified value
{'One': 2, 'Three': 2}
get(key) Returns the value of the specified key. If key does not exist in the
dictionary, the function returns None.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> dict1.get("Two") #Get the value of the specified key
2
>>> x=dict1.get("Five") #Returns None if key does not
exist
>>> print(x)
None
items() Returns a dict_items object containing a list of tuples of all key-value
pairs. The dict_items object is not subscriptable, hence we need to
convert it into a list or use a for loop to traverse it to access its elements.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> #Returns a dict_items consisting of tuples of key
value pairs
>>> x=dict1.items()
>>> x
dict_items([('One', 1), ('Two', 2), ('Three', 3),
('Four', 4)])
>>> list1=list(x) #Converting dict_items into a list
>>> list1
[('One', 1), ('Two', 2), ('Three', 3), ('Four', 4)]
>>> list1[0][0] #Accessing the first key
'One'
>>> list1[0][1] #Accessing the first value
1
>>> for a in x: #Traversing a dict_items
434
print(a)
('One', 1)
('Two', 2)
('Three', 3)
('Four', 4)
keys() Returns a dict_keys object consisting of a list containing all the keys of
the dictionary. The dict_keys object is not subscriptable, hence we need
to convert it into a list or use a for loop to traverse it to access its
elements.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
One
Two
Three
Four
>>>
pop(k, v) Removes the item from the dictionary with key=k and returns the
corresponding value. In case, k does not match with any key, the value,
v, is returned. If v is not specified and no matching key is found, an
error is generated.
>>> dict1={"One":1,"Two":2,"Three":3,"Four":4}
>>> dict1
{'One': 1, 'Two': 2, 'Three': 3, 'Four': 4}
>>> #Remove an item from the dictionary and returns its
value
>>> dict1.pop("Two")
2
>>> dict1
{'One': 1, 'Three': 3, 'Four': 4}
435
#If no matching key is found, it returns the value of the
second parameter.
>>> dict1.pop("Five", "Not Found")
'Not Found'
#If no matching key is found and the second parameter is
not given, an error is generated.
>>> dict1.pop("Five")
Traceback (most recent call last):
File "<pyshell#144>", line 1, in <module>
dict1.pop("Five")
KeyError: 'Five'
popitem() Removes and returns the last inserted item from the dictionary. The
returned value is in the form of a tuple of key-value pair.
436
>>> dict1
{'One': 1, 'Two': 2, 'Three': 3, 'Four': 4, 'Five': 5}
>>> dict3={"one": "i", "Three": "iii", "Six":6}
>>> dict1.update(dict3) #Replace the duplicate key values
>>> dict1
{'One': 1, 'Two': 2, 'Three': 'iii', 'Four': 4, 'Five':
5, 'one': 'i', 'Six': 6}
values() Returns a list of all the values in the dictionary
1
2
3
>>>
Solution steps:
1. Use reverse slicing to get the elements in reverse order
t=(1,2,3,4,5) #Original tuple
t=t[::-1] #Reverse slicing
print(t)
Output
(5, 4, 3, 2, 1)
Sample program 10.2: Write a Python program to calculate the sum and average value
of the numbers in a given tuple of tuples.
Solution steps:
437
1. Traverse the outer tuple to get inner tuple
2. Calculate the sum and average of the inner tuple elements
Sample program 10.3: Write a program to calculate distance of points from the origin.
Also find the point farthest from the origin. The x, y and z co-ordinates of points are
stored in a dictionary as given below:
d={'x': [1,2,4,4,2], 'y': [2,1,1,2,3], 'z': [1,5,2,3,4]}
Solution steps:
1. Traverse the dictionary to get coordinates of points
2. Calculate distance from the origin
3. Track the farthest point
import math #Import the math module for square root calculation
#Coordinates of points are stored in a dictionary
d={'x': [1,2,4,4,2],
'y': [2,1,1,2,3],
'z': [1,5,2,3,4]}
x=-1
index=0
print("p x y z : Distance")
for i in range(5): #Traverse the dictionary to get points
#Calculate distance of a point from the origin
a=math.sqrt(d['x'][i]*d['x'][i]+ d['y'][i]*d['y'][i]+
d['z'][i]*d['z'][i])
print(i+1, d['x'][i],d['y'][i],d['z'][i],":",round(a,2))
if a> x: #Track the farthest point
x=a
index=i
438
print("The farthest point is point no", index+1)
Output
p x y z : Distance
1 1 2 1 : 2.45
2 2 1 5 : 5.48
3 4 1 2 : 4.58
4 4 2 3 : 5.39
5 2 3 4 : 5.39
The farthest point is point no 2
Sample program 10.4: Write a program to create a new dictionary extracting few keys
from a master dictionary
Solution steps:
1. Create the master dictionary
2. Create the list of keys to be included in the new dictionary
3. Use comprehension to extract the desired key: values pairs
#Master dictionary
masterDict = {
"name": "Ravi",
"age":25,
"salary": 8000,
"city": "New Delhi" }
#Keys for the new dictionary
keys = ["name", "salary"]
#Creating sub dictionary
newDict = {k: masterDict[k] for k in keys}
print(newDict)
Output
{'name': 'Ravi', 'salary': 8000}
439
Sample program 10.5: Write a program that finds all pairs of elements in a list whose
sum is equal to a given value.
Solution steps:
1. Traverse the list of numbers
2. Find the complementary number
3. Check the presence of the complement in the list
4. Add the pair in the list of pairs
list1=[1,2,3,4,5,6,7,8,9] #List of numbers
target=10
pairs=[]
for n in list1: #Traverse the list
complement = target - n #Find the complementary number
if complement in list1: #Check the complementary number in the
list
pairs.append((n, complement))
print(pairs)
Output
[(1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)]
Sample program 10.6: Write a program to count frequency of each character in a string
and store the results in a dictionary.
Solution steps:
1. Convert the string to lower case
2. Create the list of characters of the string
3. Create a set of characters
4. Create an empty dictionary
5. Iterate the set to get each character
6. Count the character in the list and add to the dictionary
#Original string
string="Welcome to Python Programming Language"
string1=string.lower() #Covert upper case letters to lower case
list1=list(string1)#Create list of characters of the string
set1=set(list1) #Convert the list to a set to remove the duplicate
characters
dict1={} #Initialize an empty dictionary
for x in set1: #Iterate over the set elements
dict1[x]=list1.count(x) #Get the count of a character
print(dict1)
440
Output
Character: Frequency
m :3
w :1
g :4
a :3
u :1
c :1
h :1
l :2
o :4
:4
n :3
t :2
r :2
y :1
e :3
p :2
i :1
Sample program 10.7: Write a program to convert a dictionary into a list of tuples
containing key-value pairs.
Solution steps:
1. Convert the dictionary into a dict_obj object list
2. Convert dict_obj object into a list of tuple
#Original dictionary
d = {'Red': 1, 'Green': 3, 'White': 5, 'Black': 2, 'Pink': 4}
d1=d.items() #Create dict_obj object from the dictionary
print(list(d1)) # Convert dict_obj into a list of tuple
Output
[('Red', 1), ('Green', 3), ('White', 5), ('Black', 2), ('Pink', 4)]
441
Sample program 10.8: Write a program to extract elements in a tuple having k digits.
Solution steps:
1. Traverse the tuple
2. Convert the element into string
3. Calculate the length of the string
4. if the length of the string is equal to the desired number of digits, add to the list
val = (12,123,453,2,6,34) #Original tuple
print("Original List : " ,val)
k = 2 #Number of digits in retracted elements
#Extract the elements with k digits
res = [ele for ele in val if len(str(ele))==k]
print("Extracted Tuples : " ,res)
Output
Original List: (12, 123, 453, 2, 6, 34)
Extracted Tuples : [12, 34]
Sample program 10.9: Write a program to extract symmetrical tuples form a list of
tuples of two elements.
Solution steps:
1. Convert the list into a set to remove duplicate tuples
2. Create a set by swapping the elements of the tuples of the list
3. Take the intersection of the above two set to get the symmetrical tuples
#List of tuples
myList = [(3, 4), (5, 1), (1, 5), (7, 4),(4,3),(5,6)]
print("The tuple list : " + str(myList))
# Extracting all Symmetric tuples from list
set1 = set(myList) # Convert the list into a set
set2 = {(b, a) for a, b in myList} # Exchange the tuple elements
symTupleSet = set1 & set2
# Printing Symmetric tuples
print("Symmetric tuples : " + str(symTupleSet))
Output
The tuple list : [(3, 4), (5, 1), (1, 5), (7, 4), (4, 3), (5, 6)]
Symmetric tuples : {(4, 3), (5, 1), (3, 4), (1, 5)}
442
Chapter Summary
443
19 A dictionary in Python is basically an associative array, also called map, that
holds data in the form of key and value pairs.
20 We can create a dictionary by placing key: value pairs within a pair of curly
brackets, {}, separated by commas.
21 An element of a dictionary can be accessed by using the key of the element in a
pair of square brackets, [].
22 A dictionary can be used as a value in other dictionary. In this way, we can create
a nested dictionary. Nesting can be done at any depth.
23 An element of a dictionary can be removed by using del keyword. The syntax is
del dictionary[key].
24 A dictionary can be traversed to access all the keys and values one by one using
a for loop.
444
(b) tuple1 = (1, (2,3), [1,2])
(c) tuple1 = (3,)
(d) None of the above
9. Which of the following cannot be used to get the first element in tuple t =
(1,2,3,4,5)?
(a) t[0]
(b) t(0)
(c) t[-5]
(d) None of the above
10. For a tuple, which of the following will be used to get all the elements of the
tuple?
(a) t[:]
445
(b) t[::]
(c) t[0:10:1]
(d) All of the above
446
(d) All of the above
20. Which of the following built-in method cannot be used with a dict object?
(a) len
(b) all
(c) any
(d) None of the above
21. Which of the following is not true for an empty dict object, d?
(a) all(d) returns true
(b) any(d) returns false
(c) all(d) returns false
(d) None of the above
(a) True
(b) False
447
(c) Error
(d) None of the above
23. What will be the output of the following Python code snippet?
d1 = {"abc":40, "xyz":45}
d2 = {"abc":"40", "xyz":45}
print(d1 == d2)
(a) True
(b) False
(c) Error
d) None of the above
24. For code, d = {"abc":40, "xyz":45}, the number of entries in the dictionary can
be obtained by?
(a) d.size()
(b) len(d)
(c) size(d)
(d) All of the above
Review Questions
448
b. A tuple can store heterogeneous data.
c. An integer and a string cannot be stored in a single tuple.
d. A tuple is more efficient to store a read only collection than a list.
e. A tuple is stored in a single block of memory.
f. The code t = (2) will create a tuple object.
g. The code t= (2,) will create a tuple object.
h. Any collection can be converted in a tuple.
i. Comprehension can be used to create a collection.
j. The code sum ((1,2,3.0)) returns 6.
k. The code sum sum ((1,2,"3")) returns 6.
l. The code t [-1] returns the last element of the tuple t.
m. The code t [1] returns the first element of the tuple t.
n. The code t[::-1] returns the elements of tuple t in reverse order.
o. The code, 3 in (1,2,3) returns 3.
p. A tuple cannot sort its elements in place.
q. The zip () function is used to generate a zipped object from tuples.
r. The code t.count(n) returns the number of elements in the tuple.
s. A tuple cannot contain mutable sequences.
t. A set is an unordered collection of distinct items of various types.
u. During the traversal of a set, elements of the set may be in different order
than the order of elements given during creation.
v. An empty {} represents a set.
w. An empty set is created as s=set ().
x. The code sorted(set1) returns a sorted set.
y. The code sorted(set1) returns a sorted list of the set elements.
449
z. We cannot use an index to access an element of a set.
aa. A frozenset is mutable.
bb. A dictionary in Python is basically an associative array.
cc. A dictionary is also called a map.
dd. Keys must be immutable and hashable.
ee. Lists and sets cannot be used as keys.
ff. We can have duplicate keys in a dictionary.
gg. We cannot have duplicate values in a dictionary.
hh. The zip object of two lists can be used to create a dict object.
ii. We cannot append key: value pairs to an existing dict object.
jj. We cannot create a dict object using comprehension.
kk. We can access an element of a dict object using indexing.
ll. We cannot nest dictionaries.
mm. We cannot delete items from a dictionary.
nn. A dictionary can be traversed using a for loop.
oo. The len(d) returns the count of elements in dictionary d.
Programming Assignments
3. Write a program to sort a list of tuples based on the number of elements in the
tuples.
450
5. Write a program to sort a list of tuples based on the second item in the tuple. All
the tuples have n numbers.
6. Write a program to test that two sets have at least one common item.
9. Write a program to create a dictionary to store n: n*n*n as key: value pairs for 1
to 10.
14. Write a program to accept the strings which contains all vowels.
451
452
Chapter 11
File Handling
Learning Outcomes
Until now, we have used input and print functions to read and write data in a
program/script. This console-oriented (using keyboard and monitor) input and output
operations are fine for small programs where a small amount of data are involved. Further,
data stored in RAM are temporary and when we close the program or computer, data is
lost. However, programs for real-life situations invariably involve a huge amount of data to
be read and written by the programs. In such situations, files are used to store data and
perform input and output operations.
A file is a collection of data in the form of records. It is used to store data in a storage
device, such as a hard disk, pen drive, etc., permanently. A file can be created manually
using an editor or a file can be generated by a program. Later, when data is required, data
stored in a file can be retrieved using file reading operations. File handling is a set of
processes used to store and retrieve data as and when required by a program. Typical
processes involved in file handling are: creating a file, opening a file, reading data from a
file, writing data to a file, and closing a file. Data in a file can be stored in human-readable
text format (called text file) or in binary code (called a binary file). Python has rich and easy-
to-use facilities for handling both text and binary files.
On the other hand, a binary file uses raw data and does not apply any encoding
before writing it on the disk. Hence, they can only be read by the program (or compatible
programs) that has generated it. Binary files are typically used to store actual content such
as an image, audio, video, executable files, etc. A binary data file is not human-readable.
454
Input file
stream
Input file
Output file
stream
Output file
455
file_object = open(file_name, mode='r', buffering=-1, encoding=None,
errors=None, newline=None)
Table 11.1 briefly describes the various parameters of the open function. Except for
the file_name parameter, all other parameters are optional. The function opens the file
specified by the file_name parameter according to the other parameters and returns a file
object if successful, else generates an error message. The opened file should be closed by the
programer after the file operations in no longer required.
We can also use the open () function to open a file with a with statement as given
below. The primary advantage of this format is that the file will be closed automatically
as soon as we exit the block. Sometimes, we forget to close a file which leads to tied up
resources that we no longer required. Other than the above, there is no other difference.
statement2
Parameter Description
file_name It is a string that contains the name of the file to open. If it contains only the
name of the file, the file will be looked at in the current folder. However, we
can also include the relative or absolute path of the file in the file_name
variable. The absolute path of a file contains the root element and the
complete directory list required to locate the file, for example,
"C:\Users\MBM\Documents\Python". Whereas, the relative path of a file
refers to a location that is relative to the current directory, for example,
"Documents\Python".
456
mode It is a string that specifies the mode in which the file is opened. A file can be
opened in different modes, such as read, write, append, text, binary, etc. In
the read mode, we can only read data from the file. Whereas, in the write
mode, we can only write data in the file. In the append mode, we can write
data at the end of the existing content of the file. In the read and write mode,
reading and writing from/to the same file are permitted.
buffering It is an integer that is used to set the buffering policy. Buffering is the process
of transferring a chunk of data from the disk to the main memory (or from
the main memory to the disk) from where it will be used by a program. This
reduces the number of disk access and improves performance. The following
are the buffering policy supported in Python:
No buffering: In this mode, there is no buffering of the data and all the
operations are directly performed on the disk file. For this mode, we set the
value of the buffering parameter = 0. This mode is allowed only in binary
file mode.
Line buffering: In this mode, one disk operation is performed till a newline
character is encountered and is only used in the text mode. For this mode,
we set the value of the buffering parameter = 1.
Fixed-size chunk buffer. In this mode, a fixed size of data is moved from
the disk to the main memory or vice versa in one disk operation. When the
buffering parameter is >1, this mode is used.
457
By default, the buffering policy (buffering=-1) works as follows: for binary
files, the fixed size buffering of typically 4096 or 8192 bytes is used and for
text files, the line buffering is used.
errors It is a string that specifies how encoding and decoding errors in text files are
to be handled. It is important to note that the same encoding and decoding
scheme should be used for a consistent result. Following are the commonly
used values that the error parameter can take:
'ignore': it ignores encoding and decoding errors. Please note, this setting
may lead to data loss.
newline It is a string. It can take anyone of the following values: None, '', '\n', '\r',
and '\r\n'. These are the legal values of the newline parameter. The default
value of the newline parameter is None. This parameter is used only with
text files.
While in the reading mode, if the newline parameter is set to None, the
newline characters ('\n', '\r', or '\r\n') are translated into '\n' before being
returned to the caller. If it is set to empty string, i.e. '', no translation takes
plance and the given newline characters are returned to the caller. If it is set
to other legal values, input lines are only terminated by that string, and the
original line ending is returned to the caller.
While in the writing mode, if the newline parameter is set to None, the new
line characters are translated to the system's default line separator. If the
parameter is set to ' ' or '\n', no translation takes place. If the parameter is set
458
to the other legal values, newline characters are translated to the given string
before writing.
Mode Description
'r ' Opens a text file for reading only. This is the default mode. The file pointer is
placed at the start of the file.
'rb' Opens a binary file in the read-only mode. The file pointer is placed at the
beginning of the file.
'r+' Opens an existing text file for both reading and writing. If the file does not exist,
it will raise an error. The file pointer is placed at the beginning of the file. Write
operations will overwrite the existing content from the current file pointer.
'rb+' Opens an existing file for both reading and writing in binary format. If the file
does not exist, it will raise an error. The file pointer is placed at the beginning of
the file.
'w' Opens a file for writing only. If the file already exists, its contents will be deleted
and if the file does not exist, it creates a new file for writing. The file pointer is
placed at the beginning of the file.
459
'wb' Opens a file for writing only in the binary format. If the file already exists, its
contents is deleted and if the file does not exist, it creates a new file for writing.
The file pointer is placed at the beginning of the file.
'w+' Opens a file for both writing and reading in the text mode. If the file already
exists, its contents will be deleted and if the file does not exist, it creates a new
file for both reading and writing. The pointer is placed at the beginning of the
file.
'wb+' Opens a file for both writing and reading in the binary mode. If the file already
exists, its contents are deleted and if the file does not exist, it creates a new file
for both reading and writing. The pointer is placed at the beginning of the file.
'a' Opens a text file in the append mode for writing at the end of the existing content
of the file. If the file does not exist, it will create a new file for writing. For an
existing file, the file pointer is placed at the end of the existing content. No
writing is allowed in the existing content. We cannot send the file pointer in the
existing content with the help of the seek () method, i.e. writing will always be
at the end of the existing content.
'ab' Opens a binary file in the append mode for writing at the end of the existing
content of the file. If the file does not exist, it will create a new file for writing.
For an existing file, the file pointer is placed at the end of the existing content.
No writing is allowed in the existing content.
'a+' Opens a text file in the append mode for both reading and writing at the end of
the existing content of the file. If the file does not exist, it will create a new file
for writing. For an existing file, the file pointer is placed at the end of the existing
content. No writing is allowed in the existing content. However, the read pointer
can be moved to the beginning of the file for reading the existing contents also.
'ab+' Opens a binary file in the append mode for both reading and writing at the end
of the existing content of the file. If the file does not exist, it will create a new file
for writing. For an existing file, the read and write file pointers are placed at the
end of the existing content. No writing is allowed in the existing content.
However, the read pointer can be moved to the beginning of the file for reading
the existing contents also.
460
x Exclusively creates a new file for writing. If the file already exists, it will raise an
error. The file pointer is placed at the start.
Modes
Operations r r+ w w+ a a+ x
Read Yes Yes No Yes No Yes No
Write No Yes Yes Yes Yes Yes Yes
Write after seek No Yes Yes Yes No No Yes
Read after seek Yes Yes No Yes No Yes No
Create a new file No No Yes Yes Yes Yes Yes
Erase the existing content No No Yes Yes No No No
Default initial file pointer location Start Start Start Start End End Start
Method Description
close() Closes the opened file. We should close all the opened files if no further
file operations are required. This frees the resources.
flush() Clears the internal buffer of the opened file stream.
read() Reads the complete content of the file and returns it.
readable() Returns true if the file stream permits reading operations, otherwise
returns false.
readline() Reads and returns one line from the file and moves the file pointer to the
next line.
readlines() Reads all the lines of the file and returns them as a list of strings.
seek() Reposition the file pointers to perform the next operation.
seekable() Returns true if the file allows us to change the file pointer position, else
returns false.
tell() Returns the current file pointer position.
truncate() Truncates the data beyond the specified size.
writable() Returns true if the file permits writing operations, else it returns false.
461
write() Writes the specified string to the file.
writelines() Writes a list of strings to the file.
11.4 Reading from a Text File
A file object has many methods to read data from a file: readline (), readlines () and
read (). These methods can be used if the file permits reading operation, i.e. file is opened
in the read mode or the read and write mode. The content of the input file to illustrate these
methods is given in figure 11.2
The readline (n=-1) method reads the maximum n characters or up to the end of the
line of the current line (starting from the current file pointer) from the file. If n is not given
or n = -1, it reads up to the end of the current line. If n is more than the number of remaining
characters in the current line, the reading will stop at the end of the line. The read data are
returned as a string. After reading, it moves the file pointer to the next reading location. At
the end of the file, it returns an empty string. Example 11.4(a) uses the readline method to
read a file line by line and convert each line to the upper case and print it on the console.
Example 11.4(b) reads 10 bytes of data and convert them to the upper case and print on the
console. As can be seen from the example, at the most specified number of characters (here
n=10) are read from the current line. If the available number of characters in the line is less
than 10, only the available characters are returned.
462
LINE1: HELLO WORLD.
Example 11.4(b): Read the specified number of characters from a line from a text file
fp.close()
Output
LINE1: HEL
LO WORLD.
LINE2: I L
OVE PYTHON
PROGRAMMI
NG.
LINE3: IT
IS ONE OF
THE MOST W
IDELY USED
PROGRAMMI
NG LANGUAG
ES.
The readlines (n=-1) method reads the lines till the total returned bytes exceeds n or
up to the end of the file (starting from the current file pointer). Once the reading of a new
line starts, the reading will continue till the end of the line even if it exceeds the returned
bytes than n. For example, suppose if a file contains four lines and each line contains 10
bytes and n is set to 23, the readlines () will read the first three lines and a total of 30 bytes.
This is because once the readlines () start reading a new line, it reads till the end of the line.
If n is not given or n = -1, it reads up to the end of the file. If n is more than the number of
463
remaining characters in the file, it will read all the reaming lines of the file. The read data
are split into sub-strings at each newline character and return as a list of strings. The newline
character is retained in each string. After reading, it moves the file pointer to the next
reading location. At the end of the file, it returns an empty string. Example 11.4(c) uses the
readlines () method to read all the lines of a file and print them on the console as raw byte
strings. Example 11.4(d) reads lines till the total returned bytes exceeds 30 and print each
read line on the console as a raw byte string along with the length of the line.
fp=open("file1.txt","r") #Open the file in the text and read only mode
list1=fp.readlines()
for line in list1:
print(bytes(line, encoding="UTF-8"))#Print as a raw byte string
fp.close()
Output
b'Line1: Hello World.\n'
b'Line2: I love Python Programming.\n'
b'Line3: It is one of the most widely used programming languages.\n'
Example 11.4(a): Read lines till the total returned bytes is less than the specified
value
The read(n) method reads the specified number of bytes from the file starting from
the current pointer and returns it as a string. If n=-1 (default) or n is more than the total
remaining bytes in the file, it reads all the remaining bytes. Example 11.4(e) reads all the
characters of a file and returns it as a string. Example 11.4(f) reads the first 25 characters of
a file and prints it as a raw byte string. The escape character sequences, such as '\n', are
counted as one character.
464
Example 11.4(e): Read all the lines of a file as a string
fp=open("file1.txt","r") #Open the file in the text and read only mode
string1=fp.read() #Read all the remaining bytes from the file
print(string1) #Print as a string
fp.close()
Output
Line1: Hello World.
Line2: I love Python Programming.
Line3: It is one of the most widely used programming language.
The writelines (List) method writes the content of the List parameter, which is a list
of strings, into the file. Please note, all the elements of the list should be a string. If we want
to write each list item into a separate line, we have to add a new line character at the end of
each string item. Further, to write numerical values, we have to first convert them into
strings. Example 11.5(a) reads four lines of text from the console and writes them to a file.
Example 11.5(b) creates the multiplication table of 1 to 10 and writes it into a file.
fp=open("file2.txt","w") #Open the file in the text and write only mode
for i in range(4):
line=input("Enter your string:") #Read a line from the console
#Write the line along with a newline character
fp.writelines([line,"\n"])
465
fp.close() #Close the file
Input
Enter your string: Hello, everyone
Enter your string: I am enjoying Python
Enter your string: It is an easy to learn language
Enter your string: Thanks
Output(file2.txt)
Hello, everyone
I am enjoying Python
It is an easy to learn language
Thanks
The write(text) method writes the specified text into the file, starting from the
current pointer. To use this function, the file must be open in the write mode, the append
466
mode, or read and write mode. The overlapping existing content will be overwritten. After
writing, the file pointer will move to the end of the currently written text. Example 11.5(c)
add a line of text at the end of a file using the write method. The file already has one line,
say, You are new to Python.
467
print(fp.read()) #Read the file and print
fp.close()
Output
10
10.5
13000.0
(3.4+3j)
True
False
11.7 Reading Numbers from a file
All the reading methods read data from the file and return it in the form of strings.
However, we can convert the returned values into other data types. If a line in the file
contains more than one number, we can split the returned strings into substrings and then
convert each sub-string to an equivalent number. Example 11.7(a) illustrates how to read
numbers from the file. The file contains 1 to 10 and each number is written in a separate line
and there is no blank line. The program reads all the numbers given in the file and finds
their sum. Example 11.7(b) reads numbers from a file, in which a line may contain more
than one number, separated by commas, in a line. The program reads a line as a string and
splits it along the commas and find the sum of numbers in each row and print on the
console.
fp=open("file5.txt","r") #Open the file in the text and read only mode
total=0
while(1):
s=fp.readline() #Reads a line and returns it as a string
if s=="": #Break the loop if the returned string is empty
break
n=float(s) #Convert the string to an equivalent number
total=total+n #Find sum
print(total)
fp.close()
Output
55.0
468
11.8 Seek and Tell Methods
Till now, we have read and have written data into a file sequentially. However, it is
possible to read and write data from any position in the file. For this, we have to reposition
the file pointer in the file using the seek method. The current position of the file pointer can
be obtained by the tell () method. The syntax of the seek () method is as given below
fp.seek(offset, reference)
where fp is the handle of the opened file, offset is an integer that specifies the number of
positions that the file pointer will move with respect to the specified reference. The reference
is specified by the second parameter reference. The reference parameter can take any of the
following three values: 0,1 and 2. The meaning of these values are:
0: sets the reference point at the beginning of the file, i.e. offset will be from the start.
This is the default setting. This is supported by both the text file mode and binary file
mode.
1: sets the reference point at the current file position, i.e. offset will be from the current
position. The positive value will move the pointer in the forward direction, whereas
the negative value will move the file pointer in the backward direction. This option is
only supported in binary file mode.
2: sets the reference point at the end of the file, i.e. offset will be from the end of the file.
The positive value will move the pointer in the forward direction, whereas the
negative value will move the file pointer in the backward direction. This option is
only supported in binary file mode.
The syntax of the tell () method is fp.tell() which returns the current location of the file
pointer with reference to the beginning of the file. The returned value is an integer.
Example 11.8(a) illustrates some usages of the seek () and the tell () methods. In this,
reading is performed from different locations of file file8.txt containing ABCDEFGHIJ.
Please note, the value of the file pointer of the first character of a file is 0. In example 11.8(b),
the seek () method is used to write a character at random locations in a text file. The original
file contains 0 to 9 out of which some digits are replaced by ‘#’.
469
Example 11.8(a): Reading randomly from a text file
470
11.9 Iterating over Lines in a File
We can iterate over the lines of a file using a for loop. The for loop returns the content
of the file line by line. This method can be used for both text files and binary files. Following
is the syntax:
Statement1
Statement 2
:
Statement n
Where fp is the file handle and line is a variable that holds each line. Once a line is
available, we can process it as any other string. Example 11.9 iterates over each line of a file
and print it on the console.
fp=open("file1.txt","r")
for line in fp: #Iterate over each line
print(line)
fp.close()
Output
Line1: Hello World.
471
an ASCII string requires around 2.75 times more disk memory than the data in the memory.
It also requires additional time to convert a float to a string during writing and convert it
back to a float during reading. This is a waste of disk space and time. Due to this, data sets
of any substantial size are invariably stored as binary rather than as text data.
Python supports the reading and writing of binary files. For this, we have to open a
file using binary file mode codes as given the table 11.2. In the binary file mode, data are
read and written in the form of byte strings. In this, the bit patterns of data in the memory
are directly written byte-by-byte in the file and they are not converted to any sort of string
representation before it is written. However, we require to pack the memory bit patterns
into a byte string so that it can be written in a binary file. Similarly, when we read data from
a binary file, it is returned as a byte string, which needs to be unpacked to convert then back
into the desired format. Unfortunately, there is no built-in function for these operations.
However, we can import and use the struct module that provides the pack () function which
converts the bit patterns of data into an equivalent byte string, and the unpack () function
which converts a byte string into desired data. Table 11.5 briefly describes the commonly
used functions of the struct module.
str=pack(fmt, *v) The pack () method converts the variable-length arguments into
a byte string as per the given format. The fmt parameter is a
string consisting of format characters according to which the
data will be converted into byte strings. The commonly used
format characters are: 'c' for a character, 's' for a byte array, 'i' for
integer, and 'f' for a float. We can precede these characters with a
number to indicate the number of repetitions. For example, '4s' is
equal to 'ssss'. These characters are mapped to the native size of
the computer. For other format specifiers, please see online help.
The second parameter of the function is a variable-length
argument. The argument can be of integer, float, and byte string
types. The function returns the bit patterns of the arguments as a
byte string according to the specified format. See the following
example:
472
>>> struct.pack('ii',340,5021) #Convert integers in
a byte string
b'T\x01\x00\x00\x9d\x13\x00\x00'
>>> #Convert floats in a byte string
>>> struct.pack('ff',3.124,1/3)
b'\x9e\xefG@\xab\xaa\xaa>'
>>> #Convert a string and a float in a byte string
>>> struct.pack('6sf',b"Python", 3.7)
b'Python\x00\x00\xcd\xccl@'
>>> #Convert the largest float in a byte string
>>> struct.pack('f',1.7976931348623157e+308)
b'\x00\x00\x80\x7f'
tple=unpack(fmt, str) The unpack () method is the opposite of the pack method and
converts a byte string into the original data as per the given
format. The meaning of the fmt parameter is identical to the
above. The second parameter, str, is a byte string. The function
returns the converted data in the form of a tuple. See the
following example which performs the reverse operations of the
above operations:
Example 11.10(a) writes the content of a list consisting of numeric values into a
binary file and reads it back into another list. The program also writes the same list into a
text file and compares the size of the binary and the text files. It also shows how the content
of a binary file will look if we read it as a text file. Example 11.10(b) writes the square roots
of 0 to 100 in a binary file and then returns the square root of a given integer number from
the file. The program uses the file as a look-up table.
474
fp=open("list.txt","r") #Open the text file for reading
st=fp.read() #Read the complete file as a string
print("Size of the text file:", len(st)) #Size of the text file
st=st.split("\n") #Split the string along the new line characters
st.remove("") #Remove the last blank entry
list3=[]
for x in st:
x=float(x) #Convert a string into a float
list3.append(x) #Add to list3
fp.close()
print("Read list:", list3)
Output
Original list [10.1234, 20.0323, 30.12312, 12345.564]
Read list: [10.12339973449707, 20.03230094909668, 30.123119354248047,
12345.564453125]
Size of the binary file: 16
Read list [10.12339973449707, 20.03230094909668, 30.123119354248047,
12345.564453125]
Size of the text file: 35
Read list: [10.1234, 20.0323, 30.12312, 12345.564]
Binary file printed as a text file: rù!A'B A&üðABæ@F
fp=open("list.dat","rb")
for i in range(4):
475
x=int(input("Enter a number:"))
fp.seek(x*struct.calcsize('f'),0) #Locate the file pointer
st=fp.read(struct.calcsize('f')) #Read a fixed size
x=struct.unpack('f',st) #Convert the byte to a float
print("Root is:", x[0])
fp.close()
Output
Enter a number:2
Root is: 1.4142135381698608
Enter a number:4
Root is: 2.0
Enter a number:9
Root is: 3.0
Enter a number:81
Root is: 9.0
Other than saving or transferring data, serialization can be used to save intermediate
states of a long computation, such as neural network training.
The commonly used standard Python modules to serialize and reserialize objects
are the pickle module and the json module. The pickle module saves data in binary format,
whereas the json module saves in a human-readable and language-independent format.
Currently, the JSON format is a very convenient and widely used format for data exchange.
It is recommended to use the json module for exchanging information among applications,
but use the pickle module for other use cases. The pickle is faster and more compact than
the json, but not human readable.
476
11.11.1 The pickle Module
We will briefly describe the two commonly used functions of the pickle module: dump ()
and load (). The dump () function writes the object into a file and uses the following syntax:
where obj is the object that we want to serialize and fp is the file handle where the serialized
data will be written. The file should be opened in binary and write mode.
The load () function reads the serialized file and reconstruct the object in memory and uses
the following syntax:
where the first parameter, fp, is the file handle of the serialized file, opened in the binary
and read mode.
Example 11.11(a) shows how to pickle and unpickle different types of Python objects.
477
fp=open("set.dat","rb")
set2=pickle.load(fp) #Unpickle a file containing a set
print(set2)
Output
[1, 2, 3, 4, 5]
(1, 2, 3, 4, 5)
{8, 3, 5, 6}
{1: 'One', 2: 'Two'}
[[1, 2, 3, 4, 5], (1, 2, 3, 4, 5), {8, 3, 5, 6}, {1: 'One', 2: 'Two'}]
Objects and arrays can be nested and used inside each other. Typically, a JSON file
contains an object or an array. If it contains an object, it will begin with an opening curly
bracket, {, and ends with a closing curly bracket,}. On the other hand, it contains an array,
478
it will start with an opening square bracket, [, and ends with a closing square bracket,]. The
following is a typical JSON data file to store the details of a person:
{
"FirstName": "Arvind",
"LastName": "Verma",
"Age": 51,
"Address": "XYZ, Jodhpur, India",
"City": "Jodhpur",
"State": "Rajasthan",
"PINCode": "123456",
"PhoneNumbers": [
{ "Mobile": "111-111-1111" },
{ "Home": "222-222-2222" }
]
}
Similarly, for storing details of more than one person, we can create an array of the
above objects, which is given as below:
[
{
"FirstName": "Rachna",
"LastName": "Verma",
"Age": 44,
"Address": "XYZ, Jodhpur, India",
"City": "Jodhpur",
"State": "Rajasthan",
"PINCode": "123456",
"PhoneNumbers": [
{ "Mobile": "111-111-1111" },
{ "Home": "222-222-2222" }
]
},
{
"FirstName": "Arvind",
"LastName": "Verma",
"Age": 51,
"Address": "XYZ, Jodhpur, India",
479
"City": "Jodhpur",
"State": "Rajasthan",
"PINCode": "123456",
"PhoneNumbers": [
{ "Mobile": "111-111-1111" },
{ "Home": "222-222-2222" }
]
}
]
Python JSON
dict Object
list Array
tuple Array
str String
int Number
float Number
True true
False false
None Null
The commonly used functions to serialize and deserialize various Python objects as
JSON files or strings are briefly described in Table 11.7. Example 11.11(b) converts a Python
object into a JSON string using a dumps () method and recreates the python objects from
the same JSON string using a loads () function. Example 11.11(c) serializes (saves) a Python
object into a JSON file using the dump () function and reserializes the same file in another
Python object. Example 11.11(d) shows how to convert non-serializable data into a JSON
string by first converting them into a serializable object.
480
Table 11.7: Functions of serialization and deserialization of Python objects as JSON
files and strings
dumps(obj, The dumps () function creates a JSON string of the obj parameter, where
[optional obj is any JSON serializable Python object (See table 11.6). See online
parameters]) helps for optional parameters, which are primarily used for formatting,
error detection, etc.
For example,
>>> import json
>>> x=["One","Two","Three"]
>>> json.dumps(x) #Convert a list into s JSON string
'["One", "Two", "Three"]'
>>> x={1:"One",2:"Two",3:"Three"}
>>> json.dumps(x) #Convert a dictionary into s JSON string
'{"1": "One", "2": "Two", "3": "Three"}'
>>> x=(1,2,3)
>>> json.dumps(x) #Convert a tuple into s JSON string
'[1, 2, 3]'
>>> x=10.0
>>> json.dumps(x) #Convert a number into s JSON string
'10.0'
>>> x=True
>>> json.dumps(x) #Convert a Boolean value into s JSON
string
'true'
>>> x=None #Convert None into s JSON string
>>> json.dumps(x)
'null'
481
True <class 'bool'>
>>> x=json.loads('null') #The JSON null to the Python None
>>> print(x, type(x))
None <class 'NoneType'>
482
{"name": "Dave", "age": 55, "married": true, "divorced": false,
"children": ["John", "Boby"], "pets": null, "vehicles": [{"car":
"Ford", "mileage": 16}, {"scooter": "Bajaj", "mileage": 50}]}
Output
Read a JSON file and convert it to a Python object:
{'name': 'Dave', 'age': 55, 'married': True, 'divorced': False,
'children': ['John', 'Boby'], 'pets': None, 'vehicles': [{'car':
'Ford', 'mileage': 16}, {'scooter': 'Bajaj', 'mileage': 50}]}
483
Example 11.11(d): Converting various types of objects into JSON strings
import json
#Serialise/Deserialize a complex number
print("Serialize/Deserialize a complex number")
c=4+5j
s=str(c) #Convert a complex number to a string
js=json.dumps(s) #Serialize as a string
print("JSON string:", js)
s1=json.loads(js) #Deserialize as a string
c1=complex(s1) #Convert a string to a complex number
print("Original:", c,", Recreated:",c1)
#Serialise/Deserialize a set
print("\nSerialize/Deserialize a set")
s={1,2,5,4,3}
list1=list(s) #Convert a set to a list
js=json.dumps(list1) #Serialize as a string
print("JSON string:", js)
list2=json.loads(js) #Deserialize as a list
s1=set(list2) #Convert a list to a set
print("Original:", s,", Recreated:",s1)
z=zip([1,2],('a','b'))
z2=zip([1,2],('a','b'))
list1=list(z) #Convert a zipped object to a list
js=json.dumps(list1) #Serialize as a string
print("JSON string:", js)
list2=json.loads(js) #Deserialize as a list
z1=zip(list2) #Convert a list to a zipped object
print("Original zipped object:")
for x in z2:
print(x)
print("Recreated zipped object:")
for x in z1:
print(x)
484
s=json.loads(js) #Deserialize as a string
bs1=bytes(s, encoding="UTF-8") #Convert a string to a byte string
print("Original:",bs,", Recreated:",bs1)
Output
Serialize/Deserialize a complex number
JSON string: "(4+5j)"
Original: (4+5j) , Recreated: (4+5j)
Serialize/Deserialize a set
JSON string: [1, 2, 3, 4, 5]
Original: {1, 2, 3, 4, 5} , Recreated: {1, 2, 3, 4, 5}
We frequently use the CSV (Comma Separated Values) format to store tabular data
in a text file. In the CSV format, each line of the file is a data record and each record consists
of one or more fields, separated by commas. Table 11.8 shows an example of a CSV file.
Commonly, .csv is used as the extension of a CSV file, but we can also use .txt extension.
The most commonly used character to separate fields, called delimiters, in a record, is a
comma. However, we can also use some other characters, such as tab, as a delimiter. In a
CSV file, normally the first line contains the names of the fields. If the value of a field
contains a comma i.e. a delimiter, the must be enclosed within double/single quotes.
485
Python has the csv built-in module to read and write CSV files. Table 11.9 briefly
describes the commonly used functions of the csv module. The functions discussed in the
table have many optional parameters, for those readers can refer to online documentation.
Further, there are other powerful modules, such as pandas, etc. for processing CSV files.
However, we will limit ourselves to only the csv module in this book.
487
11.13 File and Directory Management
As the number of files increases, we use folders/directories to group similar files
together for easy management. A folder or directory is a storage space, or container, where
files are stored in the computer. A folder can also contain other folders, called sub-folders.
In a computer, a tree structure is used to organize files and folders, where nodes represent
folders and leaves represent files. Sometimes, we require to create/delete/rename folders
or change directories in a program. For these tasks, Python has many modules but we will
discuss some commonly used functions of the os and shutil modules. Table 11.10 briefly
describes commonly used file and directory management functions of the os and shutil
modules. For more details about these modules and other functions, readers can refer to
online help.
488
>>> os.listdir() #Lists files and folders of the
current working directory
['All Users', 'Default', 'Default User',
'desktop.ini', 'MBM', 'Public']
>>> os.listdir("d:\\") #Lists files and folders of
the specified path
['$RECYCLE.BIN', 'abc.txt', 'akv', 'file1.txt',
'System Volume Information']
os.mkdir(dir) The os.mkdir () is used to create a new directory at the specified
path. The dir parameter is a string. If dir contains the absolute path
of a new directory, the new directory will be created there. If only
the name of a new directory is provided, the new directory will be
created in the current working directory. Please note, the program
requires the creation permission to create a directory in the
specified folder, otherwise, an access error will be generated.
>>> import os #Import the os module
>>> os.chdir("c:\\Users") #Change the current working
directory
>>> os.getcwd()
'c:\\Users'
>>> os.mkdir("text") #Create a new directory
>>> os.listdir() #List directory
['All Users', 'Default', 'Default User',
'desktop.ini', 'MBM', 'Public', 'text']
>>> #Creating a new directory at an absolute path
>>> os.mkdir("D:\\akv\\Book Python\\test")
>>> #List directory
>>> os.listdir("D:\\akv\\Book Python")
['Introduction to Python.docx', 'test']
489
os.remove(file) The os.remove () function deletes a file specified by the file
parameter.
>>> os.listdir() #List directory
['abc.txt', 'akv', 'file1.txt', 'Hi']
>>> os.remove("file1.txt") #Delete a file
>>> os.listdir()
['abc.txt', 'akv', 'Hi']
>>>
os.rmdir(dir) The os.rmdir () function deletes an empty directory. We cannot
use this function of remove non-empty directory. To remove a
non-empty directory, we can use the rmtree () function of shutil
module.
>>> os.listdir()
['abc.txt', 'akv', 'Hi']
>>> os.rmdir('Hi') #Remove an empty directory
>>> os.listdir()
['abc.txt', 'akv']
os.walk(root) The os.walk(root) function can be used to traverse all the
subfolders and files of a directory. The root parameter is the root
directory whose files and folders will be traversed. The function
returns a list of tuples. Each tuple consists of three items: the
current root folder name, a list of all the sub-folders in the current
folder, and a list of all the files in the current folder. Example
11.13(a) illustrates a use of the os.walk () function.
shutil.rmtree(dir) The shutil.rmtree () function removes the dir directory and all its
files and sub-directories. The dir parameter is a string that contains
the complete path of the directory to be deleted. If on directory
name is given, the directory in the current working directory will
be deleted.
490
parameter, dst, is the destination file. If the designation is a folder
name, then the file will be copied with the same name in the
designation location. However, if the destination is a file name, the
source file will be copied with the destination file name in the
destination file location. Example 11.13(b) illustrates an example
of the shutil.copy () function.
shutil.copytree(src, The shutil.copytree() function copies the src folder including all
dst) its subfolders and files to the dst folder. Example 11.13(c)
illustrates this.
shutil.move(src, dst) The shutil.move () function moves the src file to the dst folder.
Example 11.13(d) illustrates a use of the shutil.move () function.
Output
Directory level: 0
Current root folder: D:\test
List of directories:
D:\test\Folder1
List of files:
D:\test\file1.txt
D:\test\file2.txt
Directory level: 1
Current root folder: D:\test\Folder1
List of directories:
491
D:\test\Folder1\Folder2
List of files:
D:\test\Folder1\abc.txt
D:\test\Folder1\abc1.txt
Directory level: 2
Current root folder: D:\test\Folder1\Folder2
List of directories:
List of files:
D:\test\Folder1\Folder2\xyz.txt
D:\test\Folder1\Folder2\xyz2.txt
print("\nCopied Directory")
traverse_dir("D:\\test1")
Output
Original Directory
directory level: 0
Current root folder: D:\test
List of directories:
D:\test\dir1
List of files:
D:\test\file1.txt
D:\test\file2.txt
directory level: 1
Current root folder: D:\test\dir1
List of directories:
List of files:
D:\test\dir1\file1.txt
Copied Directory
directory level: 0
Current root folder: D:\test1
List of directories:
D:\test1\dir1
List of files:
D:\test1\file1.txt
D:\test1\file2.txt
directory level: 1
Current root folder: D:\test1\dir1
List of directories:
List of files:
D:\test1\dir1\file1.txt
493
Example 11.13(d): Move a file from one folder to another
Sample Program 8.1: Write a program to write the multiplication table of numbers
between n1 and n2 in a text file.
Solution steps:
1. Read n1 and n2.
2. Open the file in the write mode
3. Iterate between n1 and n2 to generate each number in the range.
3.1. Iterate between 1 and 10:
3.1.1 Calculate a multiplication term
3.1.2 Convert the term into a formatted string
3.1.3 Write the formatted value into the file
3.2. Write a newline character
4. Close the file.
494
fp.write("\n")#Write a newline character at the end of each line
fp.close() #Close the file
Output (The content of myTable.txt)
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
Sample Program 8.2: Write a program to read myfile.txt containg numbers in each row
separated by commas and find the sum of numbers in each row.
Solution steps:
1. Open the file and read all the lines.
2. Iterate over each line:
2.1 Split the line into substrings
2.2 Initialise sum
2.3 For each substring in the list:
2.3.1 Convert the substring into a float
2.3.2 Add the number to the sum
2.4 Print the sum of the line
with open("myfile.txt","r") as fp:#Open the file in the read mode
lines=fp.readlines() #Read all the lines
i=1
for line in lines: #Iterate over each line
numbers= line.split(",") #Split the line into substrings
s=0
print(f"Line {i}:", end="")
495
for n in numbers: #Iterate over each substring in a line
x=float(n) #Convert a subtring into a number
s=s+x #Calculate sum
print(x, end=" ") #Print numbers
print(", Sum = ", f"{s:<8.2f}") #Print sum
Output
Line 1:1.0 3.2 5.5 6.1 , Sum = 15.80
Line 1:2.0 3.0 , Sum = 5.00
Line 1:5.0 8.0 2.3 , Sum = 15.30
Line 1:5.0 2.0 1.5 6.0 7.0 , Sum = 21.50
Sample Program 8.3: Write a program that reads the entire contents of a file and count
the frequency of each character. Also print the total number of characters and total
number of unque characters in the file. Here, Sample program 1 given above is used as
input file for the illustration.
Solution steps:
1. Read the file name.
2. Check the existence of the file. If it does not exist exit.
3. Open the file in the read mode.
4. Read the entire content of the file in a str object.
5. Create an empty dictionary.
6. Iterate over each character of the string:
6.1 If the character exist in the dictionary, increment its count.
6.2 Else create a new key in the dictionary.
7. Iterate over each item in the dictionary and print the frequency.
8. Get the total number of characters and total number of unique characters in the file
using the len method.
from os import path #Import the path module
filename=input("Enter file name:") #Read the filename
check= path.exists(filename) #Check whether the given file exists or
not
if check == False: #Show mesaage:file does not exist
print("File does not exist")
exit(0)
file =open(filename,'r') #Open the file for reading
496
s=file.read() #Read the entire content of the file
d=dict() #Create an empty dictinary
for c in s: #Iterate over each character of the string
if c in d: #If the character exist as a key in the dict,increment
its count
d[c]=d[c]+1
else: #Create a new key in the dictionary and set count to 1
d[c]=1
print("Total number of characters:",len(s)) #Count total characters
print("Total number of unique characters:",len(d)) #Count total unique
characters
print("Frequencies of characters:")
for k in sorted(d): #Print frequencies of characters
print(k,"=", d[k], end=', ')
Output
Enter file name:sample1.py
Total number of characters: 910
Total number of unique characters: 49
Frequencies of characters:
= 19, = 146, " = 12, # = 13, ' = 4, ( = 14, ) = 14, + = 1, , = 8, . = 2, 0 = 1, 1 = 3, : = 10, = = 11,
C = 5, E = 1, F = 3, I = 3, O = 1, P = 1, R = 2, S = 1, T = 2, [ = 4, ] = 4, a = 44, b = 2, c = 37, d
= 22, e = 94, f = 25, g = 4, h = 28, i = 49, k = 8, l = 22, m = 14, n = 49, o = 35, p = 14, q = 4, r
= 47, s = 28, t = 69, u = 14, v = 2, w = 3, x = 6, y = 5,
Sample Program 8.4: Write a program that reads the entire content of a file and count the
frequency of each word. Here, Sample program 2 given above is used as input file for the
illustration. Here, Sample program 3 given above is used as input file for the illustration.
Solution steps:
1. Read the file name.
2. Check the existence of the file. If it does not exist exit.
3. Open the file in the read mode.
4. Read the entire content of the file in a str object.
497
5. Replace all non-alphabets with spaces.
6. Split the string into words.
7. Create an empty dictionary.
8. Iterate over each word in the list:
8.1 If the word exist in the dictionary, increment its count.
8.2 Else create a new key in the dictionary.
9. Iterate over each item in the dictionary and print the frequency.
10. Get the total number of words and total number of unique word in the file using the
len method.
from os import path #Import the path module
filename=input("Enter file name:") #Read the filename
check= path.exists(filename) #Check whether the given file exist or not
if check == False: #Show the message: file does not exist
print("File does not exist")
exit(0)
file =open(filename,'r') #Open the file for reading
s=file.read() #Read the entire content of the file
s1=""
for c in s: #Replace all non-alphabets with spaces
if c.isalpha()or c==" ": s1=s1+c
else: s1=s1 +" "
498
Check = 1, Count = 2, Create = 2, Enter = 1, False = 1, File = 1, Frequencies = 1, If = 1,
Import = 1, Iterate = 1, Open = 1, Print = 1, Read = 2, Replace = 1, Show = 1, Split = 1,
Total = 2, a = 3, all = 1, alphabets = 1, an = 1, and = 1, as = 1, c = 4, check = 2, content = 1,
count = 2, d = 8, dict = 2, dictinary = 1, dictionaly = 1, does = 2, each = 1, else = 2, empty
= 1, end = 1, entire = 1, exist = 4, exists = 1, exit = 1, file = 7, filename = 4, for = 4,
frequencies = 1, from = 1, given = 1, if = 3, import = 1, in = 7, increment = 1, input = 1,
into = 1, isalpha = 1, its = 2, k = 3, key = 2, len = 2, list = 2, message = 1, module = 1,
name = 1, new = 1, non = 1, not = 3, number = 3, of = 7, open = 1, or = 2, os = 1, over = 1,
path = 3, print = 5, r = 1, read = 1, reading = 1, s = 8, set = 1, sorted = 1, spaces = 1, split
= 1, string = 1, the = 12, to = 1, total = 1, unique = 2, whether = 1, with = 1, word = 7,
words = 10,
Sample Program 8.5: Write a program that prints the first and the n lines of a file. Here,
Sample program 3 given above is used as input file for the illustration.
Solution steps:
1. Read the file name
2. Read the number of lines to read
3. Check the existence of the file. If it does not exist exit.
4. Open the file in the read mode
4. Read all the lines using readlines() method
5. Print the first n lines.
6. Print the last n lines
from os import path #Import the path module
filename=input("Enter file name:") #Read the filename
n=int(input("Enter the number of lines to read from the start and the
end:"))
check= path.exists(filename) #Check whether the given file exist or not
if check == False: #Show the message: file does not exist
print("File does not exist")
exit(0)
file =open(filename,'r') #Open the file for reading
lines=file.readlines() #Read all the lines of the file
499
print(f"The first {n} lines are:")
for line in lines[:n]:
print(line, end="")
Sample Program 8.6: Write a program to create a book database using a binary file. Write
functions to add a new book, list all books and list books of an author. The book record
contains book ID, title, author and price.
Solution steps:
1. Import pickle module to handle binary files
2. Add book function:
2.1 Open file in append and binary mode
2.2 Input book ID, title, author and price
2.3 Create a book record using a list containing book details
2.4 add pickle.dump() method to write the record in the book database
2.5 Close the file
500
3. Get books by author function:
3.1 Open the book database in binary read mode
3.2 Input the author name
3.3 Iterate over each record in the file and print the record that matches with the
author
3.4 Close the file
4. List all the books functions:
4.1 Open the book database in binary read mode
4.2 Iterate over each record in the file and print them
4.3 Close the file
5. Create the main menu to get the choice
import pickle #Import the pickle module
501
print(record)
except EOFError:
pass
return count
file.close()
#Main menu
while(True): #Show menu
print("\nMain Menu")
print("1. Add a book")
print("2. Find author's books")
print("3. List all the books")
print("4. Exit")
Main Menu
502
1. Add a book
2. Find author's books
3. List all the books
4. Exit
Choose you option:1
Enter book ID: 5
Enter book name: Pearl
Enter author name: Shyam
Enter price: 230
Main Menu
1. Add a book
2. Find author's books
3. List all the books
4. Exit
Choose you option:2
Enter author name to search: Shyam
[2, 'C++', 'Shyam', 200]
[5, 'Pearl', 'Shyam', 230]
Main Menu
1. Add a book
2. Find author's books
3. List all the books
4. Exit
503
Choose you option:
Chapter Summary
1 A text file consists of binary forms of human-readable symbols and characters and
uses either ASCII or Unicode to form binary patterns of various symbols and
characters. On the other hand, a binary file uses raw data and does not apply any
encoding before writing it on the disk. Hence, they can only be read by the
program (or compatible programs) that has generated it.
2 File handling, in general, involves the following three steps: (1) opening a file, (2)
reading/writing data from/to the file, and (3) Closing the file.
3 The open() method is used to open a file, and the close() method is used to close
it. A file opened using the open () method with a with statement is automatically
closed after the file operation.
4 A file can be opened in different modes, such as read, write, append, text, binary,
etc. The valid mode values are 'r ', 'rb', 'r+', 'rb+', 'w', 'wb', 'w+', 'wb+', 'a', 'ab', 'a+',
'ab+' and 'x'.
5 Commonly used file handling functions are close(), flush(), read(), readable(),
readline(), readlines(), seek(), seekable(), tell(), truncate(), writable(), write(), and
writelines().
6 The commonly used standard Python modules to serialize and reserialize objects
are the pickle and the json modules.
7 The CSV (Comma Separated Values) format is used to store tabular data in a text
file. In the CSV format, each file line is a data record, and each record consists of
one or more fields, separated by commas. Python has the csv built-in module to
read and write CSV files.
8 The os and shutil modules are commonly used to manage files and directory
operations, such as copy files, rename files, move files, create directories.
504
Multiple Choice questions
505
(a) 'r'
(b) 'w'
(c) 'a'
(d) All of the above
8. Which of the following file mode will raise an error if we attempt to open an
existing file?
(a) 'r+'
(b) 'a'
(c) 'w'
(d) 'x'
9. To open a file c:\mydata.txt for reading, which of the following is the correct
statement?
(a) fp = open(“c:\ mydata.txt”, “r”)
(b) fp = open(“c:\\ mydata.txt”, “r”)
(c) fp = open(file = “c:\ mydata.txt”, “r”)
(d) i fp = open(file = “c:\\ mydata.txt”, “r”)
10. Which of the following method can be used to read the entire content of a file
and return it as a string
(a) read()
(b) readline()
(c) readlines()
(d) readall()
11. Which of the following methods can be used to read the entire file content and
return each line as an item in a list of strings?
(a) read()
(b) readline()
(c) readlines()
(d) readall()
12. To read five characters from a file object fp, which of the following statement can
be used?
(a) fp.read(5)
(b) fp.readline(5)
(c) fp.readlines(5)
(d) None of the above
506
13. Which of the following statement can be used to read all the remaining characters
of the current line of a file object fp?
(a) fp.read()
(b) fp.readline()
(c) fp.readlines()
(d) All of the above
14. The number of characters read by the statement fp.readline(20) from the file
handle fp is
(a) 20
(b) 19
(c) 21
(d) It depends on the current position of the file location pointer.
15. The statement fp.readlines(20) reads
(a) minimum 20 bytes
(b) maximum 20 bytes
(c) exactly 20 bytes
(d) none of the above
16. Which of the following method can be used to write a list of strings in a file?
(a) writelines()
(b) write()
(c) writelist()
(d) None of the above
17. Which of the following method can be used to write a list of numbers in a file?
(a) writelines()
(b) write()
(c) writelist()
(d) None of the above
18. Which of the following method can be used to get the current location of the file
pointer?
(a) tell()
(b) get()
(c) find()
(d) None of the above
19. Which of the following method can be used to change the current location of the
file pointer?
507
(a) set()
(b) seek()
(c) change()
(d) None of the above
20. The statement fp.seek() with a read and write file object fp will position the file
pointer to
(a) the start of the file
(b) the end of the file
(c) at its current location
(d) it is an error
21. The binary file mode is typically used for large datasets due to
(a) it requires less disk space than a corresponding text file
(b) it is more efficient than a corresponding text file
(c) Both a and b
(d) None of the above.
22. Which of the following modes permits both read and write in the binary format
in a file?
a) 'wb+'
b) 'w'
c) 'wb'
d) 'w+'
23. Which of the following modes does not permit writing in a file?
a) 'r+'
b) 'w'
c) 'x'
d) None of the above
24. What is the type of the returned object of the readlines() method?
(a) string
(b) a list of strings
(c) a tuple of strings
(d) None of the above
25. Which of the following is true for ‘r+’ file mode?
(a) It will return an error if the file does not exist
(b) It will permit both reading and writing
(c) It will permit relocation of the file pointer
508
(d) All of the above
Review Questions
510
students with more that a given percentage, and search a student by admission
number.
17. Create an employee database using a json file to store employee records given as
a list of dictionary objects with keys: empcode, name, and salary. Your program
should be able to perform: (1) add a new record at the end of the file and (2)
display all employee records whose salary is more than a given value.
511
512
Chapter 12
Learning Outcomes
Software development is a dynamic and complex process as it has to meet the dynamic
needs of users to solve real-life complex problems. Further, as the size of a program
increases, it becomes difficult to debug, maintain and reuse it economically and effectively
using the traditional procedural programming strategies. These are the basic motivation
behind the development of the object-oriented programming (OOP) strategy, which aims
to implement real-world complex problem-solving strategies like inheritance, hiding,
polymorphism, etc. in computer programming. The main aim of OOP is to use
encapsulation, inheritance, and polymorphism to bind together the data and the functions
to avoid inadvertent modification of data and to promote the scalability and reusability of
the existing code. It was rightly said by Alan Kay, one of the promoters of OOP, that as the
complexity and size of a program increase, the architecture dominates the logic of the
program. OOP is a code management system that reduces the inadvertent modification of
variables and promotes the reusability of codes.
Python supports object oriented programming concepts from its inception in an easy-
to-implement manner. For easy comprehension, we will briefly introduce the basic concepts
of OOP before using it in Python.
513
12.1 Basic Concepts of Object Oriented Programming
The object oriented programming concepts revolves around the following concepts:
objects, classes, encapsulation, inheritance, polymorphism, dynamic binding, and message
passing.
If we look around, we will find that any ecosystem consists of a variety of objects.
These self-contained objects maintain their internal states and interact with each other
through well-defined interfaces for the proper functioning of the ecosystem as a whole.
Consider a banking system, it consists of customers, managers, cashiers, clerks, databases,
etc. Every entity in this ecosystem has well-defined roles and limited access to the resources
of the ecosystem. For example, a customer can view his records but cannot modify them,
whereas a manager can view records and can modify them also. In OOPs, we divide
complex software task into small self-contained subcomponents called classes and develop
well-defined interfaces through which these classes interact with each other to perform the
intended tasks.
A class is a data structure to map a real-life object along with methods to manipulate
its data and interact with other objects. A class is called abstract data as it only uses the
essential features of a real-life object which is necessary for the proper function of the
software. Figure 12.1 shows a schematic representation of a class. It is important to note that
a class is just a blueprint but objects are actual data in the memory. For each instance, a
separate memory for the data is used, whereas the same copy of the methods is used for all
the instances.
514
Class: Customer Object: Customer
Variables: Data:
Name Name: John
Account_Number Account_Number: 123456
Account_Type Account_Type: Saving
Balance Balance: 10000
Methods: Methods:
Show_details () Show_details ()
Deposit () Deposit ()
Withdraw() Withdraw ()
Data encapsulation, also called data hiding, is one of the most striking features of
OOP, which wraps the data and methods of a class as a single unit. It means, private data
of a class can only be directly accessed by the methods of its class. Any method outside the
class cannot modify the private data directly. This removes the chance of inadvertent
modification of the data of a class as this will be easily caught by the compiler/interpreter.
However, for the convenience of programming, sometimes, we make some variables public,
which can be directly accessed by codes outside the class, but it is not recommended.
12.1.3 Inheritance
Inheritance is the process of creating another class by using other existing classes.
The existing classes are called base classes (or parent class or super class) and the new class
is called a child class (or derived class or subclass). By inheritance, a child class acquires the
data and methods of the base classes. Additional variables and methods can be added to a
child class to increase its functionality. Inheritance is the primary mechanism of OOP to
promote the reusability of existing codes. Through inheritance, we create more specific
objects from generic objects. For example, let us consider a generic class employee which
defines the basic features such as name, age, address, phone number, etc. We can use this
class to create two derived classes: programmer and manager. When we extend the
515
employee class to define the programmer class, we only need to add variables and methods
that are specific to the programmer class, such as programming languages. Similarly, when
we create the manager class from the employee class, we need to add specific variables and
methods to the new class such a team size, etc. The generic features such as name, age, etc.
will be inherited from the base class. This way, we can reuse the codes of the base class to
manipulate the generic features of the derived classes. Figure 12.2 shows the above
concepts.
Based on the number of base classes, child classes, and level of derivation, the types
of inheritance can be: single, multiple, hierarchical, multilevel, and hybrid. The types are
shown in figure 12.3.
Single Inheritance: In single inheritance, there is one parent class and one child class
(Figure 12.3(a)).
Multiple Inheritance: In multiple inheritance, there is more than one parent class for a
derived class. In this, the features of all the parent classes are inherited into the child class
(Figure 12.3(b)).
Multilevel Inheritance: In multilevel inheritance, we inherit a child from a parent class (call
grandparent) and the child class is further used as a parent for another child class. The
features of the grandparent class are inherited to the parent class and then all the features
of the parent class are inherited to the child class (Figure 12.3(d)).
Hybrid Inheritance: In hybrid inheritance, more than one inheritance type of the above is
used to create a new class (Figure 12.3(e)).
516
Class: Employee
Variables:
Name
Address
Methods:
Set_name ()
Set_address()
Base Class
Variables: Variables:
Languages Team_size
Methods: Methods:
Set_languages () Set_team_size ()
517
A A
A A B A
B
B C
B C B C D C
D
12.1.4 Polymorphism
518
Shape
Draw ()
Dynamic binding, also known as late binding, refers to the linking of a procedure at
the run time. In this, it is not known which functions with the same name will be called
before run-time. Method Overriding is an example of dynamic binding as in this case which
method to call is decided only after determining the underline object. In figure 12.4, the
Draw () method is defined in the base class as well as in all the derived classes. The derived
class Draw () method overrides the base class and implements different algorithms to draw
different shapes.
As we already stated, in OOP, the variables of a class are not directly accessible to
other classes or methods outside the class. To manipulate the variables of objects, objects
communicate with one another by sending and receiving messages to each other. A message
passed to an object is a request to execute one of its procedures to generate the desired
results. Message passing involves specifying the name of the object, the name of the
function, and the information to be sent.
519
12.2 Define a Class in Python
Python is an object oriented programming language and provides easy to use
mechanism to implements OOP concepts. In Python, every built-in data type, such as int,
str, bool, float, list, set, tuple, dict, etc. are built-in classes.
We can create a new class by using the keyword class. A class definition requires
the following three elements:
1. Class_name: Every class has a unique name, which is used to identify it and create
its instances (objects).
2. Attributes: It is a set of variables (data) used to maintain the states and properties of
its objects. Attributes can be defined at the class level or the object level.
• In the class level attribute, only one copy of a class attribute is created which
is shared among all the instances of the class. Any instance can access and
modify a class attribute.
• In the object level attribute, a separate memory is allocated to an object
attribute for each object. Changes made in an object attribute of an object do
not affect the same attribute of the other objects.
3. Methods: It is a set of functions used to control the behavior and response
(manipulation of its data) of its objects.
class Class_name:
attributes=values
Methods (self, [Parameters])
Except for the Class_name, all other components of a class are optional. For example,
the class definition is shown in example 12.2(a) is syntactically valid and we can create
objects from it, but the objects have no functionality.
520
An empty class is of no use. We can add some functionality to a class by adding
attributes and methods to it. Attributes are variables to hold the data of objects created from
the class. Methods are functions to manipulate attributes and interact with other objects. In
a method definition, the first parameter of the method is always a reference to the class
itself. Generally, the variable name self is used for this, however, any other variable name
can be used. During calls, this first parameter is omitted. It will be automatically given by
the Python interpreter. Example 12.2(b) creates a class with some attributes and methods.
#Class definition
class Rect: #Creating a class
length=0 #Creating an attribute
width=0
def area(self):
return self.length*self.width #Accessing attributes
#Main program
r1=Rect() #Creating an instance object of a class
Output
Area r1: 200
Area r2: 100
ID of Rect.length: 1621718231632
ID of r1.length: 1621718231632
ID of r2.length: 1621718231632
521
In the previous example above, the attributes are created at the class level, called
class attributes. Kindly note the IDs of the attributes. They are the same. Each object created
from this class will share the same memory for these attributes. Hence, we can have data of
the last object created from it and the previous data will be overwritten by the new object
data. However, we can create object attributes (also called instance attributes) by creating
attributes inside a method. Each object has separate memory for its object attributes. In a
class, we can have class-level attributes as well as object-level attributes.
Example 12.2(c) creates a class with both types of attributes. Note the IDs of various
attributes in the output. For the same object attribute, the IDs for different objects will be
different. However, for the same class attribute, the IDs will be the same for all the objects.
Example 12.2(c): Creating a class with class attributes and object attributes
class Rect:
count=0 #Creating a class attribute
def set_length(self, length):
self.length=length #Creating an object attribute
def set_width(self,width):
self.width=width #Creating an object attribute
def area(self):
Rect.count+=1 #Accessing a class attribute
return self.length*self.width
r1=Rect()
r1.set_length(10)
r1.set_width(20)
print("Area r1:",r1.area())
r2=Rect()
r2.set_length(100)
r2.set_width(200)
print("Area r2:",r2.area())
522
print("r1.width:", r1.width,", r2.width:", r2.width)
print("r1.count:",r1.count,", r1.count", r2.count, ", Rect.count:",
Rect.count)
Output
Area r1: 200
Area r2: 20000
Object attribute IDs: r1.length: 1853819087440 not equal to r2.length
1853819278800
Object attribute IDs:r1.width 1853819087760 not equal to r2.width
1853819282064
Class attribute IDs: r1.count 1853819087184 equal to r2.count
1853819087184
r1.length: 10 , r2.length 100
r1.width: 20 , r2.width: 200
r1.count: 2 , r1.count 2 , Rect.count: 2
Python allows using the same name to create a class attribute and an object attribute
in a class. In this situation, class attributes will be accessed by the syntax:
Class_name.class_attribute, whereas object attributes are accessed using the syntaxes:
self.object_attribute inside the class, where self is a reference of the class.
To reduce the confusion, it is recommended to avoid the use of the same name for a
class attribute and an instance attribute. Example 12.2(d) illustrates the above concepts.
Example 12.2(d): Creating a class with a class attribute and an object attributes with
the same name
class myClass:
class_attribute=0 #Creating a class attribute
def myMethod(self,p):
self.object_attribute=p #Creating an object attribute
myClass.class_attribute=p*2 #Updating a class attribute
523
#Creating an object attrinute with the same name as a class
attribute
self.class_attribute=p*3 #Be careful
object1=myClass()
object1.myMethod(10)
#Printing an object attribute
print("Object attribute:",object1.object_attribute)
#Printing an object attribute
print("Object attribute:",object1.class_attribute)
#Printing a class attribute
print("The original class attribute", myClass.class_attribute)
Output
Object attribute: 10
Object attribute: 30
The original class attribute 20
class Rect:
def __init__(self, a, b): #Defining the constructor
self.length=a #Creating object attributes
self.width=b #Creating object attributes
r2=Rect(10,10)
524
print("Area of r2:",r2.area())
Output
Area of r1: 200
Area of r2: 100
Constructors are of two types: default and parameterized constructors. The default
constructor is a constructor which has only one argument. This argument is a reference to
the instance being constructed. The parameterized constructor has more than one
argument. The first argument is again a reference to the instance being constructed and
other arguments are the values for the various attributes of the class. Python does not
support multiple constructors. If we write more than one __init__ () method in a class, the
last method will overwrite all the previous ones. However, we can achieve multiple
constructors by using the variable-length argument facility of Python. Example 12.3(b)
illustrates how to achieve multiple constructors based on the number of arguments. Note
the use of a variable-length argument to process different forms of constructors. Example
12.3(c) shows how to implement multiple constructors based on the type of arguments.
class Shape:
def __init__(self,*args): #Defining the constructor
if len(args)==1: #Processing constructor with one argument
self.type=1
self.length=args[0]
elif len(args)==2: #Processing constructor with two arguments
self.type=2
self.length=args[0]
self.width=args[1]
else: #Processing constructor with no argument
self.type=3
def area(self):
if self.type==1:
return " square:" + str(self.length*self.length)
elif self.type==2:
return " rectangle:"+ str(self.length * self.width)
else:
return "Invalid shape"
525
s2=Shape(10) #Calling the constructor with one argument
print("Area of the",s2.area())
s3=Shape() #Calling the constructor with no argument
print(s3.area())
Output
Area of the rectangle:200
Area of the square:100
Invalid shape
class myAdd:
# constructor overloading based on argument types
def __init__(self, arg1,arg2):
Output
30
10ABC
ABC30
526
destroys the object and releases the memory. This is called automatic garbage collection.
However, before destroying an object, Python calls a special function of the object, known
as the destructor. The __del__ () is reserved to name the destructor method of a class. Similar
to the constructor, the destructor is inherited to all the created classes from the object class.
Normally, no action is required from us to destroy an object, but if we want to perform some
operations before Python kills an object, we should write that code inside the destructor
method. Following is the syntax of the destructor of a class:
class class_name:
Attributes
Methods (…)
def __del__(self):
Statements
Example 12.3(d) uses the destructor of a class to print a message. Python does not
call the destructor till the last alias of an object is deleted or goes out of scope. Example
12.3(e) illustrates this, where three aliases of an object are created. The destructor is called
when we delete the last alias.
class myClass:
count=0
def __init__(self): #Defining the constructor
myClass.count+=1
self.instance_number=myClass.count
print('Creating the instance number:',self.instance_number )
def myFun():
#This instance will be deleted once we return from the function
obj1 = myClass()
obj2=myClass()
myFun()
del obj2 #Explicitly deleting an instance
Output
Creating the instance number: 1
Creating the instance number: 2
Destroying the instance number: 2
527
Destroying the instance number: 1
class myClass:
def __init__(self): #Defining the constructor
print('An instance created')
Output
An instance created
Destroying the instance
Public member: A public member of a class is like a global variable and is accessible in any
part of the program, i.e. there is no restriction on its the access either inside or outside the
class. In Python, by default, all data members and member functions are public. The public
members can be accessed by using the dot notation, such as class_object.public_member, in
any part of the program.
Protected member: A protected member of a class is accessible to the other members of the
class as well as members of derived classes from the class. Protected members are primarily
used to enable specific resources of the parent class to be inherited by the child class. Be
528
careful about a protected member, as the dot notation can be used to access the member
even outside the class.
Private member: A private member of a class is accessible within the class only. No other
part of the program can access a private member, including the members of derived classes.
A private member is the most secure member of a class and is completely encapsulated
inside the class. We cannot use the dot notation to access a private member outside the class.
Any attempt to do so will raise an error.
529
Single trailing underscore A single trailing underscore is primarily used to use
keywords as variable names, when it seems this variable
Example: var_ name is the most suitable. For example, class_, int_ list_,
etc. This is just a convention and Python enterpriser does
not give any special meaning to the training single
underscore.
Double leading underscore A double underscore before a member of a class makes the
member private. This means the member cannot be
Example: __var accessed outside the class, using the simple dot notation.
Further, a double underscore forces the Python interpreter
to rewrite the member name using the name mangling.
Double leading and trailing A double leading and trailing underscores in an attribute
underscore or method name indicate that it is a special method or
attribute defined by the Python language. These naming
Example: __var__ patterns should be avoided by programmers. Attributes
and methods with these naming patterns are accessible
outside the class, i.e. they are not private to the class.
>>> x,y,_,_=myFun(10,20)
>>> print(x,y)
30 200
530
Example 12.4 illustrates private, protected, and public members of a class. We will
further illustrate protected members after discussing derived classes later in the chapter.
class Student:
def show(self):
print("Student name:", self.name) #Accessing a public member
print("Student age:",self._age) #Accessing a protected member
print("Student grade:" ,self.__grade) #Accessing a private
member
return None
s1=Student("John",18,8.5)
s1.show()
print("Student name:",s1.name) #Accessing a public member
print("Student age:",s1._age) #Accessing a protected member
print("Student grade:", s1.__grade) #Error: Accessing a private member
Output
Student name: John
Student age: 18
Student grade: 8.5
Student name: John
Student age: 18
Traceback (most recent call last):
File "D:\akv\akv\Python_book\Chapter 12\test1.py", line 19, in <module>
print("Student grade:", s1.__grade) #Error: Accessing a private member
AttributeError: 'Student' object has no attribute '__grade'
class myClass:
def instance_method1(self): #Defining a public instance method
print("Hello, I am a public instance method with no parameter")
Output
Hello, I am a public instance method with no parameter
Hello, I am a public instance method with a parameter
Value of the parameter: 10
Hello, I am a public instance method with no parameter
Hello, I am a private instance method
Value of the parameter: 20
Hello, I am a local method
532
12.6 Name Mangling
The name mangling is a mechanism used by Python to rename a member of a class
with a double underscore prefix to avoid naming conflicts in inherited classes. In this, an
identifier name with two leading underscores is renamed as _classname__identifier, where
classname is the name of the class where the identifier is defined. For example, an attribute
name __abc in a class xyz will be renamed as _xyz__abc.
As we discussed earlier, private members of a class are not accessible outside the
class. However, since Python renames all the private members using the name mangling,
we can use the new name of a private member to access it outside the class. In this, we use
the syntax object._classname__private_member to access a private member. Here, an
object is an instance of the class, classname is the name of the class and __private_member
is a private member of the class. We use an underscore before the name of the class and
then attach the private member with it to create its name mangling. Example 12.6 illustrates
the name mangling to access a private member. However, this is against the basic tenets of
OOP and is strongly discouraged.
class myClass:
__Private_data=10 #Creating a private data
Public_data=20 #Creating a public data
533
12.7 Display Class Attributes and Instance Methods
We can list all the attributes and methods of a class by using the dir () built-in
function. The dir () method accepts either the name of the class or an instance of the class.
Example 12.7(a) uses the dir () method to list all the attributes and methods of a class. Notice
the first entry in the output, which is the new name of the private attribute __count,
generated by the name mangling. As can also be seen from the output, the dir () method
does not list instance attributes. It only lists class attributes and instance methods.
We can also list symbol tables of a class and its instances by using a special attribute
__dict__ of the class or an instance, respectively. It uses the syntaxes: class_name.__dict__
(to list the class attributes and instance methods) or object.__dict__ (to list the object
attributes). Example 12.7(b) illustrates the above.
class Rect:
__count=0 #Creating a private class attribute
def set_length(self, length):
self.length=length #Creating an object attribute
def set_width(self,width):
self.width=width #Creating an object attribute
def area(self):
Rect.count+=1 #Accesssing a class attribute
return self.length*self.width
print(dir(Rect)) #List class attributes and methods using class
r1=Rect()
print("\n")
print(dir(r1)) #List class attributes and methods using instance
Output
['_Rect__count', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'area', 'set_length', 'set_width']
534
['_Rect__count', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'area', 'set_length', 'set_width']
class Rect:
count=0 #Creating a class attribute
def set_length(self, length):
self.length=length #Creating an object attribute
def set_width(self,width):
self.width=width #Creating an object attribute
def area(self):
Rect.count+=1 #Accesssing a class attribute
return self.length*self.width
Output
Class symbol table:
{'__module__': '__main__', 'count': 0, 'set_length': <function Rect.set_length at
0x0000021477F58550>, 'set_width': <function Rect.set_width at 0x0000021477F585E0>,
'area': <function Rect.area at 0x0000021477F58670>, '__dict__': <attribute '__dict__' of
'Rect' objects>, '__weakref__': <attribute '__weakref__' of 'Rect' objects>, '__doc__':
None}
535
12.8 Inheritance in Python
As discussed earlier in this chapter, inheritance is the primary mechanism to reuse
a class and extend or override its functionalities. Following is the syntax of inheritance in
Python:
class child_class(parent_class1, parent_class2,…, parent_classN):
child_attributes
child_methods
As can be seen from the syntax, many parent classes can be used to create a child class.
Parent classes are given in parenthesis.
Output
Hello, I am in the parent class
Hello, I am in the child class
Example 12.8(b) shows the behavior of public, protected and private attributes in a
derived class. It can be seen from the output that public and protected attributes of the
parent class are inherited in the derived class but private attributes of the parent class are
not inherited.
536
Example 12.8(b): Behavior of various types of attributes in inheritance
Output
Hello, I am in the parent class
Hello, I am in the child class
10
20
40
50
Traceback (most recent call last):
File "D:/akv/akv/Python_book/Chapter 12/test3.py", line 22, in <module>
print(ob.__privateClassVar)
AttributeError: 'Child' object has no attribute '__privateClassVar'
The method/attribute overriding: If we redefine a method in a derived class that has the
same name as that of a base class method, the derived class method will override the
537
inherited base class method. The same is true for an attribute. Example 12.8(c) illustrates
the above.
The super () method: The overridden methods and attributes of the parent class can be
accessed in the derived class by using the super () built-in method. For this we use the
syntaxes super().method_name() and super().attribute_name. The non-overridden
inherited members of the parent class can be used using the simple dot notation, such as
self.parent_member, where self is a reference to the current class. See example 12.8(d).
Example 12.8(d): Using parent class methods and attributes in a derived class
538
class Parent():#Parent Class
var1=10
var2=20
def parentMethod(self): #Parent method
print('Hello, I am in the parent class')
def fun(self):
print("I am defined in the parent class")
Output
Hello, I am in the parent class
Hello, I am in the child class
I am defined in the child class
I am defined in the parent class
Hello, I am in the parent class
Using the base class attributes: 10
Using a local attribute: 20
30
20
539
12.9 Types of Inheritance in Python
Python supports all the five types of inheritance which are discussed in section
12.1.3. In this section, we will illustrate each type of inheritance with examples.
In the single inheritance, there is only one parent class and one derived child class.
Example 12.9(a) illustrates the single inheritance.
Output
This function is defined in the parent class
This function is defined in the child class
10
20
In the multiple inheritance, there is more than one parent class and one derived child
class. Example 12.9(b) illustrates the multiple inheritance. If the two or more parents have
the member with the same name, the member in the first parent will be inherited to the
child class, others will be ignored.
540
class Parent2: #Defining another parent class
var2=20
def func2(self):
print("This function is defined in Parent2")
In multi-level inheritance, a child class is derived from another derived class. This is
similar to a grandparent–parent-child relationship. Example 12.9(c) illustrates the multi-
level inheritance.
Output
Level 0: This function is defined in Grandparent
Level 1: This function is defined in Parent
Level 2: This function is defined in Child
10
20
In the hierarchical inheritance, more than one child class is derived from a parent
class. Example 12.9(d) illustrates the hierarchical inheritance.
542
Example 12.9(e): Hybrid inheritance
Output
This function is defined in Parent
This function is defined in Child
This function is defined in Child1
This function is defined in Hybrid
543
Table 12.2: Class definitions
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__',
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'process']
544
hierarchy of classes. Following are the rules, to be used in the given sequence, to create
MRO:
a. A method/attribute is first searched in the current class. This means a
method/attribute in the current class overrides all the inherited methods/attributes
with the same name. The mro () method or __mro__ attribute can be used to obtain
the MRO of a derived class. Example 12.11(a) illustrates the above.
b. In the case of multiple inheritance, if a method/attribute is not found in the current
class, it is searched in the tuple of parent classes in depth-first, left-right fashion,
without searching the same class twice. It means the left-most parent and all its
super classes are searched first. If still not found, the second parent and all its super
classes are searched next, and so on. Example 12.11(b) illustrates this. Here, class C
has two base classes (A, B) and both have defined a function with the same name.
But class C inherits the function from class A, as it is the first class in the tuple of
base classes. However, since attribute var is defined only in class B, it is inherited
from class B.
During this process, the good head rule and the inheritance rule must be
followed strictly. The good head rule says that a class must appear before its parents
in MRO, whereas the inheritance rule says that a more specific class should come
before a generic class. If there is a violation of the good head rule, Python removes
the violating class from MRO. After removal, if the MRO follows the above two
rules, Python uses that to inherit methods and attributes (see example 12.11(c)), else
it raises the inconsistent MRO error (see Example 12.11(d)).
Example 12.11(c) shows a valid MRO after applying the good head rule and
the inheritance rule. The MRO of D without the good head and inheritance rules is
D->B->A->C->A->object. But after applying the good head rule, the MRO is
D->B->C->A->object. The first A is removed as it violates the good head rule. The
new MRO also fulfills the inheritance rule; hence it is consistent.
Example 12.11(d) shows an example of inheritance that violates the
inheritance rule. In this example, the MRO derived after applying the good head
rule is C->B->A->object, but A is also a direct super class of C. So if a method is in
both A and B classes then which version should class C call? According to the new
MRO, the version in B is called first ahead of A and that is not according to
inheritance rules (specific to generic) resulting in Python to throw the inconsistent
MRO error.
The most generic class in Python is the object class, from which every Python
class is derived. Hence, it will always be the last class in MRO. If a method/attribute
is not found in the complete search path, the undefined method/attribute error will
be raised.
545
Example 12.11(a): The MRO of a class
class B:
var=20 #Defining an attribute
def myFun(self): Defining a method
print('myFun defined in B')
Output
myFun defined in A
20
546
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,
<class 'object'>]
Example 12.11(c): The MRO of a class after applying the good head rule
obj = D()
obj.myFun()
print(D.mro())
Output
myFun defined in C
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>,
<class '__main__.A'>, <class 'object'>]
#The MRO of C without the good head and the inheritance rules.
#C->A->B->A->object
#The MRO after the good head rule. The first A is removed as it
violates the good head rule.
#C->B->A->object
#The above MRO is inconsistent as it violates the inheritance rule as A
#and B are the direct parents of C and A is also a direct parent of B.
#This type of ambiguous inheritance is not supported in Python.
class A:
547
def myFun(self):
print('myFun defined in A')
class B(A):
def myFun(self):
print('myFun defined in B')
obj = C()
obj.myFun()
Output
Traceback (most recent call last):
File "D:/akv/akv/Python_book/Chapter 12/test3.py", line 16, in
<module>
class C(A, B):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases A, B
Python supports multiple and multilevel inheritances. Due to this, an object inherits
behaviors (methods and attributes) from many super classes (parents and grandparents).
We can use the built-in function isinstance (object_name, (class1, class2..., classN)) to test
the class membership of an object to a set of classes. The method returns true if the object is
an instance of any one of the specified tuple of classes or their supper classes. Similarly, we
can test whether a given class is a subclass of any of the specified tuple of classes or their
super classes) by using the built-in method, issubclass (class_name, (class1, class2...,
classN)). Here, the first parameter must be the name of a class. Example 12.12 illustrates
some usages of the above-discussed methods.
548
Example 12.12: Type and Class Membership Tests
class Vehicles:
# Constructor
def __init__(vehicleType):
print('Vehicle is a ', vehicleType)
obj=Car()
print("Type of obj is", type(obj))
print("Is obj an instance of Car:", isinstance(obj, Car))
print("Is obj an instance of Vehicles:", isinstance(obj, Vehicles))
print("Is obj an instance of the object class:", isinstance(obj,
object))
print("Is obj an instance of the list class:", isinstance(obj, list))
print("Is obj an instance of Car or list:", isinstance(obj,(Car,
list)))
Output
Vehicle is a Car
Type of obj is <class '__main__.Car'>
Is obj an instance of Car: True
Is obj an instance of Vehicles: True
Is obj an instance of the object class: True
Is obj an instance of the list class: False
Is obj an instance of Car or list: True
Is Car a subclass of Vehicles: True
Is Car a subclass of Car: True
Is Car a subclass of list: False
Is Car a subclass of Vehicles or list: True
549
12.13 Polymorphism in Python
Polymorphism is one of the core concepts of OOP. In this, the same name or the
same symbol is used to execute a different set of codes based on the types of arguments
and/or the number of arguments. The word polymorphism means poly (many) and
morphism (forms), i.e. the same thing that has different functions in different situations.
In Python, polymorphism can be achieved by the following ways:
• method overloading
• method overriding, and
• operator overloading
class Shape:
#Overloaded method based on the number of arguments
def area(self,*arg):
n=len(arg)
if n <1 and n > 2:
print("Undefined shape")
return
if n==1:
print("Area of the circle is:", 3.14*arg[0]*arg[0])
return
if n==2:
print("Area of the Rectangle is:", arg[0]*arg[1])
return
S1=Shape()
S1.area(1) #Call of an overloaded method
S1.area(1,2) #Call of an overloaded method
Output
550
Area of the circle is: 3.14
Area of the Rectangle is: 2
class myClass:
#Overloaded method based on the number of arguments
def add(self,arg1,arg2):
if isinstance(arg1,str) and isinstance(arg2,str):
print("Concatenated string:",arg1+arg2)
elif isinstance(arg1,float) and isinstance(arg2,float):
print("Sum of numbers is:",arg1+arg2)
elif isinstance(arg1,str) and (isinstance(arg2,float) \
or isinstance(arg2, int)):
print("Concatenation of str and float is:",arg1+str(arg2))
elif (isinstance(arg1,int) or isinstance(arg1,float)) \
and isinstance(arg2,str):
print("Concatenation of float and str is:", str(arg1)+arg2)
else:
print("Unrecognised data types")
return
S1=myClass()
S1.add(1.5,3.2) #Call of an overloaded method
S1.add("Abc",2) #Call of an overloaded method
S1.add("Abc","Xyz") #Call of an overloaded method
S1.add(2, "Abc") #Call of an overloaded method
Output
Sum of numbers is: 4.7
Concatenation of str and float is: Abc2
Concatenated string: AbcXyz
Concatenation of float and str is: 2Abc
#Main program
S1=myClass()
S1.add(1.5,3.2) #Call of an overloaded method
S1.add("Abc",2.2) #Call of an overloaded method
S1.add("Abc","Xyz") #Call of an overloaded method
S1.add(2, "Abc") #Call of an overloaded method
S1.add("Python")
Output
Sum of numbers is: 4.7
Concatenation of str and float is: Abc2.2
Concatenated string: AbcXyz
Concatenation of float and str is: 2Abc
Reverse the string: nohtyP
552
operation when its operands are strings. It is a polymorphism in which an operator achieves
customized behavior depending on the type of operands. The feature in Python that allows
the same operator to have a different meaning according to the context is called operator
overloading.
When we try to use an operator with a user-defined class without defining the
operator overloading, we will get an error. Example 12.15(a) illustrates this point, where a
user-defined class vector tries to use the + operator. The error is raised as the + operator
does not know what to do with the Vector operands. However, we can define an overloaded
method to perform the desired operation for vector operands. In Python, operator
overloading is achieved by writing a special function corresponding to the operator in the
user-defined class. For example, to overload the + operator for the Vector class, we include
the special function __add__ () in the Vector class. Python internally maps this method to
the + operator. Similarly, we can overload the – operator for the Vector class by including
the special function __sub__ () in the class. Example 12.15(b) illustrates the overloading of
the addition and subtraction operators for the Vector class. Similarly, we can overload any
Python operator by including the corresponding special function in the class definition.
Table 12.2 lists commonly used operators and their corresponding special functions.
#Main program
p1 = Vector(1, 2)
p2 = Vector(2, 3)
print(p1+p2) #Trying to perform addition of two vectors
Output
Traceback (most recent call last):
File "D:\akv\akv\Python_book\Chapter 12\test3.py", line 9, in
<module>
print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'
553
Example 12.15(b): Operator overloading
554
Bitwise OR ( | ) p1 | p2 p1.__or__( self, p2)
Bitwise XOR ( ^ ) p1 ^ p2 p1.__xor__( self, p2)
Bitwise NOT ( ~ ) ~p1 p1.__invert__( self)
Less than ( < ) p1 < p2 p1.__lt__( self, p2)
Less than or equal to ( <= ) p1 <= p2 p1.__le__( self, p2)
Equal to ( == ) p1 == p2 p1.__eq__( self, p2)
Not equal to ( != ) p1 != p2 p1.__ne__( self, p2)
Greater than ( > ) p1 > p2 p1.__gt__( self, p2)
Greater than or equal to ( >= ) p1 >= p2 p1.__ge__( self, p2)
Unary negation ( – ) -p1 p1.__neg__(self)
Unary plus ( + ) +p1 p1.__pos__(self)
Subtract and assign ( -= ) p1-=p2 p1.__isub__(self, p2)
Add and assign (+= ) p1+=p2 p1.__iadd__(self, p2)
Multiply and assign ( *= ) p1*=p2 p1.__imul__(self, p2)
Divide and assign (/= ) p1/=p2 p1.__idiv__(self, p2)
Floor divide and assign ( //=) p1//=p2 p1.__ifloordiv__(self, p2)
Modulo and assign ( %= ) p1%=p2 p1.__imod__(self, p2)
Power and assign ( **= ) p1**=p2 p1.__ipow__(self, p2)
Right shift and assign ( >>= ) p1>>=p2 p1.__irshift__(self, p2)
Left shift and assign ( <<= ) p1<<=p2 p1.__ilshift__(self, p2)
Bitwise AND and assign ( &= ) p1&=p2 p1.__iand__(self, p2)
Bitwise OR and assign ( |= ) p1|=p2 p1.__ior__(self, p2)
Bitwise XOR and assign (^= ) p1^=p2 p1.__ixor__(self, p2)
When we print an object of a user-defined class, the print () function displays the
memory reference location of the object, such as the statement print(v3) will print
<__main__.Vector object at 0x000002039734E730> on the console. However, to print the
content of the object, we can overload the special function __str__ () method, which is
internally used by the print method to print the content of an object. The __str__ () method
overloads the str () as well as the format () built-in function for the class. Example 12.15(c)
illustrates this.
555
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __add__(self, v1): #Overloading the + operator
v2=Vector(0,0)
v2.x=self.x+v1.x
v2.y=self.y+v1.y
return v2
def __sub__(self, v1): #Overloading the - operator
v2=Vector(0,0)
v2.x=self.x-v1.x
v2.y=self.y-v1.y
return v2
#The __str__ method converts the content of the object into a string
def __str__(self): #The method to be called by the print function
return "Vector({0},{1})".format(self.x, self.y)
#Main program
v1 = Vector(1, 2)
v2 = Vector(2, 3)
v3=v1+v2 #Using the overloaded + operator
print("v1+v2 =",v3)
v3=v1-v2 #Using the overloaded - operator
print("v1-v2 =",v3)
s1=str(v1) #The overloaded str method
s2=format(v2) #The overloaded format method
print(s1)
print(s2)
Output
v1+v2 = Vector(3,5)
v1-v2 = Vector(-1,-1)
Vector(1,2)
Vector(2,3)
We can not only overload arithmetic operators but we can overload every type of
operator, such as comparator operators, bitwise operators, etc. Example 12.15(d) illustrates
the overloading of the less than (<) operator.
#Main program
v1 = Vector(1, 2)
v2 = Vector(2, 3)
print(v1<v2)
v1 = Vector(5, 2)
v2 = Vector(2, 3)
print(v1<v2)
Output
True
False
557
Example 12.16: Overloading built-in methods
#Main program
v1 = Vector(3, 4)
#Using the abs () method for the Vector class
print("The absolute value of the vector is:", abs(v1))
Output
The absolute value of the vector is: 5.0
class MyDecorator:
def __init__(self, function):
self.function = function
def __call__(self):
# Additional code before the function call
print("Decorated: Welcome")
self.function()
# Additional code after the function call
print("Decorated: Good bye")
558
function() #Calling the decorated function
Output
Decorated: Welcome
Original: Hello world
Decorated: Good bye
Example 12.17(b): A decorator class for a function with arguments and return values
import math
class myDecorator:
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
if args[0]<0:
return "Error: No square root of a negative number"
result = self.function(*args, **kwargs)
return result
Output
Square of 25 is 5.0
Square of -25 is Error: No square root of a negative number
Solved Examples
Sample Program 12.1: Define a bank account class that holds the following information :
Customer Name, Account Number, Account Type and current balance and performs the
following functions: make a deposit, make a withdrawal and the details of the account.
Solution Steps:
class Account: #Create a Account class
#Define constructor
def __init__(self, name, acc_num, acc_type, balance=0):
559
self.name = name
self.acc_num=acc_num
self.acc_type=acc_type
self.balance = balance
# Main program
name = input("Enter name of the account holder:")
acc_num=input("Enter account number:")
acc_type=input("Enter account type(SB/Current)")
amt =float(input("Enter initial amount:"))
A = Account(name, acc_num, acc_type, amt)
Output
Enter name of the account holder:Arvind
Enter account number:SBI001
Enter account type(SB/Current)SB
560
Enter initial amount:2000
Main menu
1. Show details
2. Deposit
3. Withdrawl
4. exit
Enter your choice2
Enter amount to deposit:1500
Main menu
1. Show details
2. Deposit
3. Withdrawl
4. exit
Enter your choice3
Enter amount to withdraw:1000
Main menu
1. Show details
2. Deposit
3. Withdrawl
4. exit
Enter your choice1
Arvind SBI001 SB 2500.0
Main menu
1. Show details
2. Deposit
3. Withdrawl
4. exit
Enter your choice4
>>>
Sample Program 12.2: Create a Polar class that stores a polar coordinate (radius and
angle) and overloads the + operator.
Solution Steps:
561
import math
class Polar: #Create a class to hold and process polar points
#Define constructor
def __init__(self, radius, angle):
self.radius = radius
self.angle=math.radians(angle)#Store angle in radians
print(f"Radius:{self.radius:8.3f},\tAngle={math.degrees(self.angle):8.3
f}")
def __add__(self, p): #Overload the + operator
#Convert polar coordinates to cartesian coordinates
x1=self.radius * math.cos(self.angle)
y1=self.radius * math.sin(self.angle)
x2=p.radius * math.cos(p.angle)
y2=p.radius * math.sin(p.angle)
#Add cartesian coordinates
x=x1+x2
y=y1+y2
#Convert a cartesian coordinate to a polar coordinate
angle= math.atan(y/x) if x != 0 else 0
radius= math.sqrt(x*x+y*y)
p1=Polar(radius,math.degrees(angle))
return p1
# Main program
p1=Polar(4,0) #The first polar point
p2=Polar(3,90) #The second polar point
p3=p1+p2 #Add two polar points
print("P1=", end=" ")
p1.show()
print("P2=", end=" ")
p2.show()
print("P3=", end=" ")
p3.show()
Output
P1= Radius: 4.000, Angle= 0.000
P2= Radius: 3.000, Angle= 90.000
P3= Radius: 5.000, Angle= 36.870
562
Sample Program 12.3: Write a program to implement the following classes.
Staff
Code
Name
Show()
Teacher Officer
Subject Grade
Publications
Show()
Show()
Solution Steps:
1. Create the Staff class
2. Derive the Teacher class from the Staff class
3. Derive the Officer class from the Staff class
class Staff: #Define a class
def __init__(self, code, name):
self.code=code
self.name=name
def show(self):
print("Code:",self.code, "\nName:", self.name)
563
self.grade=grade
def show(self):
super().show()
print("Grade:", self.grade)
#Main program
teacher= Teacher(100, "John", "English",10)
teacher.show()
officer=Officer(200, "Joe",4)
officer.show()
Output
Code: 100
Name: John
Subject: English
Publication 10
Code: 200
Name: Joe
Grade: 4
Sample Program 12.4: Create two classes CM and INCH which stores distances in cm
and inch, respectively. Overload the + operator to add the objects of these classes.
Solution Steps:
class CM: #Create CM class
def __init__(self,dist): #Constructor
self.dist=dist
self.unit="cm"
class INCH:
def __init__(self,dist): #Constructor
564
self.dist=dist
self.unit="inch"
Sample Program 12.5: Create a class to hold data of a matrix and overload the matrix
addition operation.
Solution Steps:
class MAT:
def __init__(self, matrix):
self.matrix=matrix
for i in range(n1):
m1=len(mat.matrix[i])
565
m2=len(self.matrix[i])
if m1 == m2 and m1 == m : # Check equality of columns
row=[]
for j in range(m):
row.append(mat.matrix[i][j]+ self.matrix[i][j])
result.append(row)
else:
result ="Invalid dimensions for addition"
break
else:
result ="Invalid dimensions for addition"
return result
#Main program
M1=MAT([[1,2,3],[4,5,6],[7,8,9]])
M2=MAT([[1,2,3],[4,5,6],[7,8,9]])
M3= M1+M2
print(M3, type(M3))
M1=MAT([[1,2,3],[4,5],[7,8,9]])
M2=MAT([[1,2,3],[4,5],[7,8,9]])
M3= M1+M2
print(M3, type(M3))
M1=MAT([[1,2,3],[4,5],[7,8,9]])
M2=MAT([[1,2,3],[4,5,6],[7,8,9]])
M3= M1+M2
print(M3, type(M3))
Output
[[2, 4, 6], [8, 10, 12], [14, 16, 18]] <class 'list'>
Invalid dimensions for addition <class 'str'>
Invalid dimensions for addition <class 'str'>
Chapter Summary
566
3. A class is a data structure to map a real-life object and methods to manipulate its
data and interact with other objects. A class is a blueprint, but an object is an
instance of a class that actually holds data in the memory.
4. Data encapsulation, also called data hiding, wraps a class's data and methods as
a single unit and. It means only its class methods can directly access the private
data of a class. Any method outside the class cannot modify the private data
directly. The encapsulation removes the chances of inadvertent modification of
the data of a class as this will be easily caught by the compiler/interpreter.
5. Inheritance is the process of creating a class by using other existing classes. The
existing classes are called base classes (or parent class or superclass), and the new
class is called a child class (or derived class or subclass).
6. Polymorphism in OOP means using a function name or an operator to perform
different tasks depending on the context.
7. Dynamic binding, also known as late binding, refers to linking a procedure at
the run time.
8. Python is an object-oriented programming language and provides easy to use
mechanism to implements OOP concepts. In Python, built-in data types, such as
int, str, bool, float, list, set, tuple, dict, are built-in classes.
9. A constructor is a special method of a class that is automatically called when we
create an instance. The task of a constructor is to initialize the attributes of the
class whenever an instance is created.
10. When a variable (object) goes out of scope in a program, or we delete an object
with the del command, Python automatically destroys the object and releases
the memory. This process is called automatic garbage collection. However,
before killing an object, Python calls a special function known as the destructor.
11. The name mangling is a mechanism used by Python to rename a member of a
class with a double underscore prefix to avoid naming conflicts in inherited
classes.
12. If we redefine a method in a derived class that has the same name as that of a
base class method, the derived class method will override the inherited base
class method.
13. The overridden methods and attributes of the parent class can be accessed in the
derived class by using the super () built-in method.
567
14. In Python, every data is an object derived from a class, and every class in Python,
both built-in and user-defined, is derived from the object class.
15. In multiple inheritances, there may be many methods/attributes with the same
name in itself and various superclasses of a derived class. The method resolution
order (MRO) is the sequence of classes in which Python looks for a
method/attribute in a hierarchy of classes.
568
6. In inheritance
(a) the child class gets only the data members of the parent class
(b) the child class gets only the methods of the parent class
(c) the child class gets both the methods and data members of the parent class
(d) None of the above
7. Which of the following types of inheritance is not supported in Python?
(a) single inheritance
(b) multi-level inheritance
(c) hybrid inheritance
(d) None of the above
8. Which of the following is not an example of polymorphism?
(a) operator overloading
(b) method overloading
(c) inheritance
(d) none of the above
9. Which of the following is not a built-in class in Python?
(a) Boolean
(b) int
(c) NoneType
(d) complex
10. Which of the following keyword is used to define a class in Python?
(a) def
(b) class
(c) define
(d) None of the above
11. Which of the following is an essential component of a class definition?
(a) class name
(b) attributes
(c) methods
(d) all of the above
12. In a class method definition, the first parameter refers to
(a) The first argument passed during the call
(b) The object of the class itself
(c) It can be any object
(d) None of the above
569
13. Which of the following is true about a class attribute?
(a) The ID of the class attribute is the same in all the instances of the class
(b) Only one copy of the class attribute is created
(c) Any instance of the class can modify it
(d) All of the above
14. Which of the following is true about an instance attribute?
(a) The IDs of the instance attribute are different for the different objects
(b) Separate memory is allocated to the instance attribute for each object
(c) It is also called object attribute
(d) All of the above
15. Which of the following is not true in Python?
(a) We can use the same name to create a class attribute and an object attribute in
a class
(b) The ID of the class attribute is the same in all the instances of the class
(c) Separate memory is allocated to the instance attribute for each object
(d) None of the above
16. Which of the following is true about the constructor of a class?
(a) It is called automatically when we create an instance
(b) The name of the construction is the name of the class
(c) We can have more than one valid construction in a class
(d) All of the above
17. Which of the following is true about the constructor of a class?
(a) It is automatically called when we create an instance
(b) The name of the construction is always __init__().
(c) we can achieve multiple constructors by using the variable-length argument
facility of Python
(d) All of the above
18. Which of the following is true about the destructor of a class?
(a) It is automatically called when the object goes out of scope
(b) When we delete an object with the del command
(c) The name of the destructor of a class is __del__()
(d) All of the above.
19. Which of the following access modifier is not supported in Python?
(a) public
(b) private
570
(c) protected
(d) None of the above
20. How is a member of a class made private?
(a) using the keyword private
(b) using two leading underscores before the name of the member
(c) using one leading underscore before the name of the member
(d) using two leading and two trailing underscores before the name of the
member
21. Which of the following is valid for an instance method of a class?
(a) It is defined inside the class
(b) It can only be called with the help of an instance
(c) The first parameter of the method is always the reference of the class
(d) All of the above.
22. Which of the following is not true?
(a) We can overload a function
(b) We can overload built-in Python methods
(c) We can overload user-defined functions
(d) None of the above
23. How many objects are there in the memory for the given Python code?
class A:
print("Inside class")
A()
A()
A()
(a) 1
(b) 0
(c) 3
(d) None of the above is true
24. What is the type of inheritance implemented in the following Python code?
class A():
pass
class B(A):
pass
class C(B):
571
pass
def display(self):
print(self.__a, self.b)
class B(A):
def __init__(self):
super().__init__()
self.__a = 20
self.b = 100
C = B()
C.display()
(a) 10 100
(b) 20 200
(c) 10 50
(d) 20 50
Review Questions
572
f. We cannot overload a built-in operator in Python.
g. In dynamic binding, the method linking is done at the run time.
h. Except for the class name, all other components of a class definition are
optional.
i. Each object created from a class will share the same copy of a class attribute.
j. A class attribute cannot be accessed in an instance method.
k. The constructor of a class is used to initialize the attributes of the class
whenever an instance is created.
l. In Python, a dunder method precedes and succeeds with two underscores.
m. When we delete an object with the del command, the destructor of the class
is not called.
n. A private member's name is preceded by two underscores.
o. A protected member name is preceded by a single underscore.
p. The name mangling is a mechanism used by Python to rename a member of
a class with a double underscore prefix to avoid naming conflicts in
inherited classes.
q. The super () method is used to access the parent class members.
Programming Assignments
573
3. Create a class to store a 2D point and implement a member method to determine
the quadrant of the point.
4. Create a class Stats to store a list of floating-point numbers and implement the
methods to calculate the mean, the standard deviation of the list.
5. Create a Rectangle Class to store the length and width of a rectangle and
implement the > operator to check whether the area of the first rectangle is
greater than the second rectangle.
6. Create a class Temp to store a temperature value in a given unit (Celsius,
Fahrenheit, and Kelvin) and implement a method to print the temperature in the
desired unit.
7. Create a Vehicle class to represent general features of a vehicle such as color,
weight, price, registration number. Define two classes Electric and Petrol vehicles
derived from the Vehicle class.
8. Create a Student class to store student details such as the student's name, class,
subject names and marks in five subjects, maximum marks in each subject.
Implement a method to print the mark sheet.
9. Define a class to hold the following data for a bank account: Name, Account
Number, Balance. The class should have the following functions: Open a new
account with an initial balance, deposit an amount, withdraw an amount, and
show the names and their balances. The program should be able to handle 100
customers.
10. Create a class to represent a three-dimensional vector of the for ai+bj+ck, where
a, b, and c are floats and I, k and k are unit vectors in the x-axis, y-axis, and z-
axis, respectively. The class should be able to perform the following functions:
create a new vector, modify components a vector, multiply a vector with a
constant, add two vectors, find the magnitude of a vector, and find the dot
product and cross product of two vectors.
11. Create a class to hold data of a matrix and overload the matrix addition,
subtraction, and multiplication operations.
12. Create a class Rand that generates a random number and stores all the random
numbers generated so far.
13. Create two classes, Metric and British, to hold a distance in the metric system
(meter and centimeter) and the imperial system (feet and inch), respectively.
Also, overload the addition and subtraction of two distances given in any
combination of units.
14. Create a class to store details of a book in a book shop. The details include title,
authors, price, publisher, and quantity in the stock. Define member functions to
show the book's details, sell the book, and purchase the book. The program
574
should store any number of books, update the book's price, and provide a facility
to find a book using title and author names. Design a suitable menu also.
15. Create two classes, Polar and Cartesian, to store the coordinate of a 2D vector in
the Polar and the Cartesian system, respectively. Overload + and – operators and
write a member function to convert from one system to another.
575
576
Chapter 13
When we execute a Python program, the Python interpreter may encounter two
types of errors that will stop the execution of the program: syntax errors and runtime errors
( exceptions). Syntax errors are caused by wrong syntaxes, i.e. incorrect punctuations, in the
code, for example, missing a comma, a bracket, a colon, or misspelling a word, etc. Example
13 (a) shows some syntax errors and the error messages generated by the Python interpreter.
An exception is an operation performed by a statement that is not allowed or
undefined in the given situation or the requested resources are not available. It is a runtime
error, for example, division by zero, unable to open a file, dividing a string with a number,
etc. Example 13(b) shows some examples of exceptions. Whenever a runtime error occurs,
Python creates an exception object and raises an error. If the error is not handled properly,
it prints a generic traceback to that error along with some details about the cause of the
error.
By default, the interpreter will stop the execution of the program when an exception
occurs. However, Python provides some mechanisms, called exception handling, to manage
exceptions and continue the execution of the program.
577
>>> #Missing commas is a syntax error
>>> a=[1 2 3 4]
SyntaxError: invalid syntax
>>>
>>> print(dir(locals()['__builtins__']))
['ArithmeticError', 'AssertionError', 'AttributeError',
'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError',
'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FileExistsError', 'FileNotFoundError',
'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
578
'InterruptedError', 'IsADirectoryError', 'KeyError',
'KeyboardInterrupt', 'LookupError', 'MemoryError',
'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError',
'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError',
'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError',
'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',
'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',
'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError',
'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__',
'__debug__', '__doc__', '__import__', '__loader__', '__name__',
'__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool',
'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod',
'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir',
'divmod', 'enumerate', 'eval', 'exec', 'exit', filter', 'float',
'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help',
'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len',
'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',
'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit',
'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type',
'vars', 'zip']
579
NameError Raised when a variable is not found in the local or global
scope.
NotImplementedError Raised by abstract methods.
OSError Raised when system operation causes a system-related error.
OverflowError Raised when the result of an arithmetic operation is too large
to be represented.
ReferenceError A ReferenceError exception occurs when we try to use a
variable or object that has not been defined or declared.
RuntimeError Raised when an error does not fall under any other category.
StopIteration Raised by the next() function to indicate that there is no
further item to be returned by the iterator.
SyntaxError Raised by the parser when a syntax error is encountered.
IndentationError Raised when there is incorrect indentation.
TabError Raised when indentation consists of inconsistent tabs and
spaces.
SystemError Raised when the interpreter detects an internal error.
SystemExit Raised by sys.exit() function.
TypeError Raised when a function or operation is applied to an object of
the incorrect type.
UnboundLocalError Raised when a reference is made to a local variable in a
function or method, but no value has been bound to that
variable.
UnicodeError Raised when a Unicode-related encoding or decoding error
occurs.
UnicodeEncodeError Raised when a Unicode-related error occurs during
encoding.
UnicodeDecodeError Raised when a Unicode-related error occurs during
decoding.
UnicodeTranslateError Raised when a Unicode-related error occurs during
translating.
ValueError Raised when a function gets an argument of correct type but
the passed is invalid value and canot be processed. Such as
passing negative value to find squire root of real numbers.
ZeroDivisionError Raised when the second operand of division or modulo
operation is zero.
580
13.2 Handling a General Exception
We can use the try-except construct to handle any exception with the following
syntax:
try:
#Put your suspicious code here
Statements
except:
#Handles exception
Statements
We put a suspicious code in the try block. If no exception occur in the try block code,
the except block will be skipped. However, if the Python interpreter raises an exception in
the try block, the execution of the remaining part of the try block code will be skipped and
the except block code is executed. This construction does not differentiate different types of
exceptions and handles all the exceptions in the same manner. Example 13.2 illustrates its
use in finding inverse of elements of a list, which consists of elements of different types. As
can be seen from the output of example 13.2(a), we do not know what are the types of
exceptions. However, we can use the exc_info () method of the sys module to know the
types of exceptions. The exc_info() method returns a list containing the class of the current
exception, its type and the reference of the object that caused the error. These can be helpful
to debug the program to avoid such exceptions in future. Example 13.2(b) illustrates this.
Output
The value of the element: 3
The reciprocal of the element: 0.3333333333333333
The value of the element: a
Error: An exception occurred
The value of the element: 0
Error: An exception occurred
581
The value of the element: True
The reciprocal of the element: 1.0
The value of the element: (2+3j)
Error: An exception occurred
import sys
List = [3,'a', 0, True, 2+3j] #A list with different types of data
Output
The value of the element: 3
The reciprocal of the element: 0.3333333333333333
The value of the element: a
Error: An exception occurred
The class of exception: <class 'ValueError'>
The type of exception: invalid literal for int() with base 10: 'a'
The value of the element: 0
Error: An exception occurred
The class of exception: <class 'ZeroDivisionError'>
The type of exception: division by zero
The value of the element: True
The reciprocal of the element: 1.0
The value of the element: (2+3j)
Error: An exception occurred
The class of exception: <class 'TypeError'>
The type of exception: can't convert complex to int
try:
#Put your suspicious code here
Statements
except exception1:
#Handles exception1
Statements
except (exception2, exception3,…, exceptionM):
#Handles multiple exceptions
Statements
⋮
except exceptionN:
#Handles exceptionN
Statements
except:
#General exception handler. Handles all other unhandled exceptions
Statements
else :
#Executes this block when there is no exception raised by the try block
Statements
finally:
#This block is always executed either there is an exception or not
Statements
Similar to the try-except, we put a suspicious code block in the try block that may
raise different types of exceptions during execution. If an exception is raised by the try block
code, the further execution of the remaining part of the try block code is stopped and the
Python interpreter starts executing the corresponding except block code if it is defined else
it executes the general except block, if defined. If there is no error in the try block code, the
583
interpreter executes it completely and then also executes the else block. And the finally
block code is always executed either there is an exception or not. Example 13.3(a) illustrates
the working of the above construction. We can handle a tuple of exceptions in a single
except block, see example 13.3(b).
Output
The value of the element: 3
The reciprocal of the element: 0.3333333333333333
No exception occurred
Executing the finally block
584
The value of the element: (2+3j)
TypeError exception occurred
Executing the finally block
More about the finally block: If there is an exception raised by the try block and there is no
corresponding except block or generic except block, then it will be treated as an unhandled
exception and the execution of the remaining part of the try code is skipped and the
program execution will stop after executing the finally block code. Since the finally block
always executes whether or not the try statement raises an exception, keep the following
point in mind:
a) If an exception occurs during the execution of the try clause and the exception is not
handled by an except clause, the exception is re-raised after the finally block has
585
been executed. Hence, it is important to handle the generated exceptions to avoid
crashing the program. Example 13.3(c) illustrates this point.
b) If an exception occurs during the execution of an except block or else block, the
exception is re-raised after the finally block has been executed. Example 13.3(d)
illustrates this point.
c) If the try block or except block or else block has a break, continue or return
statement, the finally block will execute just before executing the break, continue or
return statement. In simple words, if the finally block has a return statement, other
return statements in try, except or else blocks will never execute. Example 13.3(e)
illustrates this point.
d) If the try block and the finally block both include a return statement, the return
statement of the finally block will only be executed and the return statement of the
try block will never be executed. Example 13.3(f) illustrates this point.
586
Traceback (most recent call last):
File "D:\akv\akv\Python_book\chapter 7\test1.py", line 8, in <module>
r = 1/int(x) #Calculating the inverse of the element
ValueError: invalid literal for int() with base 10: 'a'
else:
print("No exception occurred in the try block")
#The following statement will generate an exception
a=x+"abc" #Error: Cannot add an integer with a string
finally:
print("Executing finally\n")
Output
The value of the element: 3
The reciprocal of the element: 0.3333333333333333
No exception occurred in the try block
Executing finally
Example 13.3(e): break, continue and return in the try, except or else block
Example 13.3(f): return statements in the try, except, else and finally block
def myInverse(x):
try:
#Suspecious code where an exception can occur
r = 1/int(x) #Calculating the inverse of the element
print("Try block")
return r #This return will never execute
except ZeroDivisionError: #The ZeroDivisionError exception handler
print("Except block")
#The following return will never execute
return "ZeroDivisionError exception occurred."
else:
print("Else block")
return "No exception" #This return will never execute
finally:
print("Finally block")
return "Finally" #Only this return will execute
588
Output
Try block
Finally block
Returned value: Finally
Except block
Finally block
Returned value: Finally
Finally block
Returned value: Finally
#Main program
a=[3,6,0,-2]
for x in a:
#Handling user defined exceptions and buitin-exception
try:
print(myFun(x))
589
except Exception as ex:
print(ex)
Output
0.3333333333333333
6 exceeds the upper limit(5)
division by zero
A negative value -2 is illegal
Where MyException is the name of the new exception class created. We can then
raise a MyException error in a program using a raise statement and catch it through the try-
except construct. Example 13.5(a) illustrates the creation of a user-defined exception and its
handling.
import math
#defining a user-defined exception
class QuadError( Exception ):
pass
def root_quad(a,b,c):
if a == 0:
#Creating an exception object
ex= QuadError( "Not a quadratic equation." ) #Error message
ex.coef= ( a, b, c ) #Adding additional information
raise ex #Raising an exception
if b*b-4*a*c < 0:
ex= QuadError( "No Real Roots exist for this equation." )
ex.coef= ( a, b, c )
raise ex
x1= (-b+math.sqrt(b*b-4*a*c))/(2*a)
590
x2= (-b-math.sqrt(b*b-4*a*c))/(2*a)
return (x1,x2)
#main program
equations=[(0,2,3),(1,2,3),(1,-4,4)]
for c in equations:
try:
print("Roots are:",root_quad(*c))
except QuadError as ex:
print(ex,": With coefficients", ex.coef)
Output
Not a quadratic equation. : With coefficients (0, 2, 3)
No Real Roots exist for this equation. : With coefficients (1, 2, 3)
Roots are: (2.0, 2.0)
#Main program
for i in range(3):
try:
month = int(input("Enter the month number: "))
if not 1 <= month <= 12:
raise MonthError(month)
print(f"{month} is a valid month number")
except MonthError as ex:
print(ex)
591
print("Entered value:",ex.month) #Additional parameter access
Output
Enter the month number: 3
3 is a valid month number
Enter the month number: -4
-4 -> Month number should be within (1,12)
Entered value: -4
Enter the month number: 15
15 -> Month number should be within (1,12)
Entered value: 15
13.6 Assertions
The assertion is used to verify a condition in a programming language as a
debugging tool. If the condition specified in the assert statement is true, no action is taken
and the execution of the program continues as normal, otherwise, an assertion error is raised
and the execution of the program stops. Following is the syntax of the assert statement:
a=[10,-20]
for x in a:
#The execution stops if the assert condition is false
assert x > 0, f"{x} is a negative number"
print(f'{x} is a positive number.')
Output
10 is a positive number.
Traceback (most recent call last):
File "D:/akv/akv/Python_book/Chapter 13/t.py", line 3, in <module>
assert x > 0, f"{x} is negative"
AssertionError: -20 is negative
592
Example 13.6 (b): Handling an assertion error
while(1):
try:
x=int(input("Enter a positive number:"))
assert x > 0, f"{x} is a negative number"
print(f'{x} is a positive number.')
break
except AssertionError as ex: #Handling assertion error
print(ex)
print("Please retry...")
continue
except: #Handling other exceptions
print("Invalid entry. Retry")
continue
print("Value read successfully")
Output
Enter a positive number:-5
-5 is a negative number
Please retry...
Enter a positive number:five
Invalid entry. Retry
Enter a positive number:5
5 is a positive number.
Value read successfully
Sample programs
Sample Program 13.1: Write a program to read an integer from the keyboard. The
program should stop only when a valid integer is entered.
Program
while True: #The loop keeps repeating till a valid integer is entered
try:
n = input("Enter an integer: ")
n = int(n) #Raises the ValueError exception if n is not an
integer
break #Break the loop if n is a valid integer
except ValueError:
print("Invalid input. Please try again ...")
print("Valid integer:", n)
593
Output
Enter an integer: a
Invalid input. Please try again ...
Enter an integer: 12.3
Invalid input. Please try again ...
Enter an integer: 12
Valid integer: 12
Sample Program 13.2: Write a program to add all the digits present in a string.
Program
s=input("Enter the string:")
x=0
for c in s: #Iterate over each character of the string
try:
x=x+int(c) #Raises an exception if c is not a digit
except:
continue #Ignore non-digits and continue to the next character
print(x)
Output
Enter the string:A23rfd21df6as3
The sum of digits in A23rfd21df6as3 is 17
Sample Program 13.3: Write a program to calculate the square root of all the valid
numbers in a list. Use exception handling to ignore the invalid entries.
Program
import math #import math module
data= [1, 2, 3.5, 'a', -5, 20]
result=[]
for x in data: #Iterate over each item in the list
try:
result.append(math.sqrt(x)) #Raises an exception if x is
invalid
except:
result.append("Invalid")
print("List:",data,"\nResult:", result)
Output
List: [1, 2, 3.5, 'a', -5, 20]
594
Result: [1.0, 1.4142135623730951, 1.8708286933869707, 'Invalid', 'Invalid',
4.47213595499958]
Sample Program 13.4: Write a program to read lines in a file and sum all the numbers
found in the file and ignore lines which are not valid numbers.
Program
try:
file_name = input("Enter the file name:")
s=0
file =open(file_name,'r') #May generate exception
flag=True
while(flag):
try:
a=file.readline()
n=float(a) #May generate exception
s=s+n
except: #Handles invalid number situations
if len(a)== 0: #Handling end of file situation
break
else: #Skips lines not containg valid numbers
continue
except Exception as e: #Handles file errors
print("Error:", e)
else:
print("Sum:",s) #Print the sum of all valid numbers
5
Output
Enter the file name:a.txt
Sum: 15.0
Enter the file name:b.txt
Error: [Errno 2] No such file or directory: 'b.txt'
595
Sample Program 13.5: Write a program to read a string from the keyboard and count the
frequencies of letters. Ignore other characters using exceptions.
Solution steps:
letters=dict() #Create an empty dictionary
for i in range(65,91): #Initialise the dictionary with letters
c=chr(i)
letters[c]=0
s=input("Enter the string:")
s=s.upper() #Convert the string to upper case letters
for c in s:
try:
letters[c]=letters[c]+1 #Can generate IndexError Exception for
non-letters
except:
continue #Ignore non-letters
print("Frequencies of letters")
for k in letters:
if letters[k] >0: print( k, ":",letters[k])
print("All other letters: 0")
Output
Enter the string:Arvind Kumar Varma 1970.
Frequencies of letters
A:4
D:1
I:1
K:1
M:2
N:1
R:3
U:1
V:2
All other letters: 0
596
Chapter Summary
597
(a) try block
(b) except block
(c) finally block
(d) else block
3. How many except blocks can a try-except construct have?
(a) 0
(b) 1
(c) >=1
d) None of the above
4. The try-except construct can handle which of the following error
(a) syntax error
(b) runtime error
(c) logical error
(d) all of the above
5. Which of the following exception is raised when the result of an arithmetic
calculation exceeds the maximum limit for a numeric type?
(a) StandardError
(b) ArithmeticError
(c) OverflowError
(d) FloatingPointError
6. The else block of the try-except-else construct is executed ______.
(a) always
(b) when an exception occurs
(c) when no exception occurs
(d) when an exception occurs in the except block
7. The finally block of the try-except-else _finally construct is executed ______.
(a) always
(b) when an exception occurs
(c) when no exception occurs
(d) when an exception occurs in the else block
8. How many exceptions can one block of except statements handle?
(a) 1
(b) 2
(c) 3
(d) None of the above
598
9. What is the output of the following code?
def myFun():
try:
return 1
finally:
return 2
k = myFun()
print(k)
(a) 1
(b) 2
(c) It is an error
(d) None of the above
10. What is the output of the following code?
def myFun():
try:
print("The try block", end=", ")
except:
print("An except block", end=", ")
else:
print("The else block", end=", ")
finally:
print("The finally block")
myFun()
(a) The try block, The else block, The finally block
(b) The try block, The finally block
(c) The try block, The else block
(d) The try block
11. What is the output of the following code?
def myFun():
try:
raise "Custom Error"
print("The try block", end=", ")
except:
print("An except block", end=", ")
599
else:
print("The else block", end=", ")
finally:
print("The finally block")
myFun()
(a) None
(b) It has syntax errors
(c) It has runtime errors
(d) Nothing will be printed
13. What is the output of the following program?
x=-10
assert x<0, print(f"{x} is negative")
600
(a) ValueError
(b) ArithmeticError
(c) NegativeValueError
(d) None of the above
15. When we attempt to read after the end of the file, which of the following
exception is raised?
(a) EOFError
(b) EndofFileError
(c) UnabletoReadError
(d) None of the above
Review Questions
601
9. Describe the assert keyword.
Programming Exercises
1. Define a function fraction (a, b) which returns a/b, but when b is zero, it should
raise an exception.
2. Define a function find_even_number(L) which returns the first even number
found in the list L. If no even number is found in the list, raise an exception.
3. Write a function to read an integer between 1 and 10. If the entered number is
outside this range, raise the ValueError exception.
4. Write a program that converts a time given in 24-hour time format to 12-hour
time format. Handle the exceptions caused by invalid hours and minutes.
5. Write a program that converts date from numerical month/day format to
Month_name day format; for example, 1/31 will result in January 31. Your
program should raise two exceptions MonthError and DayError, for invalid
month and day, respectively.
6. Write a function factorial(n) to calculate the factorial of n. If the value of n is
negative or a number with a fraction value, the function should raise the
ValueError exception.
7. Write a function quadratic_eq_roots(a, b, c) that returns the real roots otherwise
raises the ValueError exception.
8. Create a Car class that stores details of a car. Generate a list of cars. Some of the
cars have troubles with their Motors. Write a function quality_check that iterates
over the list of cars and raises exceptions whenever it finds a car with a motor
problem.
9. Write a program to read a file and print the content. Use a try_except block to
read a valid file name.
10. Write a program to evaluate the expression (a(i)+b(i))/(a(i)-b(i)), where a and b
are vectors of integers. Use exceptions to handle the indeterminate situations.
602
Chapter 14
Introduction to NumPy
Learning outcomes:
14.1 Introduction
NumPy (Numerical Python) is an open-source Python package for efficiently
processing multidimensional arrays. It is developed by Travis Oliphant in 2005. It is
primarily used for mathematical and logical operations on arrays, shape manipulation of
arrays, linear algebra, random number generations, Fourier transforms, etc. NumPy, along
with SciPy (Scientific Python) and Matplotlib (plotting library), is widely used as a free
substitute for MATLAB, for engineering and scientific computations and visualization.
Most of the popular Python distributions have NumPy pre-installed. However, if required,
we can install them using the pip install numpy command.
Python has no built-in array data type. However, we can use a list as an array but it
is very slow and does not provide functions to manipulate array data. To use arrays in
Python, programmers typically use NumPy arrays. Since NumPy is written in C, it provides
a very fast array implementation. Further, it has a large number of array processing
functions.
603
different dimensions along with their axis systems. The shape of an array is specified as an
ordered tuple of integers with the following syntax: shape (axis-0, axis-1, axis-2, …, axisN),
where axis-0, axis-1, …, axis-N are sizes of the corresponding axis. For example, an array of
the shape (4,3) is a 2D array and has four rows and each row has three columns, Figure
14.1(b). Similarly, an array of the shape (2, 4,3) is a 3D array and has two planes; each plane
has four rows and each row has three columns, Figure 14.1(c). Similarly, an array of the
shape (2,2,4,3) is a four-dimensional array. It consists of two cubes. Each cube consists of 2
planes and each plane consists of 4 rows and 3 columns. See Figure 14.1(d).
604
An element of a multi-dimensional array is accessed by an ordered tuple of integers
with the following syntax, arr[i1, i2,…, iN], where arr is the array identifier and i1,i2,… iN
are indices of the element in axis-0, axsis-1, …, axisN, respectively. Indices are enclosed
within a pair of squire bracket and are separated by commas. Consider various arrays
shown in figure 14.1, the value 2 is accessed as a [1], b [0, 1] and c [0, 0, 1], d [0,0,0,1] in
arrays a, b, and c, respectively. Please note, NumPy arrays uses 0-based indexing system.
Similarly, 9 in array c will be accessed as c [0,2,2] and 18 in array d will be accessed as d
[1,0,1,2].
In the C-contiguous, the first row is written in the memory, then the second row,
and so on, as shown in Figure 14.3(a). Whereas, in the F-contiguous system, the first column
is written than the second column and so on, as shown in Figure 14.3(c).
605
dtype Float32
itemsize 4
size 12
ndim 2
shape 4 3
strides 12 4
data 1 2 3 4 5 6 7 8 9 10 11 12
(a) The array shape (4,3)
dtype Float32
itemsize 4
size 12
ndim 2
shape 6 2
strides 4 24
data 1 2 3 4 5 6 7 8 9 10 11 12
(b) The array shown in (a) reshaped as (6,2) using the F-contiguous system
dtype Float32
itemsize 4
size 12
ndim 3
shape 3 2 2
strides 16 8 4
data 1 2 3 4 5 6 7 8 9 10 11 12
By default, NumPy arrays are stored in the C-contiguous system. Numpy uses the
concept of strides for various dimensions of the array to efficiently access the given data
either in the C-continuous system or in the F-continuous system, without changing the
order of the actual data. Stride in a dimension refers to the number of bytes required to skip
to reach the next element in that particular dimension.
606
1 2 3 4
5 6 7 8
9 10 11 12
(a) Matrix
1 2 3 4 5 6 7 8 9 10 11 12
(b) C-contiguous system
1 5 9 2 6 10 3 7 11 4 8 12
(c) F-contiguous system
In figure 14.2, the same data is viewed in different shapes. The data consists of 12
integer values. Figure 14.2(a) shows how to store the data as a matrix of shape 4x3, i.e. four
rows and three columns using C- continuous system. It can be noted that when we change
the shape of an array, data remains the same, only the metadata changes. In Figure 14.2(b),
the same data is accessed as six rows and two columns using F-continuous system by
changing shape attribute to 6x2 and stride to 4x24. Similarly, in Figure 14.2(c), the same data
is accessed as three-dimensional array of shape 3x2x2, using the C-continuous system by
setting the stride to 16x8x4.
(2) Converting other Python data types, such as lists, tuples, etc., into arrays
Using Numpy built-in functions: Numpy has many built-in functions for creating arrays
of different dimensions. Some methods create only one-dimensional arrays, but those can
be converted to other compatible multiple-dimensional arrays. However, some methods
can directly create multi-dimensional arrays. Table 14.1 lists commonly used built-in
methods to create arrays along with some illustrative examples. Before using NumPy in our
607
programs, we have to import it into our program. Typically, we import it using the
statement import numpy as np. Once imported, we can use a NumPy method with the
syntax np.method_name(parameters).
Method description
arange The arange() method creates a one-dimensional array from a range. The range
is specified by start, end, and step. It uses the following syntax:
where start is a number (integer or decimal) that defines the first value in the
array, stop is the number that defines the end of the array but isn’t included
in the array and step is the difference between two consecutive values in the
array. The default value of start is 0 and of step is 1. Note, step cannot be
zero. The last parameter, dtype is the data type of the elements. The default
value of dtype is None, which means arange () will use the most precise data
type from the types of start, stop, and step for the array elements. For
example, an array created using arr=np.arange(1, 10, 1) will have integer data
type. Whereas, an array created using arr=np.arange(1,10,0.5) will have float
data type.
zeros The zeros() method creates an array filled with zeros of a specified shape. Its
syntax is np.zeros(shape, dtype = None, order = 'C') where shape is a tuple
or list of integers representing the shape of the returned array. See the
following examples:
[[0 0 0]
[0 0 0]]]
ones The ones () method creates an array filled with ones of a specified shape. Its
syntax is np.ones(shape, dtype = None, order = 'C'). See the following
examples:
full The full () method creates an array of a specified shape with a specified value
for all its elements. Its syntax is np.full(shape, fill_value, dtype = None,
order = 'C'). See the following examples:
>>> f=np.full((2,3),4,dtype="float32")
>>> print(f)
[[4. 4. 4.]
[4. 4. 4.]]
609
eye The eye () method creates a diagonal array of a specified shape. Its syntax is
np.eye(shape, dtype = None, order = 'C'). See the following examples:
610
Example 14.4(a): Creating arrays with the arange () method
Output
Array: [ 0 1 2 3 4 5 6 7 8 9 10 11]
Array shape: (12,)
Array element type: int32
Array: [[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
611
Array shape: (3, 4)
Array: [[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]]
Array shape: (2, 2, 3)
Array: [10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.]
Array element type: float32
Array: [ 1 3 5 7 9 11 13 15 17 19 21 23]
Array element type: int32
Array: [1. 1.5 2. 2.5 3. 3.5]
Array element type: float64
Array: [24 22 20 18 16 14 12 10 8 6 4 2]
Array element type: int32
Converting Python data in Arrays: We can convert Python lists and tuples into
NumPy arrays using the numpy.array(data) and numpy.asarray(data) methods of the
NumPy module. Here, data can be a list or a tuple of homogeneous data elements or another
NumPy array. If the data is a multi-dimensional list or tuple, it must contain an equal
number of elements in an axis. For example, each row of a list must contain the same
number of elements. The list [[1,2,3], [4,5,6]] can be converted to a NumPy array as it
contains an equal number of elements in both rows, whereas, the list [[1,2,3], [4,5]] will
generate an error as the numbers of elements in two rows are not the same. Example 14.4(b)
illustrates the numpy.array() and numpy.asarray() methods to create 1D and multi-
dimensional arrays.
For list and tuple data, both the functions create independent NumPy arrays, but for
a NumPy array data, the numpy.array() creates another independent NumPy array but
numpy.asarray() method creates an alias of the data array, i.e. any changes made in either
the original array or the created array will change both. Example 14.4(c) illustrates this.
Example 14.4(b): Converting Python lists and tuples into NumPy arrays
import numpy as np
lst1=[1,2,3]
arr=np.array(lst1) #Converting a 1D list into a NumPy array
print(arr, "\n")
612
arr1=np.asarray(lst1) #Converting a 1D list into a NumPy array
print(arr1, "\n")
#Converting a list which contains lists and tuples into a NumPy array
lst2=[(1,2,3),[4,5,6]]
arr=np.array(lst2)
print(arr, "\n")
arr1=np.asarray(lst2)
print(arr1, "\n")
#Converting a tuple which contains lists and tuples into a NumPy array
tpl=([1,2,3],(4,5,6))
arr=np.array(tpl)
print(arr, "\n")
arr1=np.asarray(tpl)
print(arr1, "\n")
Output
[1 2 3]
[1 2 3]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
613
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
import numpy as np
lst1=[1,2,3]
arr=np.asarray(lst1) #Creating an independent copy
arr1=np.asarray(arr) #Creating a linked copy
print(lst1,arr, arr1)
arr[0]=10 #This change will also be in arr1 but not in lst1
arr1[1]=20 #This change will also be in arr
print(lst1,arr,arr1, "\n")
614
print(lst1, arr, arr1)
arr[0]=10 #This change will not affect arr1
arr1[1]=20 #This change will not affect arr1
print(lst1, arr,arr1, "\n")
Output
[1, 2, 3] [1 2 3] [1 2 3]
[1, 2, 3] [10 20 3] [10 20 3]
[1, 2, 3] [1 2 3] [1 2 3]
[1, 2, 3] [10 2 3] [ 1 20 3]
[1, 2, 3] [1 2 3] [1 2 3]
[1, 2, 3] [10 2 3] [10 2 3]
Using Special Library Functions to create arrays: NumPy has many special library
functions to create arrays, such as arrays of random numbers. Arrays of random numbers
are widely used in scientific and engineering computations. NumPy offers the random
module to work with random numbers. We can import the random module of NumPy by
using the following syntax: from numpy import random. Table 14.2 lists commonly used
special functions to create random number arrays.
Method Description
615
2
>>> random.randint(-5,5) #A random number between -5 and 5
3
>>> random.randint(0,10,5) # 1D array of random integers
array([3, 1, 3, 6, 3])
>>>#Use a tuple to specify the shape of the array
>>>random.randint(0,10,(2,3))
array([[6, 1, 3],
[5, 2, 8]])
>>>#Use a list to specify the shape of the array
>>> random.randint(-5,5,[2,3])
array([[ 4, 1, 1],
[-5, -1, 1]])
rand The random.rand(s1,s2,…,sN) method returns an array of random float
between 0 and 1. The shape of the returned array is specified through the
integers parameters s1,s2,…, sN. All the parameters are optional and by
default, it returns a single random float number. Contrary to the
random.randint () method, we cannot use a tuple or a list to specify the
shape of the returned array. Some illustrative examples of this method are
given below:
616
array([3, 1, 4])
>>> #Randomly choose numbers from a list and return them as
a multi-dimensional array
>>> random.choice([1,2,3,4,5],(2,2))
array([[5, 4],
[3, 4]])
>>> #Randomly choose numbers from a tuple and return them
as an array
>>> random.choice((1,2,3,4,5),5)
array([2, 3, 5, 2, 4])
>>> #Randomly choose numbers from an array and return them
as an array
>>> arr=np.array([1,2,3,4,5])
>>> random.choice(arr)
5
shuffle The random.shuffle(arr) method shuffles the elements of the given array
For a multidimensional array, the shuffling is done along the axis=0. See
the following examples.
>>> a=[1,2,3,4,5]
>>> random.shuffle(a) #Shuffles elements of a list
>>> a
[4, 2, 3, 5, 1]
>>> b=np.array((1,2,3,4,5))
>>> random.shuffle(b) #Shuffles elements of an array
>>> b
array([5, 4, 3, 1, 2])
>>> a=np.arange(12).reshape(3,2,2) #Create a multi-
dimensional array
>>> print(a)
[[[ 0 1]
[ 2 3]]
[[ 4 5]
[ 6 7]]
[[ 8 9]
617
[10 11]]]
>>> random.shuffle(a) #Shuffle a multi-dimensional array
>>> print(a)
[[[ 0 1]
[ 2 3]]
[[ 8 9]
[10 11]]
[[ 4 5]
[ 6 7]]]
permutation The random.permutation (seq) method returns a random permutation of
the given sequence.
>>> a=np.array([1,2,3,4,5])
>>> #Create a random permutation of the given sequence
>>> b=random.permutation(a)
>>> b
array([2, 4, 1, 3, 5])
Method Description
ndim The attribute ndarray.ndim represents the number of dimensions (axes) of the
ndarray.
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> arr.ndim #Get the number of dimensions
618
3
shape The attribute ndarray.shape is a tuple of integers representing the size of the
ndarray in each dimension.
Datatype Description
bool_ Boolean type (True or False)
int_ Default integer type (either int64 or int32)
intc Equivalent to C int (either int32 or int64)
intp Integer used for indexing (either int32 or int64)
int8 Byte (-128 to 127)
int16 Integer (-32768 to 32767)
int32 Integer (-2147483648 to 2147483647)
int64 Integer (-9223372036854775808 to 9223372036854775807)
uint8 Unsigned integer (0 to 255)
619
uint16 Unsigned integer (0 to 65535)
uint32 Unsigned integer (0 to 4294967295)
uint64 Unsigned integer (0 to 18446744073709551615)
float_ float64
float16 Half precision float: sign bit, 5 bits exponent, 10 bits mantissa
float32 Single precision float: sign bit, 8 bits exponent, 23 bits mantissa
float64 Double precision float: sign bit, 11 bits exponent, 52 bits mantissa
complex_ complex128
complex64 Complex number, represented by two 32-bit floats (real and imaginary
components)
complex128 Complex number, represented by two 64-bit floats (real and imaginary
components)
>>> a=np.arange(12).reshape(3,4)
>>> print(a)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
>>> a[0,0] #Accessing the first element of the first row
0
>>> a[0][0] #Using two separate square brackets to access an element
0
>>> a[2,3] #Using a single square bracket to access an element
11
>>> a[-1,-1] #Accessing elements with negative indexing
11
620
>>> a[1] #Accessing a sub-array
array([4, 5, 6, 7])
>>> b=a.reshape(2,2,3)
>>> b
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> b[0] #Accessing a sub-array
array([[0, 1, 2],
[3, 4, 5]])
>>> b[1][1] #Accessing a sub-array
array([ 9, 10, 11])
Slicing: Similar to Python collection objects, such as lists, tuples, NumPy arrays also
support slicing. Through slicing, we can get a sub-array of an array. Numpy uses the Python
slicing notations, which has the following syntax: [start: end: step], where start is the
starting index, end is the last index of the original array and step is the increment used to
create the sub array. All the parameters are optional. The default value of start is 0, default
value of end is size of the concerned axis and the default value of step is 1. Example 14.6(b)
illustrates slicing operations.
621
>>> a[-12:-1:2] #Get alternate elements starting from the 12th from the
end
array([ 0, 2, 4, 6, 8, 10])
>>> a[11:0:-2] #Get alternative elements starting from the 11th in the
reverse order
array([11, 9, 7, 5, 3, 1])
>>> b=np.arange(12).reshape(3,4)
>>> print(b)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
>>> b[1:3,1:3]#Get a slice of 2nd and 3rd rows and 2nd and 3rd columns
array([[ 5, 6],
[ 9, 10]])
>>> #Select alternate elements from each row and each column
>>> c=b[::2,::2]
>>> print(c)
[[ 0 2]
[ 8 10]]
>>> b[1:3,:] #Get 2 and 3 rows
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> b[::-1] #Transpose the array in axis-0
array([[ 8, 9, 10, 11],
[ 4, 5, 6, 7],
[ 0, 1, 2, 3]])
>>> b[:,::-1] #Transpose the array in axis-1
array([[ 3, 2, 1, 0],
[ 7, 6, 5, 4],
[11, 10, 9, 8]])
List indexing: For accessing more than one element in an array, we can use lists of indices
for each axis. All the lists used should be of the same size. The elements are accessed by
pairing the first element of each list, then the second and so on. We can also use list for some
axes and slicing for the others. The selected elements are returned as 1D array. Example
14.6(c) illustrates this.
>>> a=np.arange(10)
>>> ind=[1,4,2,6,5,2]
>>> a[ind] #List indexing
array([1, 4, 2, 6, 5, 2])
622
>>> a=np.arange(9).reshape(3,3)
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> a[[0,1,2],[0,1,2]] #Select diagonal elements
array([0, 4, 8])
>>> a[[0,0,2,2],[0,2,0,2]] #Select all corner elements
array([0, 2, 6, 8])
>>> a[[0,1,2,2,2],[0,0,0,1,2]] #Select the first column and the last
row
array([0, 3, 6, 7, 8])
>>> a[:,[1,2]] #Combining slicing and list indexing
array([[1, 2],
[4, 5],
[7, 8]])
>>> a[[0,2],:] #Mixing list indexing and slicing
array([[0, 1, 2],
[6, 7, 8]])
>>> a[[0,2,1],:] #Rearranging rows
array([[0, 1, 2],
[6, 7, 8],
[3, 4, 5]])
>>> a[[0,0,1,1,2,2],:] #Repeating rows
array([[0, 1, 2],
[0, 1, 2],
[3, 4, 5],
[3, 4, 5],
[6, 7, 8],
[6, 7, 8]])
Array indexing: Similar to the list indexing, we can use a NumPy array to access multiple
elements from an array. The selected elements are returned in the shape of the index array.
We can use array indexing in a multidimensional array as well, where corresponding
elements are paired to access the elements. Example 14.6(d) illustrates the array indexing.
>>> a=np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> ind=np.array([2,3,6,8])
>>> a[ind] #Array indexing
array([2, 3, 6, 8])
623
>>> a[ind[::-1]] #Indexing array can be manipulated
array([8, 6, 3, 2])
>>> ind=np.array([[1,5],[6,8]]) #Multi-dimensional indexing array
>>> a[ind]
array([[1, 5],
[6, 8]])
>>> a=np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> rows=np.array([0,2])
>>> columns=np.array([1,3])
>>> a[rows,columns] #Array indexing in multi-dimension
array([ 1, 11])
>>> #Multi-dimensional indexing in a multi-dimensional array
>>> ind1=np.array([[0,2],[1,2]])
>>> ind2=np.array([[1,2],[0,2]])
>>> a[ind1,ind2]
array([[ 1, 10],
[ 4, 10]])
Ellipsis indexing: NumPy arrays use ellipsis (…), three dots, to automatically add the
required number of full slice (:) to make the number of the indexing dimensions equal to
the number of axes of the array. We can use only one ellipsis in ellipsis indexing. Example
14.6(e) illustrates the ellipsis indexing. In this example, a [0 ,0, …] is equal to a [0, 0, :, :] and
a[0, …] is equal to a[0, :, :, :].
>>> a=np.arange(24).reshape(2,2,2,3)
>>> a
array([[[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]],
624
[21, 22, 23]]]])
>>> a[0,0,...] #The ellipsis covers the remaining 2 dimensions
array([[0, 1, 2],
[3, 4, 5]])
>>> a[0,...] #The ellipsis covers the remaining 3 dimensions
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> a[0,...,0] #The ellipsis covers the middle 2 dimensions
array([[0, 3],
[6, 9]])
>>> a[0:1,...] #Ellipsis with slicing
array([[[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]]])
>>> a[...,1:2] #Ellipsis with slicing
array([[[[ 1],
[ 4]],
[[ 7],
[10]]],
[[[13],
[16]],
[[19],
[22]]]])
Boolean Array Indexing: In the Boolean Array indexing, we use an array of Boolean values
as an indexing array. The values of the array corresponding to the True values in the
indexing array are selected and returned as a 1D array. A Boolean indexing array can be
created using a Boolean expression. Example 14.6(f) illustrates the Boolean array indexing.
626
operation involves a scalar and an array, the same scalar is used with all the elements of the
array to perform the operations. Commonly used element-wise operations are arithmetic
operations, logical operations, transcendental operations, etc. Some of these operations can
be performed either through operators or the corresponding methods.
Arithmetic operations: All the Python arithmetic operators can be used with arrays to
perform element-wise arithmetic operations. All the numeric data types including complex
numbers can be processed by NumPy. Example 14.7(a) illustrates some arithmetic
operations.
>>> a=np.random.randint(10,size=4)
>>> b=np.random.randint(10,size=4)
>>> print(a,b)
[7 4 6 2] [7 8 8 5]
>>> a+b #Addition of arrays
array([14, 12, 14, 7])
>>> a-b #Subtraction
array([ 0, -4, -2, -3])
>>> a*b #Multilication
array([49, 32, 48, 10])
>>> a/b #Float division
array([1. , 0.5 , 0.75, 0.4 ])
>>> a**b #Power
array([ 823543, 65536, 1679616, 32], dtype=int32)
>>> a+2 #Scalar addition
array([16, 14, 16, 9])
>>> a/2 #Scalar division
array([7. , 6. , 7. , 3.5])
>>> c=a.reshape(2,2)
>>> d=b.reshape(2,2)
>>> print(c)
[[7 4]
[6 2]]
>>> print(d)
[[7 8]
[8 5]]
>>> c+d #Addition
array([[14, 12],
[14, 7]])
>>> c%d #Modulus
array([[0, 4],
[6, 2]], dtype=int32)
627
>>> c+=d #Compound operations
>>> print(c)
[[14 12]
[14 7]]
#Generate NumPy arrays of random complex numbers
>>> Z = np.random.random(3) + np.random.random(3) * 1j
>>> Y = np.random.random(3) + np.random.random(3) * 1j
>>> print(Z)
[0.63094606+0.343771j 0.04810698+0.89952661j 0.11646971+0.11310903j]
>>> print(Y)
[0.42228583+0.09089449j 0.59921329+0.56704785j 0.33460894+0.00751817j]
>>> Z+Y #Addition of complex arrays
array([1.05323189+0.43466549j, 0.64732027+1.46657446j,
0.45107865+0.12062719j])
>>>
Relational and Logical operations: Relational operations such as greater than, less than,
etc, and logical operations such as and, or, etc. can be efficiently performed on arrays. For
logical operations, use np.logical_and() and np.logical_or() methods to perform logical
AND and OR operations element-wise, instead of and and or operators. Example 14.7(b)
illustrates some logical and relational operations on arrays.
628
array([ True, True, False, True])
>>> np.logical_and(a<=b,True) #Using a scalar logical value
array([ True, True, False, True])
>>> a=np.arange(1,5)
>>> a
array([1, 2, 3, 4])
>>> np.sin(a) #Calculate element-wise sine
array([ 0.84147098, 0.90929743, 0.14112001, -0.7568025 ])
>>> np.log(a) #Calculate element-wise natural log
array([0. , 0.69314718, 1.09861229, 1.38629436])
>>> np.log10(a) #Calculate element-wise log base 10
array([0. , 0.30103 , 0.47712125, 0.60205999])
>>> np.exp(a) #Calculate element-wise exponential
array([ 2.71828183, 7.3890561 , 20.08553692, 54.59815003])
>>> #Random integers between -5 and 5
>>> a=np.random.randint(-5,5, size=4)
>>> b=np.random.randint(-5,5, size=4)
>>> c=a+1j*b #Creating an array of complex numbers
>>> print(c)
[-4.-3.j 0.+4.j -5.-4.j -4.+1.j]
>>> np.sin(c) #Calculate sine of complex numbers
array([ 7.61923172 +6.54812004j, 0. +27.2899172j ,
26.18652736 -7.74111755j, 1.16780727 -0.76816276j])
>>> np.log(c) #Calculate natural log of complex numbers
array([1.60943791-2.49809154j, 1.38629436+1.57079633j,
1.85678603-2.46685171j, 1.41660667+2.89661399j])
The numpy.linalg sub-module of the NumPy module provides all the functionalities
required for linear algebra. Some of the commonly used functions of this module are
described in table 14.3.
629
Table 14.3: Linear algebra functions in NumPy
Function Description
dot The numpy.dot(a, b, out = None) method returns the dot product of a
and b if a and b are vectors. If a and b are matrices, it returns their matrix
multiplication. For higher order arrays, it returns the sum-product over
the last axis of a and the second-to-last axis of b. It can also handle vectors
of complex numbers.
>>> a=np.random.randint(5,size=3)
>>> b=np.random.randint(5,size=3)
>>> print(a,b)
[1 3 3] [4 2 3]
>>> np.dot(a,b) #Calculate the dot product of two vectors
19
>>> a=np.random.randint(5,size=6).reshape(2,3)
>>> b=np.random.randint(5,size=6).reshape(3,2)
>>> print(a)
[[0 3 2]
[0 4 1]]
>>> print(b)
[[2 4]
[1 3]
[2 4]]
>>> np.dot(a,b) #Calculate the matrix multiplication of
two 2D arrays
array([[ 7, 17],
[ 6, 16]])
>>> a=np.random.randint(5,size=8).reshape(2,2,2)
>>> b=np.random.randint(5,size=8).reshape(2,2,2)
>>> print(a)
[[[0 4]
[3 2]]
[[4 4]
[0 4]]]
>>> print(b)
[[[3 4]
[4 4]]
[[2 1]
[4 4]]]
630
>>> np.dot(a,b) #Calculate the dot product of higher
dimension arrays
array([[[[16, 16],
[16, 16]],
[[17, 20],
[14, 11]]],
[[[28, 32],
[24, 20]],
[[16, 16],
[16, 16]]]])
>>> a=2+3j
>>> b=4+5j
>>> np.dot(a,b) #Dot product of vectors
(-7+22j)
vdot The numpy.vdot(a, b) returns the dot product of vectors a and b. If a and
b are arrays of higher dimensions, they are flattened before calculating
the dot product. For vectors of complex numbers, the dot product of the
conjugate of the first vector with the second vector is returned.
>>> a=2+3j
>>> b=4+5j
>>> np.vdot(a,b) #Dot product of the conjugate of a and b
(23-2j)
>>> np.dot(a,b) #Dot product of a and b
(-7+22j)
>>> a=np.array([2,3,6])
>>> b=np.array([4,2,8])
>>> np.vdot(a,b) #Dot product of vectors
62
>>> a=np.arange(4).reshape(2,2)
>>> b=np.arange(4,8).reshape(2,2)
>>> np.vdot(a,b) #Dot product after flattening both a and
b
38
matmul The numpy.matmul(a,b) method returns the matrix multiplication of
two matrices a and b. For higher dimension arrays, it broadcasts the array
like a stack of matrices as elements residing in the last two indexes,
respectively. On the other hand, the numpy.dot(a,b,) method returns the
multiplication as the sum of products over the last axis of the first array
and the second-to-last of the second.(why to discuss this?). Whereas
631
numpy.multiply(a,b,) method returns the element-wise multiplication of
two arrays.
>>> a=np.arange(4).reshape(2,2)
>>> b=np.arange(4,8).reshape(2,2)
>>> a
array([[0, 1],
[2, 3]])
>>> b
array([[4, 5],
[6, 7]])
>>> np.matmul(a,b) #Matrix multiplication of two 2D arrays
array([[ 6, 7],
[26, 31]])
>>> np.dot(a,b) #Matrix multiplication of two 2D arrays
array([[ 6, 7],
[26, 31]])
>>> np.multiply(a,b) #Element-wise multiplication of two
2D arrays
array([[ 0, 5],
[12, 21]])
>>> a=np.arange(8).reshape(2,2,2)
>>> b=np.arange(8,16).reshape(2,2,2)
>>> print(a)
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
>>> print(b)
[[[ 8 9]
[10 11]]
[[12 13]
[14 15]]]
>>> np.matmul(a,b) #Plane-wise matrix multiplication of
two arrays
array([[[ 10, 11],
[ 46, 51]],
[[118, 127],
[170, 183]]])
>>> np.matmul(a[0],b[0]) #Plane 0
array([[10, 11],
[46, 51
>>> np.matmul(a[1],b[1]) #Plane 1
632
array([[118, 127],
[170, 183]])
>>> np.dot(a,b) #Dot product of two arrays
array([[[[ 10, 11],
[ 14, 15]],
[[ 46, 51],
[ 66, 71]]],
[[118, 131],
[170, 183]]]])
>>> np.multiply(a,b) #Element-wise multiplication of two
arrays
array([[[ 0, 9],
[ 20, 33]],
[[ 48, 65],
[ 84, 105]]])
>>>
det >>> a=np.random.randint(5,size=9).reshape(3,3)
>>> a
array([[1, 2, 2],
[3, 2, 1],
[2, 0, 4]])
>>> np.linalg.det(a) #Calculate the determinant of a
matrix
-20.000000000000007
>>> a=np.random.randint(5,size=12).reshape(3,2,2)
>>> a
array([[[0, 4],
[1, 3]],
[[2, 3],
[3, 1]],
[[2, 0],
[2, 3]]])
>>> np.linalg.det(a) #Calculate the determinant of each
sub-matrix
array([-4., -7., 6.])
633
solve The numpy.linalg.solve(A, B) method solves a system of linear equations
of the form AX=B, where A is the coefficient square matrix and B is the
constant vector. For the following system of linear equations:
𝑥+𝑦+𝑧 = 3
2𝑥 + 3𝑦 + 𝑧 = 6
𝑥 + 𝑦 + 5𝑧 = 7
>>> A=np.array([[1,1,1],[2,3,1],[1,1,5]])
>>> B=np.array([3,6,7])
>>> print(A)
[[1 1 1]
[2 3 1]
[1 1 5]]
>>> print(B)
[3 6 7]
>>> X=np.linalg.solve(A,B) #Solve a system of linear
equations
>>> print(X)
[1. 1. 1.]
inv The numpy.linalg.inv(a) method finds the multiplicative inverse of an
array. If the array is of more than two dimensions, the inverses of the
matrices formed by the last two axes are calculated. The last two axes
must for a square matrix.
>>> A=np.array([[1,1,1],[2,3,1],[1,1,5]])
>>> print(A)
[[1 1 1]
[2 3 1]
[1 1 5]]
>>> np.linalg.inv(A) #Inverse of a matrix
array([[ 3.5 , -1. , -0.5 ],
[-2.25, 1. , 0.25],
[-0.25, 0. , 0.25]])
>>> A=np.random.randint(5,size=8).reshape(2,2,2)
>>> A
array([[[3, 3],
[4, 3]],
[[4, 4],
[1, 2]]])
>>> np.linalg.inv(A) #Plane-wise inverse of an array
array([[[-1. , 1. ],
[ 1.33333333, -1. ]],
634
[[ 0.5 , -1. ],
[-0.25 , 1. ]]])
Function Description
sum The numpy.sum(a, axis=None) method sums the elements of the array
in the specified axis. The method can also be called with the array
object, such as a.sum(axis=0). In no axis is specified, all the elements
will be summed.
>>> a=np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a.sum(axis=0) #Sum elements along an axis
array([12, 15, 18, 21])
>>> np.sum(a, axis=1) #Sum elements along an axis
array([ 6, 22, 38])
>>> a.sum() #Sum all the elements. Global reduction
66
mean The numpy.mean(a, axis=None) method finds the mean of the
elements in the specified axis.
635
>>> a.mean(axis=1)
array([1.5, 5.5, 9.5])
>>> np.mean(a) #Find global mean
5.5
std The numpy.std(a, axis=None) method finds the standard deviation of
the elements in the specified axis.
>>> a.argmin(axis=1)
array([3, 1, 1], dtype=int64)
636
>>> a.ravel() #Flatten the array
array([94, 40, 97, 10, 40, 37, 60, 75, 94, 51, 74, 72])
>>> a.argmin() #The index of the minimum in the flattened
view
3
reduce The numpy.add.reduce(a, axis=0) sums the elements in a specified
axis.
1. An array with the size of dimension in an axis equal to 1 can be stretched to match the
other array in the same axis.
2. An array can be stretched in more than one axis if it meets the above criterion.
Figure 14.4 graphically illustrates the concept of the broadcasting. The elements written
in the solid boxes are the original array and the elements in the dotted boxes are the
broadcasted elements. Example 14.7(d) illustrates the broadcasting concept.
637
1 2 3 + 5 5 5 = 6 7 8
(a) Broad casting with a scalar
1 2 3 1 2 3 2 4 6
4 5 6 + 1 2 3 = 5 7 9
7 8 9 1 2 3 8 10 12
(b) Broadcasting with a vector
1 1 1 1 2 3 2 3 4
2 2 2 + 1 2 3 = 3 4 5
3 3 3 1 2 3 4 5 6
(c) Broadcasting with two vectors
>>> a=np.arange(1,4).reshape(1,3)
>>> a
array([[1, 2, 3]])
>>> a+5 #Broadcasting with a scalar
array([[6, 7, 8]])
>>> a.shape
(1, 3)
>>> print(a, a.shape)
[[1 2 3]] (1, 3)
>>> b=np.arange(1,10).reshape(3,3)
>>> print(b,b.shape)
[[1 2 3]
[4 5 6]
[7 8 9]] (3, 3)
>>> b+a #Broadcasting with a matrix and a vector
array([[ 2, 4, 6],
[ 5, 7, 9],
[ 8, 10, 12]])
>>> c=a.T
>>> print(c, c.shape)
[[1]
[2]
638
[3]] (3, 1)
>>> a+c #Broadcasting with a row vector and a column vector
array([[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
>>> a=np.arange(8).reshape(2,2,2)
>>> print(a)
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
>>> b=np.array([[1,2],[3,4]])
>>> print(b)
[[1 2]
[3 4]]
>>> a+b #Broadcasting in multi-dimensional arrays
array([[[ 1, 3],
[ 5, 7]],
[[ 5, 7],
[ 9, 11]]])
A NumPy array can be reshaped, resized and axes can be flipped depending on the
requirement in a situation. Table 14.5 list commonly used array shape manipulation
methods.
Function Description
>>> a=np.arange(8)
>>> print(a) #Original array
[0 1 2 3 4 5 6 7]
639
>>> b=a.reshape(2,4) #Reshaped array
>>> print(b)
[[0 1 2 3]
[4 5 6 7]]
>>> c=np.reshape(a,(2,2,2)) #Reshaped array
>>> print(c)
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
>>> print(a.shape, b.shape,c.shape) #Shapes of arrays
(8,) (2, 4) (2, 2, 2)
ravel The numpy.ravel(arr, order="C") method returns a flattened 1D array.
The shape of the original array does not change.
640
>>> b=a.reshape(2,2,3) #Reshaped array
>>> b
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> #Transposing an array in given axes order. Only axes 1
and 2 are swaped
>>> c=b.transpose((0,2,1))
>>> c
array([[[ 0, 3],
[ 1, 4],
[ 2, 5]],
[[ 6, 9],
[ 7, 10],
[ 8, 11]]])
>>> b.transpose(2,1,0) #All the axes are swapped
array([[[ 0, 6],
[ 3, 9]],
[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]]])
>>>
>>> b.T # Using T flag to transpose all axes
array([[[ 0, 6],
[ 3, 9]],
[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]]])
resize The numpy.resize(a, new_shape) returns a new array with the specified
shape. If the new array is larger than the original array, then the new
array is filled with repeated copies of a. However, the
a.resize(new_shape) syntax resizes the original array itself and fills the
extra new elements created due to resize with zeros. It is recommended
to use numpy.reshape() if the number of elements in the original and the
new arrays are the same.
641
>>> a=np.arange(6).reshape(2,3)
>>> a #Original array
array([[0, 1, 2],
[3, 4, 5]])
>>> b=np.resize(a,(3,4)) #Use the repeated copies of the
original array
>>> b #Resized array
array([[0, 1, 2, 3],
[4, 5, 0, 1],
[2, 3, 4, 5]])
>>> a.resize((3,4), refcheck=False) #Fill the extra
elements with zero
>>> a #Original but resized array
array([[0, 1, 2, 3],
[4, 5, 0, 0],
[0, 0, 0, 0]])
>>> #For the reduced size, extra tail elements are
discarded
>>> c=np.resize(a,(2,2))
>>> print(c)
[[0 1]
[2 3]]
pad The numpy.pad(arr, pad_width, mode='constant', **kwargs) enlarges an
array by padding values at the end of each axis. By default, it uses zero
as the padding value. However, there are other values, such as a constant
value, edge values, maximum of the axis, etc. can be used. See online help
for greater details.
643
Example 14.7(e): Sorting NumPy arrays
>>> a=np.random.randint(100,size=12).reshape(3,4)
>>> a #Original array
array([[50, 50, 31, 37],
[48, 78, 68, 96],
[11, 14, 41, 81]])
>>> a.sort() #Sort in place along the last axis, i.e. along the row
>>> a
array([[31, 37, 50, 50],
[48, 68, 78, 96],
[11, 14, 41, 81]])
>>> a.sort(axis=0) #Sort in place along axis=0
>>> a
array([[11, 14, 41, 50],
[31, 37, 50, 81],
[48, 68, 78, 96]])
>>> b=np.sort(a,axis=None) #Return sorted flattened array
>>> b
array([11, 14, 31, 37, 41, 48, 50, 50, 68, 78, 81, 96])
>>> a
array([[11, 14, 41, 50],
[31, 37, 50, 81],
[48, 68, 78, 96]])
However, the above way to store data shows that there is no relationship among
data. A NumPy structured array can be used to store such data in a more meaningful
manner. Structured arrays are ndarrays whose compound datatype consists of a tuple of
named fields and their datatypes. A compound data type can be created using the following
644
methods: (a) using a list of tuples of field names and the corresponding data types, (b) using
a dictionary with two keys 'names' and 'formats' for field names and data types,
respectively, and (c) using a string, when the fild names are not important.
where field1,field2, …, fieldN and format1, format2,…, formatN are strings. A format string
consists of an alphabet and a number, for example, 'i4', 'S10', 'f8', etc. The alphabet indicates
the type of data. Various valid alphabets are given in table 14.6 along with their data types.
The number in a format string is the size of the data in bytes, for example, 'S10' means string
data type of 10 characters long 'i4' meand 4 byte integer. Optionally, a format string can be
prefixed with < or >, which means "little-endian" or "big-endian," respectively, and specifies
the ordering convention for significant bits.
For the example data given above, the compound datatype is defined using the three
methods are as given below:
Once a compound data type is defined, it can be used to create a structured array.
In a structured array, data can be accessed using either a field name or the corresponding
integer index, similar to normal arrays. Example 14.8(a) illustrates the creation and
645
manipulation of a structured array. The creation of a compound data type and array
creation can be combined in one step. Example 14.8(b) illustrates this.
Table 14.6: Formatting string characters and their corresponding data types
646
array([(b'Alice', 20, 65. ), (b'John', 40, 85. ), (b'Boby', 35, 70. ),
(b'Den', 15, 40.5)],
dtype=[('f0', 'S10'), ('f1', '<i4'), ('f2', '<f8')])
>>> #Creating a compound data type using a dictionary
>>> dtype2 = np.dtype({'names':('name', 'age', 'weight'),
'formats':('U10', 'i4', 'f8')})
>>> data2=np.zeros(4,dtype=dtype2)
>>> data2['name']=name #Populating fields
>>> data2['age']=age
>>> data2['weight']=weight
>>> data2
array([('Alice', 20, 65. ), ('John', 40, 85. ), ('Boby', 35, 70. ),
('Den', 15, 40.5)],
dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f8')])
>>> data[0] #Accessing using an index
(b'Alice', 20, 65.)
>>> data[0][0] #Accessing using indices
b'Alice'
>>> print(data[0][0],data[0][1],data[0][2])
b'Alice' 20 65.0
>>> data['name'] #Accessing using a field name
array([b'Alice', b'John', b'Boby', b'Den'], dtype='|S10')
>>> data['age']
array([20, 40, 35, 15])
>>> data['weight']
array([65. , 85. , 70. , 40.5])
>>> print(data['name'][0]) #Hybrid accessing
b'Alice'
647
Sample Program 14.1: Write a program to add a border of zeros to a square matrix
Solution Steps:
1. Use pad method of NumPy module to add a border
import numpy as np # Import the NumPy package
m=3
n=1
array = np.ones((m, m)) # Creating a mXm Numpy matrix
print("Original array")
print(array)
print("\nMatrix with 0 border")
# using np.pad()
array = np.pad(array, pad_width=n, mode='constant',constant_values=0)
print(array)
Output
Original array
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
Sample Program 14.2: Write a program to count zero and non-zero values in an array
Solution Steps:
1. Use count_nonzero method to get non zero elements
2. Use the size attribute to get the total elements in the array
import numpy as np #Import NumPy module
arr = np.array([[0, 1, 4, 3, 0], [0, 3, 8, 0, 7]]) #Original array
n = np.count_nonzero(arr) #Count non-zero elements
print ("Number of non zero elements:", n)
print("Number of zeros:", arr.size-n) #Number of zeros
Output
Number of non zero elements: 6
Number of zeros: 4
648
Sample Program 14.3: Write a program to remove leading and trailing zeros of a 1D
array.
Solution Steps:
1. Use trim_zero method to remove leading and trailing zeros
import numpy as np #Import NumPy module
arr = np.array([0,0,1,2,3,0]) #Original array
arr1 = np.trim_zeros (arr) #Remove leading and training zeros
print("Original array:", arr)
print("Trimmed array:",arr1)
Output
Original array: [0 0 1 2 3 0]
Trimmed array: [1 2 3]
Sample Program 14.4: Write a program to replace all the negative values in an array with
zero.
Solution Steps:
1. Use less than conditional operator, <, to generate a Boolean index matrix and use that
matrix to replace the negative values with zeros
import numpy as np #Import NumPy module
array1 = np.array([[1, 2, -3],[4, -5, -6]])
print("Original array:\n", array1)
# Code to replace all negative value with 0
array1[array1<0] = 0
print("Resulting array: \n", array1)
Output
Original array:
[[ 1 2 -3]
[ 4 -5 -6]]
Resulting array:
[[1 2 0]
[4 0 0]]
Sample Program 14.5: Write a program to remove all the columns containing non-
numeric values.
Solution Steps:
649
1. Use np.isnan method along with any method to locate the columns with non numeric
values. The n.nan method generates a Boolean index array.
import numpy as np # Import Numpy module
# Create 3X3 2-D Numpy array with non-numeric data
n_arr = np.array([[10, 22, 10, 23],
[41, 52, 25, np.nan],
[20, np.nan, 41, 31]])
print("Given array:")
print(n_arr)
Output
Given array:
[[10. 22. 10. 23.]
[41. 52. 25. nan]
[20. nan 41. 31.]]
Sample Program 14.6: Write a program to get row indices of all the rows of a matrix
where rows contain a value greater than a given value.
Solution Steps:
1. Use numpy.where method and numpy.any method to identify the rows with values
grater than the specified value.
import numpy #Import NumPy Module
# Original array
arr = numpy.array([[1, 2, 3, 4, 5],
[7, -3, 20, 4, 5],
[3, 2, 4, -4, 1],
[9, 7, 34, 6, 0]
])
X = 6 # Specified value
print("Original Array:\n", arr)
# finding out the row numbers
output = numpy.where(numpy.any(arr > X, axis = 1))
650
print("Result:\n", output)
Output
Original Array:
[[ 1 2 3 4 5]
[ 7 -3 20 4 5]
[ 3 2 4 -4 1]
[ 9 7 34 6 0]]
Result:
(array([1, 3], dtype=int64),)
Sample Program 14.7: Write a program to create an array of normally distributed random
numbers
Solution Steps:
1. Import numpy.matlib to access randn method which generates the Normally
distributed random numbers.
import numpy as np #Import NumPy module
import numpy.matlib #Import numpy.matlib module
Sample Program 14.8: Write a program to get the first k smallest values from a 2D array.
Solution Steps:
1. Flatten the 2D array using ravel method
2. Use sort method to sort the flattened array
3. Print the first k values.
import numpy as np #Import NumPy module
mat1=np.array([[1,5,2,3],[7,2,0,3]]) #2D array
arr1=np.ravel(mat1)#Flatten the matrix
arr1=np.sort(arr1) #Sort the flattened array
k=3
print("Original matrix:\n",mat1)
print("The first k smallest values:",arr1[:k])#Print the first k values
651
Output
Original matrix:
[[1 5 2 3]
[7 2 0 3]]
The first k smallest values: [0 1 2]
Chapter Summary
652
14. The syntax of the slicing is [start: end: step], where start, end and step are
optional and have default values, 0, size of the concerned axis and 1, respectively.
15. We can use lists of indices for accessing multiple non-contiguous elements from
a NumPy array.
16. Similar to the list indexing, we can use a NumPy array to access multiple
elements from an array.
17. The Boolean Array indexing is used to return elements corresponding to true
entry in Boolean indexing array.
18. NumPy operations can be grouped as elementwise operations, matrix and linear
algebra operations, basic reductions, broadcasting, array shape manipulation,
and sorting data.
653
(b) It can have only three dimensions
(c) It is stored in a contiguous memory
(d) Indexing can be used to access individual elements
654
(a) eye
(b) empty
(c) full
(d) None of the above
11. Which of the following is not true about the array indexing?
(a) Indexing starts with 0
(b) Indexing starts with 1
(c) -1 can be used in indexing
(d) The indices can be given either within a square bracket separated by
commas or in separate square brackets
12. Which of the following is true about the slicing for NumPy arrays?
(a) Syntax of slicing is [start: end: step]
(b) In slicing, start, end and step are optional
(c) The default value of start is 0
(d) all of the above
15. Which of the following can be used to change the shape of an array?
(a) reshape
(b) ravel
(c) resize
(d) All of the above
655
a = np.arange(6)
print(a[2:-2])
(a) [2 3]
(b) [1 2]
(c) [2]
(d) None of the above
import numpy as np
a = np.array([[1, 2], [3, 4]])
print(a.ndim)
(a) 2
(b) 2,2
(c) 1
(b) None of the above
656
(a) [ 4 10 18]
(b) 32
(c) 90
(d) None of the above
20. Which of the following function is used to find the index of the maximum
element in a NumPy array?
(a) argmax
(b) max
(c) amax
(d) None of the above
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.vstack((a, b))
print(c)
657
23. What is the output of the following code?
import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.concatenate((a, b))
print(c)
24. Which of the following is used to find the inverse of a matrix, m, in NumPy?
(a) np.linalg.inv(m)
(b) m.inverse()
(c) m.inv()
(d) inv(m)
(a) 6
(b) [2,3]
(c) [3,2]
(d) None of the above
Review Questions
658
d. NumPy is written in C programming language.
e. NumPy array index starts with 1.
f. Each dimension of an array is called axis.
g. C- contiguous and F-contiguous are two approaches to store data in a
NumPy array.
h. The shape of an array can be changed by using metadata without changing
the actual array data.
i. The arange method creates a multi-dimensional array from a range.
j. The empty method creates an array of a specified shape with garbage
values of its elements based on the state of the memory.
k. The eye method creates a diagonal array of a specified shape.
l. The linspace method creates a 1D array of evenly spaced numbers for a
given interval and the number of items.
m. The default value of number of elements in linspace is 50.
n. The random.randint(a, b, sh=1) method returns an array of random
integers between a (included) and b (included).
o. NumPy arrays can store and process complex numbers.
p. The index value -1 is an invalid value for an axis.
q. We cannot use slicing in NumPy to get a sub-array.
r. For accessing noncontiguous multiple elements in an array, we can use lists
of indices for each axis.
s. Ellipsis (…) can be used for indexing.
t. NumPy permits Boolean arrays for indexing.
u. The numpy.argmax(a, axis=None) method finds the maximum element in
the specified axis.
659
v. NumPy uses broadcasting to perform elementwise operations on two
arrays of different shapes.
w. Structured NumPy Arrays can be used to store and process compound and
heterogeneous data.
Programming Assignments
3. Write a program to generate 5x5 matrix of random integers between 0 and 100.
6. Write a program to create a 5x2 integer array of random numbers where the
difference between any two column elements is more than 5.
660
14. Write a program to replace all the values in an array greater then n by m.
16. Write a program to create an array of random numbers of size NxM between 10
and 100.
661
662
Chapter 15
Introduction to Matplotlib
Learning outcomes
Visualization of data helps to determine patterns in the data and is an important tool in
engineering and scientific computations and research. Matplotlib is a widely used cross-
platform data visualization, and graphical plotting library of the Python programming
language. It can be used for creating static, animated, and interactive visualizations of data.
Typically, Matplotlib is used along with NumPy, SciPy, and many other packages for
creating a variety of plots, such as Line Plot, Bar Plot, Scatter Plot, Histogram, etc. It also
provides functions to create variety of 3D plots. This chapter briefly introduces the basic
functionalities of Matplotlib. The Matplotlib module can be installed using the pip install
Matplotlib command. Before using it, we have to import it in our program using any one
of the following syntaxes: from matplotlib import pyplot as plt or import
matplotlib.pyplot as plt. Most of the Methods of the Matplotlib module has a number of
parameters to customize the methods. However, in this brief introduction to the Matpotlib
module, we will only discuss the commonly used parameters of the commonly used
methods. For other methods and parameters, we encourage readers to see the online
documentation of the module. Figure 15.1 shows the common components of a plot.
663
2. Create the plot using a built-in plotting function, such as plot(), scatter(),
histogram(), bar(), contour3D(), plot_surface(), etc, from the Matplotlib module. The
Matplotlib module has a big list of plotting functions for different types of plots. We
can plot more than one series of data in a single plot by either calling plot functions
more than once or giving more than one data set to the same function.
3. Customize the plot by creating labels for various axes, creating the plot title and sub-
title, creating a grid, creating legends, etc. The Matplotlib module has many buit-in
functions, such as xlabel(), ylabel(), title(), etc., to meet the specific customization
requirement. There are more than 100 parameters through which we can achieve the
required appearance of a plot.
4. Show the plot. Plots are created in the memory and finally we use the show() method
to show it on the screen. We can also save the plot into different formats in a file for
future uses.
664
Example 15.1(a)
665
15.2 The plot Method
The plot() method, which creates a line plot, is one of the most widely used methods
in the Matplotlib module. It has the following syntax:
where x and x2 are x-coordinate values, y and y1 are y coordinate values, fmt and fmt2 are
formatting strings for plots, and kwargs are optional keyword-value parameters. The
formatting string has the following syntax:
fmt = '[marker][line][color]'
where, marker is a character that represents a symbol, such as a triangle, square, circles,
etc., to be plotted at data points, see table 15.1 for marker symbols; line is a set of characters
used to create different line styles, such as solid line, dash line, etc. and color is a character
that creates lines of different colors, see table 15.2 for different line styles and line colors.
The default color of a Matplotlib plot is blue and line type is solid line. By default, no morker
for the data points is used. For example, fmt= 'v-.r' will create a plot with a red-colored
dash-dot line with downward triangle markers at each data point. Example 15.2(a)
illustrates the above.
666
Table 15.2: Characters used as line style and color in the plot function
667
The plot() method is typically used to visualize functions of the form y = f(x), where,
x is a set of values of x-coordinates, in ascending order, and y is the corresponding y
coordinate values. We can plot more than one line plot in a single plot by providing more
than one set of x and y values. Either we can use a separate plot method for each set of data
or we can use a single plot method to plot different sets of data. We can set different
markers, line styles, and colors for a different set of data. Example 15.2(b) illustrates plots
of y=x2 and y=x2-10 for the values of x in the range of -5 to 5 with a step size of 1.
668
plt.show() # Show the plot
The code below will produce the same result as the above code
import matplotlib.pyplot as plt #Import mappaltlib module
import numpy as np #Import numpy module
x = np.arange(-5,6) #x axis values
y = x*x #The corresponding y axis values
y1=y-10
plt.plot(x, y1,'o-g') #Plot the first set of data
plt.plot(x,y, 'x--b') #Plot the second set of data
plt.title('Plots of y=x^2 and y=x^2-10')#Giving a title to the graph
plt.show() # Show the plot
Output
669
15.3 Creating sub-plots
We can create a number of subplots in a figure and each subplot can have different
types of plots and different types of appearances with the subplots () method, which has
the following syntax:
where nrows and ncols are integers and control the numer of rows and the number of
columns , respectively, of subplots. The default values of these parameters is 1. Other
parameters are used to control the properties of subplots. The function returns handle of
the figure as fig and an NumPy array, ax, of all the axes of the subplots. For subplots
consisting of multi-rows and multiple-columns, the array will be 2D. Each subplot will have
an independent plot. The figsize parameter can be used to control the size of the figure. We
can use the fig.tight_layout() method to automatically maintains the proper spaces between
subplots. However, we can use the plt.subplots_adjust(left=0.1,bottom=0.1,
right=0.9,top=0.9,wspace=0.3,hspace=0.4) method to customise the spaces between
Matplotlib subplots. The parameters wspace and hspace specify the gaps between the
columns and rows of subplots, respectively. The values of these parameters are the fraction
of the average width and the average height of subplots, respectively. And the parameters
left, right, top and bottom parameters specify four sides of the subplots’ positions. The
values left and right are the fractions of the figure width and values top and bottom are the
fractions of the figure height. Example 15.3 illustrates the subplots() method.
670
axs[1][0].set_title('exp') #Title of the first sub-plot
axs[1][0].set_xlabel('x')
axs[1][0].set_ylabel('y')
axs[1][1].plot(x,np.log10(x)) #Create the fourth sub-plot
axs[1][1].set_title('log') #Title of the first sub-plot
axs[1][1].set_xlabel('x')
axs[1][1].set_ylabel('y')
#fig.tight_layout() #Automatically adjust the gaps among subpots
plt.subplots_adjust(left=0.1,bottom=0.1,
right=0.9,top=0.9,wspace=0.3,hspace=0.4)
plt.show()
Output
671
15.4 Customizing a Plot
We can customise a plot by adding additional details as as axes labels, the plot title
and sub-title, creating grids, creating axes ticks, etc. using various buit-in methods. We will
describe commonly used methods in this section.
We can label x-axis by the xlable() method, y-axis by the ylabel() method. These
method have the following syntaxes:
where, xlabel and ylabel are strings use to label the axes. The parameter loc controls the
location of the label and it can take the flowing values: 'left', 'center', 'right'. The default is
'center'.
If we are using axes object to create a sub-plot, we can use the following functions
for axes labelling:
We can give a title and a sub-title to a plot by the sutitle() and title () methods. The title()
method has the following syntax:
where title is a string, which is used as the title of the plot. The parameter loc controls the
horizontal location of the title and it can take any of the following values: 'left', 'center',
'right'. The default is 'center'. The parameter y controls the vertical location of the title. The
value y=0 is the bottom and y=1 is the top of the plot. The values of y are on the figure
coordinate system, which has values in the range of 0 and 1, for both x and y axes.
If we are using axes object to create a sub-plot, we can use the following functions
to insert a title:
672
axes.set_title(label, fontdict=None, loc=None, pad=None, *, y=None, **kwargs)
We can add a super title by the suptitle () method which has the following syntax:
matplotlib.pyplot.suptitle(title, **kwargs)
where title is a string storing the main title of the plot. The location of the main title is
controlled through the parameters x and y, which has default values of 0.5 and 0.98 in the
figure coordinates. Additionally, we can use the ha parameter for the horizontal allignment
and the va parameter for the vertical alignment. The ha parameter can be set to 'center',
'left', or 'right' and the default is 'center'. Similarly, the va parameter can be set to 'top',
'center', 'bottom', 'baseline' and the default is 'top'.
We can use fig object returned by the subplots() method to give a super title to a plot, which
has the following syntax:
fig.suptitle(t, **kwargs)
Example 15.4(a) illustrates how to label axes and give a title and a super title to a
plot. See example 15.3(b) above which uses axes object and figure object to label axes and to
give title to each plot and to give super title to the plot.
673
15.4.2 Adding a Grid to a Plot
We can add a grid to a plot using the grid () method, which has the following syntax:
where the b parameter can take True, False or None. To show a grig, we set b=True. The
which parameter takes any value from 'major', 'minor',and 'both'. The value 'both' will
show both major and minor grids. The axis parameter takes any value from 'both', 'x', and
'y'. The value 'both' will create grids for both x and y axes. We can also set the color, linestyle
and line width of grid lines through the respective parameters. The default values are
color='r', linestyle='-', and linewidth=2.
Similarly, we can use the grid () method of the axis object to set gids for sub-plots,
which has the following syntax:
674
axes.grid(self, b=None, which='major', axis='both', **kwargs)
675
15.4.3 Adding ticks and tick-labels
Ticks are values shown on an axis of a plot. They a very helpful in reading the plot.
Matplotpli automatically puts ticks on various axis. Matplotlib's default ticks and its
formatting are generally acceptable in most situations. However, we can customise ticks
and tick-labels with the following methods:
axes.set_xticks(ticks, *, minor=False
axes.set_xticklabels(labels, *, fontdict=None, minor=False, **kwargs)
axes.set_yticks(ticks, *, minor=False
axes.set_yticklabels(labels, *, fontdict=None, minor=False, **kwargs)
where, ticks is a list of axis values where ticks lables will be shown, labels is a list of values
which will be shown as ticks. Example 15.3(c) illustrates customidation of ticks.
676
Example 15.3(c): Customizing axis ticks
677
15.3.4 Adding Legends
The legend in a plot is a tool to describe the meaning of various lines and symbols
used in the plot. It is specifically very useful in a plot that consists of many series of data.
Legends are used to describe various data series. We can use the legend() method of
matplotlib to add a legend in a plot, which has the following syntax:
where legend1, legend2, …, legendN are the labels of various legends, loc is the location of
the legend on the plot. It can take any one of the following values: 'best', 'upper right', 'upper
left', 'lower left', 'lower right', 'right', 'center left', 'center right', 'lower center', and 'upper
center', and 'center'. The 'best' option places the legend at the location, among the other nine
locations, with the minimum overlap with plots. The location of the legend can also be
decided by the parameter bbox_to_anchor, where x=0 indicates the left border, x=1
indicates the right border, y=0 indicates the bottom border and y=1 indicates the top border
of the plot.
We can also use the legend() method of the axes object to create legends in subplots,
which has the following syntax:
678
axs[0][1].plot(x,np.sin(x))
axs[0][1].set_title('Legend lower right')
axs[0][1].grid(True)
axs[0][1].plot(x,np.cos(x))
axs[0][1].legend(['square','root'], loc='lower right')
axs[1][0].plot(x,np.sin(x))
axs[1][0].set_title('Legend lower left')
axs[1][0].grid(True)
axs[1][0].plot(x,np.cos(x))
axs[1][0].legend(['square','root'], loc='lower left')
axs[1][1].plot(x,np.sin(x))
axs[1][1].set_title('Legend upper left')
axs[1][1].grid(True)
axs[1][1].plot(x,np.cos(x))
axs[1][1].legend(['square','root'], loc='upper left')
plt.subplots_adjust(left=0.1,bottom=0.1,
right=0.9,top=0.9,wspace=0.3,hspace=0.4)
plt.show()
Output
679
15.3.5 Twin axis
Sometimes, we plot more than one curves in a plot which has different units or
scales. We use the twin axis concept to include additional axis for such plots. We use the
method Axes.twinx() to create the second y-axis that shares the same x-axis with the origil
y-axis. Similarly, we can create the second x-axis by using the Axes.twiny() method.
Example 15.3(e) illustrates the twin-axis concept.
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(0.01, np.pi*2, 0.001)
data1 = np.exp(t)
data2 = np.cos(0.4 * np.pi * t)
data3 = np.sin(0.4 * np.pi * t)
680
fig, ax1 = plt.subplots() #Create axis and figure
ax1.set_xlabel('time (s)')
ax1.set_ylabel('exp', color = 'r') #Customize the first y-axis
ax1.plot(t, data1, color = 'r') #Plot the first curve
ax1.tick_params(axis ='y', labelcolor = 'r')
ax2 = ax1.twinx() #Create a second y axis which will share the same x-
axis
ax2.set_ylabel('cos', color = 'g') #Customize the second y-axis
ax2.plot(t, data2, color = 'g') #Plot the second curve
ax2.tick_params(axis ='y', labelcolor = 'g')
fig.legend(labels = ('exp','cos'),loc='lower right')#Add legend
fig.suptitle('Twin axis', fontweight ="bold")
fig.tight_layout() #Automatically adjust the gaps among sub-plots
plt.show()
Output
681
15.4 Bar Charts
A bar chart is used to present categorical data with rectangular bars with heights or
lengths proportional to the values of the data. Bar charts can be simple, grouped or stacked
charts. In a grouped bar chart, rectangles are grouped together, whereas in a stacked bar
chart, rectangles are stacked one over other. The bars can be plotted vertically or
horizontally. Vertical bar charts are created with the bar() method and horizontal bar charts
are created using the barh() method. The syntaxes of these two methods are as given below:
where x is the location of bars on the x-axis, height is the value of the data, width is the
width of bars (default is 0.8), bottom is the y-value of the bottom of the boars (default is 0)
and align is the alignment of the bar at x values. If x is non-numeric, bars are evenly
distributed along the x-axis.
where y is the location of bars on the y-axis, width is the value of the data, height is the
height of bars (default is 0.8), left is the x-value of the left of the boars (default is 0) and align
is the alignment of the bar at y values. If y is non-numeric, bars are evenly distributed along
the y-axis.
Example 15.4(a) illustrates various types of vertical bar charts and figure 15.4(b)
illustrates various types of horizontal bar charts.
We can create a polar bar plot in Matplotlib by setting the polar property of the axes
object to true, with the following syntax:
ax = matplotlib.pyplot.axes(polar=True)
import numpy as np
import matplotlib.pyplot as plt
fig,axs = plt.subplots(1,3)
682
# creating the dataset
x=np.array([1,2,3,4])
course_names = ['C','C++','Java','Python']
no_students = np.array([15,40,25,50])
no_jobs =np.array([14,35,20,45])
boys=np.array([10,30,20,25])
girls=no_students-boys
#Creating a column bar plot
axs[0].bar(course_names, no_students, color ='red',width = 0.25)
axs[0].set_xlabel("Courses offered")
axs[0].set_ylabel("No. of students enrolled")
axs[0].set_title("Simple bar chart")
axs[0].grid(True)
#Creating a column grouped bar plot
axs[1].bar(x, no_students, color ='red',width = 0.25)
axs[1].bar(x+.25, no_jobs, color ='green',width = 0.25)
axs[1].set_xlabel("Courses offered")
axs[1].set_ylabel("No. of students enrolled and placed")
axs[1].set_title("Grouped bar chart")
axs[1].set_xticks(x) #Axis tick values
axs[1].set_xticklabels(course_names) #Axis tick labels
axs[1].legend(['Registred','Placed'])
#Creating a column stacked bar plot
axs[2].bar(x, boys, color ='red',width = 0.25)
axs[2].bar(x, girls, color ='green', bottom=boys, width = 0.25)
axs[2].set_xlabel("Courses offered")
axs[2].set_ylabel("No. of boys and girls enrolled")
axs[2].set_title("Stacked bar chart")
axs[2].set_xticks(x) #Axis tick values
axs[2].set_xticklabels(course_names) #Axis tick labels
axs[2].legend(['Boys','girls'])
fig.suptitle("Different types of column bar charts")
fig.tight_layout()
plt.show()
Output
683
Example 15.4(b): Various types of horizontal bar charts
import numpy as np
import matplotlib.pyplot as plt
fig,axs = plt.subplots(1,3)
# creating the dataset
x=np.array([1,2,3,4])
course_names = ['C','C++','Java','Python']
no_students = np.array([15,40,25,50])
no_jobs =np.array([14,35,20,45])
boys=np.array([10,30,20,25])
girls=no_students-boys
#Creating a horizontal bar plot
axs[0].barh(course_names, no_students, color ='red',height = 0.25)
axs[0].set_ylabel("Courses offered")
axs[0].set_xlabel("No. of students enrolled")
axs[0].set_title("Simple bar chart")
axs[0].grid(True)
#Creating a horizontal grouped bar plot
axs[1].barh(x, no_students, color ='red',height = 0.25)
axs[1].barh(x+.25, no_jobs, color ='green',height = 0.25)
684
axs[1].set_ylabel("Courses offered")
axs[1].set_xlabel("No. of students enrolled and placed")
axs[1].set_title("Grouped bar chart")
axs[1].set_yticks(x) #Axis tick values
axs[1].set_yticklabels(course_names) #Axis tick labels
axs[1].legend(['Registred','Placed'])
#Creating a horizontal stacked bar plot
axs[2].barh(x, boys, color ='red',height = 0.25)
axs[2].barh(x, girls, color ='green', left=boys, height = 0.25)
axs[2].set_ylabel("Courses offered")
axs[2].set_xlabel("No. of boys and girls enrolled")
axs[2].set_title("Stacked bar chart")
axs[2].set_yticks(x) #Axis tick values
axs[2].set_yticklabels(course_names) #Axis tick labels
axs[2].legend(['Boys','girls'])
fig.suptitle("Different types of horizontal bar charts")
fig.tight_layout()
plt.show()
Output
import numpy as np
import matplotlib.pyplot as plt
685
ax = plt.axes(polar=True) #Set polar coordinate system
N = 10 #Number of bars
theta = np.arange(0.0, 2 * np.pi, 2 * np.pi / N)
radii = np.random.randint(0,10,size=10)#Random radii of bars
width = np.pi / 4 * np.random.rand(N) #Random widht of bars
bars = plt.bar(theta, radii, width=width, bottom=0.0)#Bar plot
#Setting color of each bar based on the radii
for r,bar in zip(radii, bars):
bar.set_facecolor(plt.cm.jet(r/10.))
#Label axes
ax.set_xticklabels(['0','45','90','135','180','225','270'])
ax.set_yticklabels([1,2,3,4,5,6,7,8,9])
plt.show()# Show chart
Output
686
15.6 Histogram Plots
The important parameters are x, which contains the data, and bins, which sets the
number of bins (default is 10) to be created for the histogram plot. The function returns
frequency of each bin, which can be used to create a line plot over the histogram. For the
other parameters, please see the online documentations. Example 15.5(a) illustrate the
creation of a histogram plot. The hist() method also returns the individual patches of a
histogram, which we can use to assign different colors to different patched. Example 15.5(b)
illustrates the creation of a colored histogram.
687
Example 15.5(b): A colored histogram plot
A pie chart is a pictorial represention of data in the form of slices of a circle. The sizes
of slices are in proportion to the values of data. We create a pie chart in Matplotlib using the
pie() method, which has the following syntax:
689
where x is the data to be plotted. Other parameters are used to control the appearance of a
plot. For details about the other parameters, please refer online documentations of the
matplolib module. Example 15.6 illustrates different types of pie charts.
import numpy as np
import matplotlib.pyplot as plt
fig,axs = plt.subplots(1,2)
#Create data
course_names = ['C','C++','Java','Python']
no_students = np.array([15,40,25,50])
explode = (0, 0.1, 0, 0) #Explode the 2nd slice
color=['red','green','blue','cyan'] #Define colors
axs[0].pie(no_students,labels=course_names) #Default pie chart
axs[0].set_title("Default Pie chart")
#Customised pie chart
axs[1].pie(no_students,labels=course_names, explode=explode,
colors=color)
axs[1].set_title("Exploded Pie chart")
fig.suptitle("Different types of Pie charts")
plt.show()
Output
690
15.8 Scatter Plots
A scatter plot plots relationship between two variables in the form of dots in a
castesian coordinate system. This is typically used to observe and visualise patterns in large
number of data. In this chart, we can have more than one value of the dependent variable
for the same value of the independent variable. We use scatter method to plot a scatter plot
in Matplotlib, which has the following syntax:
where x and y are the pair of data to be plotted. We can control the size and color of dots
through the s and c parameters respectively. We can control transparency of colors by the
alph parameter. Other parameters are used to customise the appearance of a scatter plot.
See online documentation for their details. Example 15.7 illustres different types of scatter
plots.
691
# Show the plot
plt.show()
Output
692
functions are used to create curve contours and filled contours plots, respectively, which
have the following syntaxes:
where X and Y are meshgrid points and Z is the corresponding values at each grid point.
The parameter levels decides the number of contour curves in a contour plot or the number
of color shades used to plot a filled contour plot. Example 15.8 illustrates the creation of a
curve contour plot and a filled contour plot.
import numpy as np
import matplotlib.pyplot as plt
xlist = np.linspace(-3.0, 3.0, 100)
ylist = np.linspace(-3.0, 3.0, 100)
#Create a meshgrid from x and y values
X, Y = np.meshgrid(xlist, ylist)
Z = np.sqrt(X**2 + Y**2) #Calculate Z values at each mesh grid
fig,ax=plt.subplots(1,2)
#Create a filled contour plot
cp1 = ax[0].contourf(X, Y, Z, levels=10)
fig.colorbar(cp1, ax=ax[0]) # Add a colorbar to a plot
ax[0].set_title('Filled Contours Plot')
ax[0].set_xlabel('x')
ax[0].set_ylabel('y')
#Create a curve contour plot
cp2 = ax[1].contour(X, Y, Z, levels=10)
fig.colorbar(cp2, ax=ax[1]) # Add a colorbar to a plot
ax[1].set_title('Curve Contours Plot')
ax[1].set_xlabel('x')
ax[1].set_ylabel('y')
fig.tight_layout() #Automatically adjust the spaces between sub-plots
plt.show()
Output
693
15.10 Box Plots
A box plot, also called whisker plot, visually summarises the vital information, such
as the minimum, first quartile, median, third quartile, and maximum, of a data set. In a box
plot, a box is created from the first quartile to the third quartile and the median is marked
by a line in the box. The box is connected with the minimum and maximum with lines. The
boxplot method has the following syntax:
where x is an array or sequence of vectors. For each vector, the method creates on box plot.
Through other parameters, we can show meanlines and customise the plot as per our
requirements. For other parameters, please refer online documentations. Example 15.9
illustrates box plots.
694
Example 15.9: Box plots
695
15.11 Violin Plots
Violin plots are similar to box plots and it plots the probability density of the data at
different values. Primarly, it is used to visualize the distribution of variables. We use the
violinplot() method to generate a violin plot. It has the following syntax:
Where dataset is an array of vectors. For each vector, a separate violin plot is created. Other
parameters are used to customize a violin plot. See online documentation for more details
about other parameters. Example 15.10 illustrates voiline plots.
696
Example 15.10: Violin plots
Output
697
15.12 Quiver Plots
A quiver plot is used to visualize dynamic processes such as particle flow, electrical
potential, stress gradients, etc. It shows the dynamic quantities with the help of directional
vectors. Vectors have both magnitude and direction. Vectors are plotted as arrows in a
quiver plot. The quiver () method is used to create a quiver plot. It has the following syntax:
where X, Y define the arrow locations, U, V defines the arrow directions, and C optionally
sets the color of arrows. Other parameters can be used to customize the plot as per
requirement. Please, see the online documentation for the same. Example 15.11 illustrates a
quiver plot.
698
x,y = np.meshgrid(np.linspace(-np.pi,np.pi,10), np.linspace(-
np.pi,np.pi,10))
#x and y components of vectors
u = np.sin(y);
v = np.cos(x);
fig, ax = plt.subplots(1,2)
ax[0].quiver(x,y,u,v)
ax[0].set_title("Default quiver plot")
r = np.random.rand(100) #Generate random numbers
m=np.max(r) #Get the maximum
c=plt.cm.jet(r/m)#Generate color from the random numbers
ax[1].quiver(x,y,u,v, color=c)
ax[1].set_title("Colored quiver plot")
fig.tight_layout()
plt.show()
Output
699
15.13 3D Plots
Though primarly designed for 2D plots, the Matplotlib module can be used to create
different types of 3D plots, such as 3D curve plots, 3D scatter plots, 3D surface plots, 3D
mesh plots, etc., by creating 3D Axes. A 3D axes can be created by passing the parameter
projection="3d" to Axes.add_subplot(projection="3d") method. Prior to Matplotlib 3.2.0, to
create 3D plots, we need to explicitly import the mpl_toolkits.mplot3d module but now it
is not required.
Once a 3D axes has been created, we can create a simple 3D line plot by using the
plot3D () method or the plot () method, with the following syntaxes:
where x,y and z are the 1D arrays containing the coordinates of points. Other positional and
keyword parameters are similar to the 2D plot() method. The zdir parameter sets the
orientation of the plot. Its possible values are 'x', 'y' and 'z', and default is 'z'. Example
15.12(a) illustrates simple 3D line plots.
We can create 3D scatter plot with the scatter3D method or scatter() method, with
the following syntaxes:
where x,y and z are the 1D arrays containing the coordinates of points. Other positional and
keyword parameters are similar to the 2D scatter() method. The zdir parameter sets the
orientation of the plot. Its possible values are 'x', 'y' and 'z', and default is 'z'. Example
15.12(b) illustrates simple 3D scatter plots.
import numpy as np
import matplotlib.pyplot as plt
#Create a spiral curve data
z = np.linspace(0, 1, 100)
x = z * np.sin(20 * z)
700
y = z * np.cos(20 * z)
fig = plt.figure() #Create a figure
#Add sub-plots to a figure and create a 3D axes
ax = fig.add_subplot(1,2,1, projection='3d')
ax.plot3D(x, y, z)
ax.set_title('Default 3D line plot')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
#Create another 3D axes
ax1 = fig.add_subplot(1,2,2, projection='3d')
#Plot a customised 3D line plot
ax1.plot3D(x, y, z, 'g--', zdir='x')
ax1.set_title('Customised 3D line plot')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_zlabel('z')
plt.show()
Output
701
Example 15.12(b): 3D scatter plots
import numpy as np
import matplotlib.pyplot as plt
#Create a spiral curve data
z = np.linspace(0, 1, 100)
x = z * np.sin(20 * z)
y = z * np.cos(20 * z)
fig = plt.figure() #Create a figure
#Add sub-plots to a figure and create a 3D axes
ax = fig.add_subplot(1,2,1, projection='3d')
ax.scatter3D(x, y, z)
ax.set_title('Default 3D scatter plot')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
#Create another 3D axes
ax1 = fig.add_subplot(1,2,2, projection='3d')
#Plot a customised 3D scatter plot
ax1.scatter(x, y, z,c='red')
ax1.set_title('Customised 3D scatter plot')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_zlabel('z')
plt.show()
Output
702
15.14 3D Pontour Plots
We can create 3D contour plots, both curve contour and filled contour plots, using
the contour() and contourf() methods (contour3D() and contourf3D() methods) of Axes3D
class, respectively. These methods have the following syntaxes:
where X, Y is a meshgrid points and Z is the values of the function at various grid points.
X, Y and Z are 2D arrays of the same size. Other parameters are used to customise the plots.
Please see the online documentation for their details. Example 15.13 illustrates 3D curve
contour and filled contour plots.
703
Example 15.13: 3D contour plots
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm #Import color maps
#Create a dataset for a 3D contour plot
def f(x, y):
return np.sin(np.sqrt(x ** 2 + y ** 2))
x1 = np.linspace(-6, 6, 30)
y1 = np.linspace(-6, 6, 30)
x,y = np.meshgrid(x1, y1) #Create meshgrid
z = f(x, y) #Calculate z value for each grid point
704
15.15 Wireframe and Surface Plots
We can create a wireframe plot and a surface plot of 3D points using the methods
plot_wireframe() and plot_surface() methods, respectively. These plots help in visualising
the topology of a surface. A surface plot is like a wireframe plot, but each face of the
wireframe is a filled polygon. Following are the syntaxes of these functions:
where X, Y, and Z are 2D arrays of the same size. X and Y are rectangular grid of points and
Z contains the z values at each grid points. Other parameters are used to customize the
plots. See the online documentation for more details of these parameters. Example 15.14
illustrates wireframe and surface plots.
705
Example 15.14: Wireframe and surface plots
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
#Create a dataset for a 3D contour plot
x1 = np.linspace(0,2*np.pi,20)
y1 = np.linspace(0,2*np.pi,20)
x,y = np.meshgrid(x1, y1)
z = np.sin(x)*np.cos(y)
706
15.16 Animation using Matplotlib
For more vivid representation of data, Matplotlib provides facilities to generate
animations of various plots using animation module. Animation of a Matplotlib plot is
possible as elements of a plot are stored as dynamic and editable items, called artist. For
example, the artist in a line plot is Line2D, which is nothing but collection of all the end poit
coordinates of all the line segment, line type, line color, etc. An artist can be updated by
updating the data behind the artist using the corresonidng set method. For example, we can
use set_data method to update the coordinate points. The animation module uses two
classes to create animation: FuncAnimation and ArtistAnimation.
FuncAnimation: In FuncAnimation, we start by generating the data for the first plot and
then update the data for the next frame by calling a function which updates the data. The
update function calculates the data for the next frame and uses the set methods of various
plots to update the data.
707
ArtistAnimation: In ArtistAnimation, the data for all the frames are generated before the
start of animation and is stored in an interable. The ArtistAnimation method uses these data
to create animation.
1. Create the initial plot including all the artists (parameters) required for the animation.
Also get the handle of the plot.
2. Define an animation function that will calculate the values of the artists for the next
frame.
3. Call the constructor of the FuncAnimation object and pass the plot handle, animation
function and other parameters.
4. Either show the animation by using pyplot.show method or save the animation by using
the animation. Animation.save method.
Example 15.15(a) uses the above method to show the animation of trajectory of a
projectile.
708
ax.set(xlim=[0, 45], ylim=[-1, 12], xlabel='Time [s]', ylabel='Z [m]')
def update(frame):
t=tf[frame]
x.append(t*v*np.cos(theta)) #Next x-coordinate
y.append(v*np.sin(theta)*t-0.5*9.81*t*t) #Next y coordinate
data = np.stack([x, y]).T
scat.set_offsets(data) #Update the plot data
return (scat)
#Create animation
ani = animation.FuncAnimation(fig=fig, func=update, frames=40,
interval=300, repeat = False)
plt.show() #Show animation
Output
709
15.16.2 Steps to create animation plot using ArtistAnimation:
ArtistAnimation can be used only for plots that returns iteratble artists, such as bar charts,
line plot, etc. It cannot be used to the scatter plot as the returned path collection is not
iterable. Following are the steps to create animation using FuncAnimation:
Example 15.15(b) uses the above method to show the animation of trajectory of a projectile
using a line plot.
#Create animation
ani = animation.ArtistAnimation(fig=fig, artists=artists, interval=30,
repeat = True)
710
plt.show() #Show animation
ani.save(filename="d:/example.gif", writer="pillow") #Save animation
Output
Sample Program 15.1: Write a program to generate 10000 normally distributed random
numbers and plot their histogram with 100 bins
Solution Steps:
1. Import numpy, numpy.random and Matplotlib modules
2. Generate 10000 normally distributed random numbers using numpy.random.randn
method with default parameters.
3. Plot a histogram using hist method
711
import numpy as np #Import NumPy module
import numpy.random #Import random number generators
import matplotlib.pyplot as plt #Import Matplotlib module
r=numpy.random.randn(10000) #Generate random numbers
plt.hist(r,100) #Plot the histogram
plt.show()#Show the plot
Output
Sample Program 15.2: Write a program to plot the projectile of a ball thrown at 45 degree
at the velocity 20 m/s.
Solution Steps:
1. Calculate x and y coordinates of some points on the projectile path using Newton’s
second law of motion
2. Use a scatter plot to plot the calculated points
import numpy as np #Import NumPy module
712
import matplotlib.pyplot as plt #Import Matplotlib module
theta =45 #Throw angle in degree
theta = theta*np.pi/180 #Convert the angle into radian
v= 20 #Throw velocity
tof= 2*v*np.sin(theta)/9.81 #Calculate the time of flight
t=np.linspace(0,tof,100) #Generate time series
x=t*v*np.cos(theta) #Calculate x co-ordinate of the projectile
y=v*np.sin(theta)*t-0.5*9.81*t*t #Calculate y- co-ordinate
plt.scatter(x,y)#Create a scatter plot
plt.show() #Show the plot
Output
Sample Program 15.3: Write a program to create a scatter plot of random points with
random coloured balls of random sizes
Solution Steps:
1. Generate random x and y coordinates for various points
2. Generate random sizes for various points
3. Generate random colours for various points
713
4. Use scatter plot to plot these points.
import matplotlib.pyplot as plt #Import Matplotlib
import numpy.random #Import numpy.random
x = numpy.random.randint(0,100,10) #x-coordinates
y = numpy.random.randint(0,100,10) #y-coordinates
points_size = numpy.random.randint(0,1000,10) #Point sizes
c = numpy.random.randint(0,100,10) #Color of points
plt.scatter(x,y,s=points_size,c=c, cmap='viridis')
plt.title("Coloured Scatter Plot with random size of scatter points ",
fontsize=12)
plt.xlabel('x-axis',fontsize=12) #Add label to x-axis
plt.ylabel('y-axis',fontsize=12) #Add label to y-axis
plt.show()
Output
714
Sample Program 15.4: Write a program to animate the price variations of five stocks using
a vertical bar chart
Solution Steps:
1. Generate labels for various stocks
2. Generate initial height of bars showing the prices of the stocks
3. Assign colors to each stock bar
4. Use bar plot function to show the bars
5. Create a function to calculate the price variations in each frame and assign the new
prices to each bar
6. Use FuncAnimation function of animation module to animate the bar for each frame
import numpy as np #Import NumPy module
#import animation, pyplot module of Matplotlib
from matplotlib import animation as animation, pyplot as plt, cm
715
Chapter Summary
716
5. We can label x-axis by the xlable method, y-axis by the ylabel method.
6. We can give a title and a sub-title to a plot by the suptitle and title methods.
7. We can add a grid to a plot using the grid method.
8. We can use the legend method to add a legend in a plot.
9. Vertical bar charts are created with the bar method and horizontal bar charts are
created using the barh method.
10. We can create a polar bar plot in Matplotlib by setting the polar property of the
axes object to true.
11. We use the hist method to plot a histogram.
12. We create a pie chart using the pie method.
13. We use scatter method to plot a scatter plot.
14. The contour and contourf functions are used to create curve contours and filled
contours plots
15. The boxplot method create a boxplot, which visually summarises the vital
information, such as the minimum, first quartile, median, third quartile, and
maximum, of a data set.
16. We use the violinplot method to generate a violin plot.
17. The quiver method is used to create a quiver plot which is used to visualize
dynamic processes such as particle flow, electrical potential, stress gradients, etc.
18. Matplotlib module can be used to create different types of 3D plots, such as 3D
curve plots, 3D scatter plots, 3D surface plots, 3D mesh plots, etc., by creating 3D
Axes.
19. We can create a wireframe plot and a surface plot of 3D points using the methods
plot_wireframe() and plot_surface() methods, respectively.
717
Multiple Choice Questions
4. The savefig() function can save a Matplotlib plot in the following format?
(a) PNG
(b) PDF
(c) SVG
(d) All of the above.
5. Which of the following function can be used to set the limit of x-axis of a plot?
(a) xlim()
(b) xlimit()
(c) xtrim()
(d) All of the above.
718
7. Which of the following can be used to change the color of a Matplotlib plot?
(a) the color() function
(b) the hue() function
(c) By specifying the color parameter in the plot() function
(d) all of the above
8. Which of the following is the correct syntax for the formatting string?
(a) fmt = '[marker][line][color]'
(b) fmt = '[color] [marker][line]'
(c) fmt = '[marker] [color] [line]'
(d) None of the above.
10. Which of the following is used to automatically adjust the spaces among
subplots?
(a) tight_layout()
(b) auto_layout()
(c) subplots_adjust()
(d) None of the above
11. Which of the following function can be used to label x-axis in a plot?
(a) labelx()
(b) xlable()
(c) xtext()
(d) None of the above
12. Which of the following is used to give main title of a group of subplots?
(a) title()
(b) suptitle()
(c) maintitle()
(d) None of the above.
719
(a) grid()
(b) minor_grid()
(c) mgrid()
(d) None of the above.
15. Which of the following is used to describe the meaning of various lines and
symbols used in the plot?
(a) legend
(b) ticks
(c) title
(d) None of the above.
720
(b) setting polar property of the axis() method to true
(c) It is not possible to create a polar chart
(d) None of the above
24. Which of the following is used to visualise a dynamic process such as flow of
particles?
(a) quiver plot
(b) scatter plot
(d) Violin plot
(d) None of the above.
721
(b) 3D scatter plots
(c) 3D surface plots
(d) None of the above.
Review Questions
722
s. A quiver plot can visualize a dynamic process, such as particle flow.
Programming Assignments
2. For the following data, plot a line plot, scatter plot and vertical bar chart.
x 1 2 3 4 5 6 7 8 9 10 11
3.
y 31 11 10 17 21 16 26 21 28 34 33
x 1 2 3 4 5 6 7 8 9 10 11
y1 28 18 30 10 17 12 32 13 24 37 13
y2 24 40 16 27 13 11 26 19 32 13 19
5. For the data given in question 4, draw a scatter diagram for y1 and y2.
6. For the data given in question 4, plot a multi line plot with legend located at the
bottom right corner of the plot.
7. For the data given in question 4, create a box plot for y1 series.
8. Write a program to plot y=sin(x) for 0<=x<=4p with 0.2 step size.
10. The following is the montly unit sale data of a store for few items:
723
Total
Month Shampoo Toothpaste Soap Moisturiser
Units
1 1381 1654 1412 1288 5735
2 1336 1994 1325 1165 5820
3 1745 1868 1714 1145 6472
4 1205 1593 1402 1180 5380
5 1758 1150 1221 1782 5911
6 1171 1071 1166 1605 5013
7 1389 1237 1199 1519 5344
8 1969 1263 1230 1701 6163
9 1041 1228 1804 1927 6000
10 1651 1197 1687 1459 5994
11 1071 1242 1955 1954 6222
12 1171 1154 1417 1376 5118
11. For the above data, write a program to plot the monthly total sale of the store
using a line plot.
12. For the above data, write a program to show montly sale of different items using
a multiline plot.
13. For the above data, plot a scatter plot for shampoo and moisturizer sales.
14. For the above data, plot a monthly sale of various items using a vertical bar chart.
15. For the above data, plot a pie chart to show the contribution of various items on
the total annual sale.
16. For the above data, plot a box plot for toothpaste.
724
17. Write a program to plot a 3D spiral.
x/y 1 2 3 4 5 6 7 8 9 10
18.
1 16 22 40 38 10 15 29 36 10 17
2 34 35 20 38 28 39 38 21 30 18
3 36 28 28 15 13 18 38 25 10 25
4 13 25 26 39 15 22 29 19 10 24
5 35 26 33 27 40 24 30 27 27 13
6 10 15 34 21 12 22 39 34 26 24
7 30 32 38 32 40 32 18 23 40 35
8 25 14 31 25 40 40 13 40 11 13
9 29 15 13 23 25 31 35 28 37 33
10 23 35 12 23 38 27 37 11 34 37
725
726
Chapter 16
Python has many graphical user interfaces, such as tkinter, wxPython, and JPython,
to develop GUI-based Python applications. However, this chapter describes how to create
GUI programs in Python using the tkinter module. The tkinter module is a Python binding
to the Tk GUI toolkit, the original GUI library for the Tcl language. Further, this module is
bundled with almost all the Python distributions and is very easy to use. Example 16.1
shows a GUI program that prints the string "Welcome to Python GUI program !" in the
shell when clicking the Message button in the application.
727
(a) CUI based BMI calculator (b) GUI based BMI calculator
GUI
728
Output
16.2.1 Widgets
Widgets are graphical components, such as buttons, textboxes, and lists. The tkinter
module supports several widgets. The commonly used widgets are shown in table 16.1,
along with their brief descriptions. Figure 16.1 shows the appearances of some widely used
widgets.
729
Table 16.1: Commonly used widgets
Widget Description
Button The Button widget is used to create a button.
Canvas The Canvas widget is used to create a canvas to draw shapes, such as
lines, ovals, polygons, and rectangles.
Checkbutton The Checkbutton widget is used to create checkboxes to select multiple
options.
Entry The Entry widget is used to create a single-line text entry field for
accepting values from a user.
Frame The Frame widget is a container widget and is used to organize and
group other widgets.
Label The Label widget is used to create a single-line text or image that can be
used as the caption for other widgets.
Listbox The Listbox widget is used to create a list of items that a user can select.
Menubutton The Menubutton widget is used to create different types of menus in an
application.
Menu The Menu widget is used to create a drop-down menu in an application.
Message The Message widget is used to create a multiline text display field.
Radiobutton The Radiobutton widget is used to create multiple option radio buttons
and permits to select only one option at a time.
Scale The Scale widget is used to create a slider widget to generate different
values based on the option of the slider.
Scrollbar The Scrollbar widget is used to create scroll bars for various widgets to
scroll the content.
Text The Text widget is used to create a multiple lines input box.
Toplevel The Toplevel widget is used to create additional container window.
Spinbox The Spinbox widget is used to create a spin button to generate numbers
between a specified range.
messagebox This messagebox widget is used to display message boxes (for example,
OK, Cancel box, Yes, No box, and True, False box) in GUI applications.
730
Figure 16.1: Commonly used widgets
16.2.2 Events
Events in a program can be user-generated or system-generated. A user-generated
event is generated when a user interacts with a widget with any input device, such as
pressing a mouse's button, moving the mouse pointer, and pressing a key. On the other
hand, system-generated events are automatically generated by the operating system, such
as timer events. These events are recorded by the operating system and passed on to the
concerned applications. The application responds to an event if the event is bonded with an
event listening function of a widget. Otherwise, the event is ignored.
731
which is pressed. The Tkinter module assigns names to events generated by the keyboard
and the mouse. The names can be generic or specific. For example, if a programmer is
interested in handling a keypress, he can use the event name "<Key>". However, if he is
interested in handling a specific key, such as A, or B, he can use "A" or "B", respectively.
Similarly, if a programmer wants to take action on the click of any mouse button, he can use
"<Button>", but if he wants to take action of the left button click, then he can use the name
"<Button-1>" or "<1>". Table 16.2 lists the commonly used mouse and keypress event
names supported by the tkinter module, along with their brief descriptions.
Table 16.2 list the commonly used events in the tkinter module
"<Button>" The event name "<Button>" handles any mouse click, i.e., click of
any mouse button. Whereas "<Button-1>", "<Button-2> and
"<Button-3>" hands the left button, the middle button, and the right
button, respectively.
"<Motion>" The name "<Motion>" handles the motion of the mouse pointer.
732
mouse button, we use "<ButtonRelease-1>", "<ButtonRelease-2>",
and "<ButtonRelease-3>", respectively.
"<Leave>" A leave event is generated when the mouse pointer leaves a widget.
We use "<Leave>" to handle a leave event.
"<FocusIn>" When a widget gets the keyboard focus for typing characters in it,
a focus-in event is generated. This event is handled by
"<FocusIn>".
"<Return>" When we press the enter key, the tkinter module generates a return
event. This event is handled by "<Return>". Similarly, special keys,
such as Tab and Backspace, are handled with unique event names.
For example, "<Cancel>" for the break key, "<BackSpace>" for the
backspace key, "<Tab>" for the tab key, "<Shift_L>" for the shift
key, "<Control_L>" for the control key, "<Alt_L>" for the alt key,
"<Pause>" for the pause key, "<Caps_Lock>" for the caps lock key,
"<Escape>" for the esc key, "<Prior>" for the page up key, "<Next>"
for the page down key, "<End>" for the end key, "<Home>" for the
home key, "<Left>" for the left arrow key, "<Up>" for the up arrow
key, "<Right>" for the right arrow key, "<Down>" for the down
arrow key, "<Print>" for the print key, "<Insert>" for the insert key,
and "<delete>" for the delete key.
Similarly, function keys F1, F2, F3, F4, F5, F6, F7, F8, F9, F10,
F11, and F12 are maped to "<F1>", "<F2>", "<F3>", "<F4>", "<F5>",
733
"<F6>", "<F7>", "<F8>", "<F9>", "<F10>", "<F11>", and "<F12>",
respectively.
"<Key>" The event name "<Key>" handles a keypress event of any key on
the keyboard.
"<Shift-Up>" Events generated by holding down a special key and then pressing
another key, called combination key, such as a shift + up arrow key,
control + c key are handled by "<Shift-Up>" and "<Shift-c>"
respectively. We can use prefixes like Alt, Shift, and Control with
other keys to handle other combination keys.
import tkinter as tk
def myFun(event=None): #An event listener function
print("The current location of the mouse pointer is:")
print("x = ", event.x) #Get x location of the mouse pointer
print("y = ", event.y) #Get x location of the mouse pointer
print("Button number = ", event.num) #Get button number
root=tk.Tk()
734
root.geometry("100x100")
button=tk.Button(root, text= "Click to get the mouse pointer position")
button.bind("<Button>", myFun) #Binding an event with a listener
button.pack(padx=10, pady=10)
root.mainloop()
GUI
Output
1. Import the tkinter module. Preferred ways to call the module are import tkinter as
tk, from tkinter import *, or from tkinter import Button, Label.
2. Initialize the main application window and set its title, size, and appearance. The
main window of an application is created by calling the Tk() function of the tkinter
module. For example, the statement root = tk.Tk() creates the application's main
735
window and returns the handle root for its future reference. The appearance of the
window is specified through various attributes (discussed later in the chapter).
3. Create widgets and set their caption, size, appearance, and other properties. We can
create a widget by calling the construction of its widget class. For example, to create
a button, we call the constructor Button of the button widget. The statement button
= tk.Button(root, text="Click Me") creates a button with the caption "Click ME", and
it will be placed inside the main window. The creation of commonly used widgets
and their appearance control will be discussed later.
4. Create a layout of widgets. Once widgets are created, we need to arrange their
placement on the containing window. The tkinter module has geometry managers
to create the desired layout. For example, button.grid(row=1, column=1) places the
button in the second row and the second column. Different geometry managers
available in the tkinter module will be discussed later.
Example 16.3 shows the above steps for the BMI GUI application shown in figure 16.1.
Steps 3, 4, and 6 are repeated for each widget used in the application.
736
h=float(h)/100 #converting to meter
w=float(entry2.get())
if h>0:
bmi=w/(h*h) #BMI formula
#Setting the widget data
bmi_str.set(str(round(bmi,2)))
else:
bmi_str.set("Invalid data")
else:
bmi_str.set("Invalid data")
737
entry1=tk.Entry(root)
#Placing the widget in the main window in the first row and second
column (Step 4)
entry1.grid(column=1, row=0,padx=5, pady=5)
738
lable4=tk.Label(root, textvariable=bmi_str,
bg="green",justify="left",relief= tk.SUNKEN, padx=5, pady=5)
#Placing the widget in the main window in the fourth row and second
column (Step 4)
lable4.grid(column=1, row=3, sticky=tk.W, padx=5, pady=5)#Text is left
aligned
GUI
Table 16.3: Commonly used methods to set attributes of the root window
geometry It is used to change the size and location of the window. The size and
location are specified as a string of the form ‘widthxheight+x+y’, where
width and height are the window's width and height in the number of
pixels, x is the horizontal offset, and y is the vertical offset in the number of
739
pixels. If x is positive, the left edge of the screen is used as the reference, and
if it is negative, the right edge of the screen is used as the reference.
Similarly, a positive y value uses the top edge of the screen, and a negative
y value, the bottom edge. For example, root.geometry(‘300x200+50+50')
sets the width=300 and heigh=200 pixels of the root window and places the
window 50 pixels from the left and top edges of the screen.
resizable It is used to specify whether a window can be resized or not. For example,
root.resizable(False, False) makes the root window of fixed size, both
horizontally and vertically. We can control the minimum and maximum
size of a resizable window with root.minsize(min_width, min_height) and
root.maxsize(min_height, max_height) functions, respectively.
config It is used to configure the native attributes, such as the background color,
cursor of the window. For example, root.configure(background='green')
sets the background color to green and root.config(cursor='gumby') sets
the cursor to Gumby.
iconbitmap It is used to change the window icon. It requires the icon image to be in the
.ico format.
import tkinter as tk
root=tk.Tk() #Create the main application window
root.title("MyFirst GUI Application") #Set the title of the window
root.geometry("400x400+50+50") #Set the size of the window and its
location
#Make the window resizable vertically and fixed horizontally
740
root.resizable(False, True) #Set the resizable flag
root.iconbitmap('./python_104451.ico') #Set the icon of the window
root.attributes('-alpha',0.9) #Set the transparency of the window
root.configure(background='green')#Set the background color
root.config(cursor='gumby')#Set the background color
root.mainloop() #Start the event loop
Output
where widget is the handle of the created widget, WidgetClass is the constructor of the
Widget Class, parent_window is the container window/widget handle in which the widget
will be added, and options are the customization parameters. For example, the statement
button = tkinter.Button(root, text= "Click Me", bg= "green", command=myFun) will
create a button widget in the root window with the caption Click Me, and background color
green and will call the function myFun on the left mouse button click.
741
object. For example, to set the background color (i.e. the attribute bg) to green of a button
widget, we can use any one of the following:
(1) button = tk.Button(root, text= "Click Me", bg = "green") #Using the constructor
Some attributes are common to all the widgets (called standard attributes), and some
are specific to a widget. The common attributes are discussed in section 16.5.1, and the
specific attributes are discussed separately for each widget.
Table 16.3 lists common standard attributes along with their brief descriptions.
Example 16.5 illustrates some standard attributes.
Attribute Description
state The state attribute sets the state of a widget. A widget can be in the
following states: normal, active, and disabled. A widget is in the
normal state when it responds to the user actions; otherwise, it is in
the disabled state. When a normal state widget gets the focus of an
input device, it goes into the active state. The tkinter module has
three constants - NORMAL, ACTIVE, and DISABLED,
representing normal, active, and disabled states, respectively. In
place of these constants, we can also use strings "normal", "active",
and "disabled". Example 16.5(a) illustrates various states for the
button widget.
padx and pady The padx and pady attributes add extra spaces (in pixels) around
the widget. The padx attribute adds equal spaces to the left and the
ipadx and ipady right of the widget. At the same time, the pady attribute adds equal
spaces on the top and the bottom of the widget. Example 16.5(b)
illustrates padding around a widget.
742
The attributes ipadx and ipady allocate the spaces around the text
inside the widget boundary in the x and y directions, respectively.
background or bg The background colors of widgets can be set with the background
foreground or fg attribute. We can also use bg as an abbreviation of background.
Similarly, the foreground colors of widgets can be set with the
activebackground foreground attribute, which can also be abbreviated to fg.
activeforground
In the active state of a widget, the background and foreground can
be changed using the activebackground and activeforground
attributes, respectively.
743
cursor The cursor is a small icon that shows where the mouse pointer is
located on the screen. We can use different shapes for different
widgets. Commonly used cursor shapes available in the tkinter
module are "arrow", "circle", "clock","cross", "dotbox", "exchange",
"fleur", "heart", "man", "mouse", "pirate", "plus", "shuttle", "sizing",
"spider", "spraycan", "star", "target", "tcross", "trek", "watch". We
use the cursor attribute to change the shape of the cursor for a
widget. Example 16.5(g) illustrates cursor setting.
activeforeground It is used to set the color of the text when the widget is activated.
activebackground It is used to set the color of the background when the widget is
activated.
image It is used to set an image to be displayed on the widget.
import tkinter as tk
root=tk.Tk() #Create the main application window
root.title("Demo of standard attributes") #Set the title of the window
root.geometry("250x130") #Set the size of the window and its location
744
checkbutton1=tk.Checkbutton(root, text="Active",
activebackground='blue')
checkbutton1["state"]=tk.ACTIVE #Activating widget
checkbutton1.grid(row=2,column=1, padx=10, pady=10)
checkbutton2=tk.Checkbutton(root, text="Disabled")
checkbutton2["state"]=tk.DISABLED #Disabling widget
checkbutton2.grid(row=2,column=2, padx=10, pady=10)
import tkinter as tk
root=tk.Tk() #Create the main application window
root.title("Demo of standard attributes") #Set the title of the window
root.geometry("250x130") #Set the size of the window and its location
745
label1=tk.Label(root, text="Padded Label 6")
label1.grid(row=2,column=1, padx=15, pady=10)
label1=tk.Label(root, text="Padded Label 7")
label1.grid(row=3,column=0, padx=15, pady=10)
label1=tk.Label(root, text="Padded Label 8")
label1.grid(row=3,column=1, padx=15, pady=10)
GUI
import tkinter as tk
root=tk.Tk() #Create the main application window
#Setting background, foreground, active background and active
foreground colors of widgets
button=tk.Button(root, text="Red background", bg="red")
button.grid(row=0,column=0, padx=15, pady=10)
button1=tk.Button(root, text="Blue foreground", fg="#0000FF")
button1.grid(row=0,column=1, padx=15, pady=10)
button2=tk.Button(root, text="Green active background", state="active",
activebackground='green')
button2.grid(row=1,column=0, padx=15, pady=10)
button3=tk.Button(root, text="Magenta active
foreground",state="active", activeforeground='magenta')
button3.grid(row=1,column=1, padx=15, pady=10)
746
Example 16.5(d): Setting the width and height of a widget
import tkinter as tk
root=tk.Tk() #Create the main application window
#Setting the width and heigth of a widget
button=tk.Button(root, text="Default Button")
button.grid(row=0,column=0, padx=15, pady=10)
button1=tk.Button(root, text="30 characters wide button",width=30)
button1.grid(row=0,column=1, padx=15, pady=10)
button2=tk.Button(root, text="Button with three lines height",height=3)
button2.grid(row=1,column=0, padx=15, pady=10)
button3=tk.Button(root, text="Button(30x3)",width=30, height=3)
button3.grid(row=1,column=1, padx=15, pady=10)
root.mainloop() #Start the event loop
GUI
747
Example 16.5(e): Various types of widget reliefs
import tkinter as tk
root=tk.Tk() #Create the main application window
#Setting border decoration using the relief attribute
button=tk.Button(root, text="Flat Button", relief=tk.FLAT)
button.grid(row=0,column=0, padx=15, pady=10)
button1=tk.Button(root, text="Sunken Button",relief="sunken")
button1.grid(row=0,column=1, padx=15, pady=10)
button2=tk.Button(root, text="Raised Button",relief="raised")
button2.grid(row=0,column=2, padx=15, pady=10)
button3=tk.Button(root, text="Grooved Button",relief= tk.GROOVE)
button3.grid(row=1,column=0, padx=15, pady=10)
import tkinter as tk
root=tk.Tk() #Create the main application window
#Setting fonts of widgets
button=tk.Button(root, text="Times 18 italic", font=('Times', '18',
'italic'))
button.grid(row=0,column=0, padx=15, pady=10)
button1=tk.Button(root, text="Times 12 bold",font=('Times', '12',
'bold'))
button1.grid(row=0,column=1, padx=15, pady=10)
button2=tk.Button(root, text="Arial 15 underline",font=('Arial', '15',
'underline'))
748
button2.grid(row=0,column=2, padx=15, pady=10)
button3=tk.Button(root, text="TkTextFont",font="TkTextFont")
button3.grid(row=1,column=0, padx=15, pady=10)
button4=tk.Button(root, text="TkTooltipFont",font="TkTooltipFont")
button4.grid(row=1,column=1, padx=15, pady=10)
button5=tk.Button(root, text="TkDefaultFont",font="TkDefaultFont")
button5.grid(row=1,column=2, padx=15, pady=10)
import tkinter as tk
root=tk.Tk() #Create the main application window
#Setting cursors of widgets
button=tk.Button(root, text="Circle cursor", cursor = "circle")
button.grid(row=0,column=0, padx=15, pady=10)
button1=tk.Button(root, text="Clock cursor",cursor ="clock")
button1.grid(row=0,column=1, padx=15, pady=10)
button2=tk.Button(root, text="Cross cursor",cursor ="cross")
button2.grid(row=0,column=2, padx=15, pady=10)
button3=tk.Button(root, text="Man cursor",cursor ="man")
button3.grid(row=1,column=0, padx=15, pady=10)
749
16.5.2 Geometry Layout Managers
For organizing widgets throughout the parent widget area, the tkinter module
provides the following geometry managers: pack, grid, and place. The place geometry
manager positions a widget using the absolute value of x and y coordinates. The pack
geometry manager organizes widgets in horizontal and vertical boxes utilizing an
algorithm. The grid geometry manager places widgets in a tabular two-dimensional grid.
We can use any one geometry manager to create the desired layout. We should not mix grid
and pack geometry managers in a program.
The pack layout manager: The pack geometry manager is a relative position manager that
places widgets in horizontal and vertical boxes in the main window or container widget. It
is called relative as when we resize the container; widgets automatically adjust their
positions base on the size of the container. The layout is controlled with the fill, expand, and
side options. These options are briefly described in Table 16.4.
Option Description
side The side option decides the location of the widget in the available space for
the widget. There are four possible locations: top, bottom, left, and right.
The default is the top option. The top option places the widget adjacent to
the top edge of the container. If there is already a widget, the new widget
will be placed just below that. Similarly, the left, right, and bottom options
place the widget along the container window's left, right, and bottom edges.
Example 16.5(h) illustrates the side option.
To create a complex playout, we usually use container widgets, such as
frames to place other widgets properly. Each frame uses its own geometry
manager. Example 16.5(i) uses frames to create a data entry form.
750
expand The expand option controls how much of the available space of the container
is allocated to widgets. If the expand options of all the widgets are set to
false or 0, the pack manager allocates the minimum space required to
display each widget. However, if the expand option is set to true, the extra
available space is equally distributed among all the widgets with expand=1.
Example 16.5(j) illustrates the expand options.
fill The fill option increases the size of the widget to occupy the available space
to a widget. It can take the following three values, tk.X, tk.Y, and tk.BOTH.
The value tk.X, or "x", increases the size in the x-direction; the value tk.Y, or
"y", increases the size in the y-direction and the value tk.BOTH, "both",
increase the size in both directions. Example 16.5(k) illustrates the fill
options. You can notice that if expand is set to false, the fill in y-direction
will do nothing as the pack manager only allocate the minimum height
required to show the widget. However, the x-direction has no such limit.
import tkinter as tk
root = tk.Tk()
root.geometry('300x200') #Available space
b1 = tk.Button(root, text="Left", width=15)
b1.pack(side='left') #Place adjacent to the left edge
b2 = tk.Button(root, text="Right", width=15)
b2.pack(side='right') #Place adjacent to the right edge
b3 = tk.Button(root, text="Top", width=15)
b3.pack(side='top') #Place adjacent to the top edge
b4 = tk.Button(root, text="Bottom", width=15)
b4.pack(side='bottom') #Place adjacent to the bottom edge
b5 = tk.Button(root, text="Top1", width=15)
b5.pack(side='top') #Place adjacent to the last widget placed at the
top edge
b6 = tk.Button(root, text="Bottom1", width=15)
b6.pack(side='bottom') #Place adjacent to the last widget placed at the
bottom edge
root.mainloop()
GUI
751
Example 16.5(i): The side attribute
import tkinter as tk
root = tk.Tk()
root.geometry('300x200')
#Using frames to properly align widgets
frame1=tk.Frame(root) #Frame 1
frame1.pack(pady=10)
label1 = tk.Label(frame1,text="Name", width=20)
label1.pack(side="left")
entry1=tk.Entry(frame1)
entry1.pack(side="right")
frame2=tk.Frame(root) #Frame 2
frame2.pack(pady=10)
label2 = tk.Label(frame2,text="Class", width=20)
label2.pack(side="left")
entry2=tk.Entry(frame2)
entry2.pack(side="right")
frame3=tk.Frame(root) #Frame 3
frame3.pack(pady=10)
label3 = tk.Label(frame3,text="Age", width=20)
label3.pack(side="left")
entry3=tk.Entry(frame3)
entry3.pack(side="right")
frame4=tk.Frame(root) #Frame 4
752
frame4.pack()
b1=tk.Button(frame4, text="Save")
b1.pack(side="right", padx=10)
b2=tk.Button(frame4, text="Discard")
b2.pack(side="right", padx=10)
b3=tk.Button(frame4, text="Help")
b3.pack(side="right", padx=10)
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
root.geometry('200x200')
753
frame2.pack(expand=1, fill=tk.BOTH)
tk.Button(frame2, text='Expand = 0').pack(expand=0)
tk.Button(frame2, text='Expand = 1').pack(expand=1)
#Widgets expand equally in the total space in the frame
frame = tk.Frame(root, width=100, height=100, bg="blue")
frame.pack(expand=1, fill=tk.BOTH)
tk.Button(frame, text='Expand = 1').pack(expand=1)
tk.Button(frame, text='Expand = 1').pack(expand=1)
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
root.geometry('200x300')
#Effect of combination of fill and expand settings
frame = tk.Frame(root, width=100, height=100, bg="black")
frame.pack(expand=1, fill=tk.BOTH)
tk.Button(frame, text='Fill = not set, expand=0').pack(expand=0)
tk.Button(frame, text='Fill = not set, expand=0').pack(expand=0)
754
#Widgets occupy the minimum space in the frame
tk.Button(frame1, text='Fill = x, expand=0').pack(expand=0, fill='x')
tk.Button(frame1, text='Fill = y, expand=0').pack(expand=0, fill='y')
#The first wiget occupy the minimum space required for its display but
the second widget expand to the remaining available space in the frame
frame2 = tk.Frame(root, width=200, height=100, bg="red")
frame2.pack(expand=1, fill=tk.BOTH)
tk.Button(frame2, text='Fill = x,expand=0').pack(expand=0, fill='x')
tk.Button(frame2, text='Fill = y, expand=1').pack(expand=1, fill='y')
root.mainloop()
GUI
755
The grid layout manager: The grid geometry manager is the most widely used layout
manager as it can be used to create complicated layouts easily. It divides the available space
of a container into a two-dimensional grid. We can place widgets in grid cells. The
individual grid cell can be accessed with its row and column indices. It also allows merging
adjacent grid cells to accommodate larger widgets. Table 16.5 shows the attributes that
control the layout in the grid manager.
Parameters Meaning
row and column The attributes row and column specifies the row and column index
where the widget will be placed. The index of the first row and the
first column is 0. The grid manager automatically determines the
756
maximum number of rows and columns based on the index used.
We can keep some grid cells blank. Example 16.5(l) illustrates the
row and column attributes.
rowspan, When we want to spread a widget in more than one cell, we can
columnspan use the rowspan to spread in more than one row and use
columnspan to spread in more than one column. We can use both
simultaneously to cover more than one row and more than one
column. Example 16.5(m) illustrates the rowspan and the
columnspan attributes.
sticky If the cell is larger than the widget size, the sticky option is used to
specify the location within the cell where the widget will be placed.
The possible values of sticky are N, S, E, W, NW, NE, SW, and SE.
NW N NE
W Default location E
SW S SE
padx The padx attribute adds external padding above and below the
pady widget. The pady adds external padding to the left and right of the
ipadx widget. The ipadx adds internal padding inside the widget from
ipady the left and right sides. The ipady adds internal padding inside the
widget from the top and bottom sides.
757
Example 16.5(l): The row and column attributes of the grid layout manager
import tkinter as tk
root = tk.Tk()
#The grid layout manager. Location is decided by the row and column
values
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
#The grid layout manager. use of rowspan and column span to merge
cells.
bt1=tk.Button(root, text='Cell (0, 0), columnspan=2')
bt1.grid(row=0,column=0,columnspan=2, padx=5, pady=5)
bt2=tk.Button(root, text='Cell (0, 2)')
bt2.grid(row=0,column=2, padx=5, pady=5)
bt3=tk.Button(root, text='Cell(1, 0)\n rowspan=2')
758
bt3.grid(row=1,column=0, rowspan=2, padx=5, pady=5)
bt4=tk.Button(root, text='Cell (1, 1) columnspan=2\nrowspan=2')
bt4.grid(row=1,column=1, rowspan=2, columnspan=2, padx=5, pady=5)
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
#Uses of the sticky attribute to locate widgets in their available
spaces
759
tk.Button(root, text='Cell (2, 2) sticky=SE').grid(row=2,column=2,
sticky="SE")
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
#External and internal padding
tk.Button(root, text='Cell (0, 0)').grid(row=0,column=0, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (0, 1)').grid(row=0,column=1, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (0, 2)').grid(row=0,column=2, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (1, 0)').grid(row=1,column=0, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (1, 1)').grid(row=1,column=1, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (1, 2)').grid(row=1,column=2, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (2, 0)').grid(row=2,column=0, padx=5,pady=5,
ipadx=5,ipady=5)
760
tk.Button(root, text='Cell (2, 1)').grid(row=2,column=1, padx=5,pady=5,
ipadx=5,ipady=5)
tk.Button(root, text='Cell (2, 2)').grid(row=2,column=2, padx=5,pady=5,
ipadx=5,ipady=5)
root.mainloop()
GUI
The place layout manager: The place geometry layout manager is an absolute layout
manager where we can explicitly specify the position and the size of a widget in the
container window. This geometry manager is the simplest layout manager, but the size and
the position of a widget do not change if we resize the window. Further, changing the
caption and the font of the caption may require a re-layout. Hence, it is not recommended
as a general-purpose layout manager. However, it has the ability to create any complex
layout. Table 16.6 lists the attributes of the place manager and briefly describes them.
anchor The attribute anchor is the reference location on a widget used to place
the widget in the container window. The tkinter module supports the
following locations: north ("n"), east("e"), south("s"), west("w"), north-
east("ne"), north-west("nw"), south-east("se"), south-west("sw"), and
"center". These values are also defined in the tkinter module as tk.N, tk.E,
tk.S, tk.W, tk.NE, tk.NW, tk.SE, tk.SW and tk.CENTER, respectively.
These positions are shown in the following figure. Example 16.5(p)
illustrates the anchor attribute.
761
nw n ne
w center e
sw s se
bordermode The bordermode attribute decides the origin of the pixel coordinate
system to place widgets in the container. It can be set to either tk.INSIDE
("inside") or tk.OUTSIDE ("outside"), where "inside" means the border
width of the parent widget is ignored during the calculation of the offsets
and "outside" means the border width of the parent widget will be
included. The figure below shows how this attribute affects the origin.
See example 16.5(q).
Widget
762
x, y The attributes x and y specify the horizontal and vertical offsets of the
relx, rely selected anchor point (by default, the anchor point is the northwest
corner, i.e., nw) of the widget (in pixels) from the pixel coordinate origin.
By default, the origin is the northwest (i.e., upper left) corner of the
container window/widget.
The attributes relx and rely are the horizontal and vertical offset of the
anchor point from the northwest corner of the container widget and are
specified as a float between 0.0 and 1.0, as a fraction of the height and
width of the container widget/window. Example 16.5(q) illustrates the
attributes x, y, relx, and rely.
height, The attributes height and width specify the height and width of the
width, widget in pixels. The attribute relheight and relwidth specify the height
relheight, and width as a float between 0.0 and 1.0, as a fraction of the height and
relwidth width of the parent widget. The relative dimensioning automatically
adjust itself when we re-size the parent window. Example 16.5(q)
illustrates the attributes height, width, relheight, and relwidth.
import tkinter as tk
root = tk.Tk()
#Setting anchor points for widgets
f1 = tk.Frame(root, relief=tk.RAISED,bg='red', width=200, height=100)
f1.grid(row=0,column=0)
b1=tk.Button(f1,text="Anchor = default")
b1.place(x=20,y=20)
763
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
#Absolute and relative positioning and sizing of widgets
f1 = tk.Frame(root,bg='red', width=200, height=100)
f1.grid(row=0,column=0)
b1=tk.Button(f1,text="Absolute reference")
b1.place(x=20,y=20)
764
root.mainloop()
GUI
We can create a hotkey for a button by binding the keypress event of the hotkey
with the parent window. Note, don’t bind the hotkey with the button. The hotkey of a
widget is normally shown as an underlined letter and is activated by the user as a
combination of Alt + hotkey_letter. A letter can be underlined with the attribute underline.
The concept of the hotkey can be used with some other widgets also. Note, the hotkey for a
widget should be unique on a form. Example 16.6(b) illustrates the hotkey concept.
We can change the caption of a button during run-time using the attribute
textvariable. We cannot directly change the values of widget variables. For changing values
of widget variables, we have to create the corresponding tkinter variable types using the
765
following methods tk.BooleanVar(), tk.StringVar(), tk.IntVar(), and tk.DoubleVar(). Once
a tkinter variable is created, its set () method is used to assign the corresponding type of
values, and its get () method is used to get the current value of the widget variable. This
concept is true for all the widgets that support the variables. Example 16.6(c) illustrates how
to change the caption of a button at run-time. The number of clicks on the button is reflected
in its caption.
import tkinter as tk
root = tk.Tk()
#The button widget
b1=tk.Button(root,text="Handling the Left and the Right
clicks",command=funLeftClick)#Left click
root.bind("<Button-3>",funRightClick) #Binding the right click
b1.pack(padx=10,pady=10)
root.mainloop()
GUI
Output
The left mouse button clicked
The right mouse button clicked
import tkinter as tk
766
print("The hotkey H is pressed")
root = tk.Tk()
#A button with a hotkey
b1=tk.Button(root,text="Button with a Hot key",underline=14,
command=leftClick)#Left click
root.bind("<Alt-H>",hotKey) #Binding a hotkey
root.bind("<Alt-h>",hotKey) #Binding a hot key
b1.pack(padx=10,pady=10)
root.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
#Creating a tkinter string variable
click_count= tk.StringVar(None,"The number of clicks on this button =
0")
c=0 #Initialising a counter
#A button with a variable caption
b1=tk.Button(root,textvariable=click_count,command=clickCount)#Left
click
b1.pack(padx=10,pady=10)
root.mainloop()
767
GUI
Name Description
width and The attributes width and height specify the width and height of the
height canvas in pixels. Example 16.7(a) creates a canvas and draws two
ovals.
scrollregion By default, the size of the canvas is infinite in x and y directions.
However, we can limit the canvas scrolling in x and y directions using
xscrollcommand the attribute scrollregion. It takes a tuple of four numbers, (x1, y1, x2,
yscrollcommand y2), where (x1, y1) is the left-top corner of the canvas and (x2, y2) is
the right-bottom corner. When the canvas widget size is smaller than
xscrollincrement the scrollregion, we use horizontal and vertical scroll bars to scroll the
yscrollincrement canvas. The xscrollcommand and yscrollcommand attributes are
used to collect horizontal and vertical scroll bars, respectively. The
attributes xscrollincrement and yscrollincrement specify the step size
of the scroll in x and y directions, respectively. Example 16.7(b) creates
a scrollable canvas.
Create_line() The create line () method draws a chain of lines between given points.
Its syntax is given as below:
768
where (x1, y1), x2, y2), …, (xn, yn) are endpoints of line segments. The
options arguments control the color and appearance of lines. The fill
attribute specifies the color, width specified the thickness, and dash
specifies various dash line patterns. The dash attribute is a tuple of
integers or a string of dashes and dots. For example, dash = (2,4) or
dash = "." means a pattern of two solid and four transparent pixels.
We cannot create any arbitrary dash patterns as dash line patterns are
limited to the patterns supported by the operating system. On
Windows operating system, the following four patterns are available:
(2, 4), (6, 4), (6, 4, 2, 4,) and (6, 4, 2, 4, 2, 4). The string equivalents of
these patterns are: ".", "-", "-.", and "-..". If we specify any other line
patterns, the nearest available matching pattern will be used. Example
16.7(c) illustrates the create_line () method.
create_arc() The create_arc() method is used to create an arc. Its syntax is:
where, bb is the bounding box of the ellipse of which the arc is a part.
To create a circular arc, take a square bounding box. It is a tuple of 4
integers (x1, y1, x2, y2). Where (x1, y1) is the upper left corner and (x2,
y2) is the lower corner of the bounding box. The parameter start is the
start angle, and extend is the angle from start to the end angle of the
arc in degree (See the figure given below). Zero degrees represent the
x-axis, and a positive value is in the counterclockwise direction, and a
negative value is in the clockwise direction. The fill parameter is the
fill color of the arc. Example 16.7(d) illustrates the method.
769
create_polygon() The create_polygon method creates a polygon from the given vertex
points. The start point and endpoint are connected. The syntax of the
method is:
Where (x1, y1), (x2, y2), …, (xn, yn) are vertices of the polygon. The
options attributes are used to control the appearance of the polygon.
Example 16.7(e) illustrates the create_polygon method.
create_oval() The create_oval method creates an oval from a given bounding box.
The syntax of the method is:
Where (x1, y1) and (x2, y2) are the diagonally opposite corners of the
rectangular bounding box. The options attributes are used to control
the appearance of the oval.
Example 16.7(f) illustrates the create_oval method.
create_rectangle The create_rectangle method creates a rectangle. The syntax of the
method is:
Where (x1, y1) and (x2, y2) are the diagonally opposite corners of the
rectangular. The options attributes are used to control the appearance
of the oval.
Example 16.7(g) illustrates the create_rectangle method.
create_image The create_image method is used to add an image on the canvas. Its
syntax is:
where x, y is the location on the canvas where the anchor point of the
image will be located. The possible anchor points are N, S, E, W, NW,
NE, SW, SE, and center points of the image. The image argument is
the image handle returned by the PhotoImage method, which loads
the image in memory. However, the tkinter PhotoImage () method
only supports the GIF, PGM, PPM, and PNG file formats. The syntax
of the PhotoImage() method is:
770
image_id = PhotoImage(file = image_address)
import tkinter as tk
parent = tk.Tk()
#Create a canvas of size 100x100 with green background
canvas = tk.Canvas(parent, width=100, height=100, bg="green")
canvas.create_oval(0,0, 100, 100, fill="blue") #Draw an oval
canvas.create_oval(25, 25, 75, 75, fill="red") #Draw an oval
canvas.pack()
parent.mainloop()
GUI
import tkinter as tk
parent = tk.Tk()
parent.geometry("150x150")
#Scrollable canvas
771
canvas = tk.Canvas(parent, width=100, height=100,
xscrollincrement=50,yscrollincrement=50)
canvas.create_oval(0, 0, 50, 50, fill="red")
canvas.create_oval(100, 100, 250, 250, fill="blue")
canvas.grid(row=0, column=0)
#Creatting a horizontal scroll bar
scroll_x = tk.Scrollbar(parent, orient="horizontal",
command=canvas.xview)
scroll_x.grid(row=1, column=0, sticky="ew")
#Creating a vertical scroll bar
scroll_y = tk.Scrollbar(parent, orient="vertical",
command=canvas.yview)
scroll_y.grid(row=0, column=1, sticky="ns")
#Connecting scroll bars with canvas
canvas.configure(yscrollcommand=scroll_y.set,
xscrollcommand=scroll_x.set)
#Setting scrollable size
canvas.configure(scrollregion=(0,0,300,300))
parent.mainloop()
GUI
import tkinter as tk
parent = tk.Tk()
#Create arcs
canvas = tk.Canvas(parent, width=300, height=100, bg="white")
772
canvas.create_line(10,10,100,10) #Default line
canvas.create_line(10,20,100,20, fill="red") #Coloured line
canvas.create_line(10,30,100,30, width=4) #Thick line
canvas.create_line(10,40,100,40, dash=(2,4))#Dashed line
canvas.create_line(10,50,100,50, dash=(6,4), fill="#00FF00")#Long dash
line
canvas.create_line(10,60,100,60, dash=(6,4,2,4))#Long and small dashes
canvas.create_line(10,70,100,70, dash=(6,4,2,4,2,4))#Long and small-
small dashes
canvas.create_line(10,80,100,80, dash="-..")#Long and small-small
dashes
canvas.create_line(110,10,200,10,200,80,110,80)#Multiple line segments
canvas.create_line(250,10,300,80,210,80,250,10, dash=".", fill="blue")
canvas.pack()
parent.mainloop()
GUI
import tkinter as tk
parent = tk.Tk()
#Create a canvas
canvas = tk.Canvas(parent, width=300, height=300, bg="white")
#Create arcs
bounding_box = 0,0, 300, 300 #Specify the bounding box of the ellipse
canvas.create_arc(bounding_box, start=0, extent=45, fill="red")#Create
a filled arc
canvas.create_arc(bounding_box, start=180, extent=-30,
fill="blue")#Create a filled arc
canvas.create_arc(bounding_box, start=-90, extent=30,
fill="black")#Create a filled arc
canvas.create_arc(bounding_box, start=-135, extent=-30)#Create an
unfilled arc
773
canvas.pack()
parent.mainloop()
GUI
import tkinter as tk
parent = tk.Tk()
#Create polygons
canvas = tk.Canvas(parent, width=310, height=100, bg="white")
canvas.create_polygon(10,10,100,10,100,80,10,80)#Draw a polygon
#Draw a polygon with a fill color and specified outline
canvas.create_polygon(150,10,200,80,110,80, dash=".",fill="blue",
outline='red')
canvas.create_polygon(250,10,300,80,210,80, dash="-",fill="white",
outline='red')
canvas.pack()
parent.mainloop()
GUI
774
Example 16.7(f): Draw ovals
import tkinter as tk
parent = tk.Tk()
#Create ovals
canvas = tk.Canvas(parent,width=400, height=150, bg="white")
canvas.create_oval(10,100,150,10)#Draw an oval
#A filled oval with border
canvas.create_oval(160,10,230,150, fill='red', width=4)
#Draw an unfilled oval with dashed outline
canvas.create_oval(250,10,350,110,width=4, fill='',dash="-..",
outline='green')
canvas.pack()
parent.mainloop()
GUI
775
Example 16.7(g): Draw rectangles
import tkinter as tk
parent = tk.Tk()
#Create rectangles
canvas = tk.Canvas(parent,width=400, height=150, bg="white")
canvas.create_rectangle(10,100,150,10)#Draw a rectangle
#A filled rectangle with a border
canvas.create_rectangle(160,10,230,150, fill='red', width=4)
#Draw an unfilled rectangle with dashed outline
canvas.create_rectangle(250,10,350,110,width=4, fill='',dash="-..",
outline='green')
canvas.pack()
parent.mainloop()
GUI
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width = 200, height = 200, bg='green')
canvas.pack()
img = tk.PhotoImage(file="Python.png") #Create image handle
canvas.create_image(30,30, anchor=tk.NW, image=img)#Put image on the
canvas
mainloop()
GUI
776
Example 16.7(i): Write texts on a canvas
import tkinter as tk
root = tk.Tk()
colors=['','red','green','blue','yellow','cyan']
canvas = tk.Canvas(root, width = 500, height = 200, bg='white')
canvas.pack()
for i in range(1,5):
font_name =('Helvetica',25-2*i,'bold') #Create font
#Write texts on the canvas
canvas.create_text(30,30*i,fill=colors[i], font=font_name,
anchor=tk.NW, text="Welcome in the world of canvas")#Put image on the
canvas
root.mainloop()
GUI
777
16.8 Checkbutton Widget
A checkbox button is a GUI widget used to choose an option from two mutually
exclusive options. It is used to answer the yes/no type of questions, such as, do you know
Python programming? A checkbox button is created from the class Checkbox and has the
following syntax:
where root is the container widget, or application window handle and options are used to
control the widget's appearance. The methods and attributes specific to the checkbox button
are listed in table 16.8, along with a brief description of each. For the standard attributes,
see table 16.3.
778
deselect, The deselect () method clears (turn off) the Checkbutton through
flash, code.
invoke, The flash () method flashes the Checkbutton several times between
select, its active and normal colors but leaves it the way it started. This is
toggle used to get the attention of the user.
The invoke () method simulates the mouse click event through the
program. We can use it to change the state of a Checkbutton
through the program.
The select () method sets (turns on) the Checkbutton through the
program.
The toggle () method toggles the state of the Checkbutton. Example
16.8(b) illustrates these functions.
import tkinter as tk
languages=["","Python","C++","Java"]
root = tk.Tk()
label =tk.Label(root, text="Select the languages you know")
label.pack(padx=5)
#Create checkboxes
check1=tk.Checkbutton(root, text="1. Python", variable=check_values[0],
onvalue=1)
check1.pack(anchor='nw',padx=5)
check2=tk.Checkbutton(root, text="2. C++", variable=check_values[1],
onvalue=2)
check2.pack(anchor='nw',padx=5)
check3=tk.Checkbutton(root, text="3. Java", variable=check_values[2],
onvalue=3)
779
check3.pack(anchor='nw',padx=5)
b1=tk.Button(root, text="Print Choices", command=printChoices )
b1.pack(padx=5, pady=5)
root.mainloop()
GUI
Output
Your choices are:
Choice No: 1, Language: Python
Choice No: 3, Language: Java
import tkinter as tk
languages=["Python","C++","Java"]
780
def invokeChoices(): #Invoke checkbuttons
check1.invoke()
check2.invoke()
check3.invoke()
root = tk.Tk()
label =tk.Label(root, text="Select the languages you know")
label.pack()
check_values=list()
check_values.append(tk.IntVar())
check_values.append(tk.IntVar())
check_values.append(tk.IntVar())
781
16.9 Entry Widget
The Entry widget is used to get one-line text input from the user. For a long input
text, the arrow keys can be used to move to scroll the text. We can also use the entry widget
to display and modify a single-line text. The following syntax is used to create an entry
widget:
where root is the parent window/widget, and options control the appearance and behavior
of the entry widget. Table 16.9 lists commonly used specific attributes and methods of the
entry widget. For the standard attributes, see table 16.3.
Attribute/method Description
textvariable The textvariable attribute links the StringVar object with the content
of the entry widget. We can use the StringVar object to retrieve the
current text from your entry widget.
show The show attribute is used to make a password entry widget by
showing a specified character in place of the entered characters. For
example, show= '*', will display * for each entered character.
However, internally, the widget stores the actual characters.
delete, The delete () method is used to delete a part of the entry widget text.
get, Its syntax is delete(first, last = None ). The method will delete all the
insert characters between the indices first and last. If the last argument is
omitted, only the single character at the index first is deleted.
The get () method is used to get the current text of the widget as a
Python string.
The insert method inserts a string at a specified index. Its syntax is
insert (index, string), where index is the index where the string is
inserted.
Example 16.9 illustrates these methods.
782
Example 16.9: Entry widget attributes and methods
import tkinter as tk
def insertText(): #Insert the text in the user name field at index 1
entry1.insert(1, entry4.get())
root =tk.Tk()
user =tk.StringVar(root,'DEFAULT') #Initialise the default user name
password = tk.StringVar(root,'123456') #Initialise the default password
password1 = tk.StringVar(root,'')
text1 = tk.StringVar(root,'$') #Initialise the insert text
#Create user data entry fields
label1 = tk.Label(root, text="Enter your name:",anchor='nw',
width=30,justify=tk.LEFT)
label1.grid(row=0,column=0, padx=5,pady=5 )
entry1 = tk.Entry(root,textvariable=user, width=30)
entry1.grid(row=0,column=1, padx=5,pady=5)
783
label4 = tk.Label(root, text="Text to insert in name:", anchor='nw',
width=30,justify=tk.LEFT)
label4.grid(row=3,column=0, padx=5,pady=5, sticky='n')
entry4 = tk.Entry(root,textvariable=text1, width=30)
entry4.grid(row=3,column=1, padx=5,pady=5)
#Create different buttons
button1 = tk.Button(root, text = "Clear form", command=clearForm)
button1.grid(row=4,column=0,padx=30,pady=5,sticky = 'e')
button2 = tk.Button(root, text = "Set to default", command=defaultForm)
button2.grid(row=4,column=0,padx=30,pady=5,sticky = 'w')
button3 = tk.Button(root, text = "Show password", command=showPass)
button3.grid(row=4,column=1,padx=10,pady=5, sticky = 'e')
button4 = tk.Button(root, text = "Insert text", command=insertText)
button4.grid(row=4,column=1, padx=5,pady=5, sticky = 'w')
root.mainloop()
GUI
where root is the parent container widget or application window, and options are attributes
to set the frame's appearance, such as frame size, background color, cursor shape, and relief.
By default, the frame shrinks or grows to fit its contents. However, we can override this by
784
using the method frame.grid_propagate(arg). The arg value 1 shrinks the frame, and the
value 0 expands to the specified size. See table 16.3 for the standard attributes. Example
16.10 illustrates the frame widget.
root = Tk()
#Creating frames
frame1 = Frame(root,width=200, height=200,bg='green', bd=3,
relief='sunken')
frame1.grid(row=0, column=0, padx=5, pady=5)
frame1.grid_propagate(0)
label1= Label(frame1,text= "Frame 1")
label1.grid(row=0,column=0,padx=5, pady=5)
label1= Label(frame1,text= "Frame colour=green")
label1.grid(row=1,column=0,padx=5, pady=5)
root.mainloop()
GUI
785
16.11 Label Widget
The label widget is used to show non-editable single or multiline texts or an image.
It is typically used to create captions for other widgets or to display results. We can create
a label widget using the Label class with the following syntax:
where root is the parent container window or widget, and options are the attributes to set
the widget's appearance. Example 16.11 illustrates the label widget.
import tkinter as tk
def changeLabel(): #Change label text
var.set(str(int(var.get())+1))
root = tk.Tk()
#Create a text label
var = tk.StringVar(root,"0")
label1 = tk.Label( root, text='Raised label', relief=tk.RAISED )
label1.grid(row=0,column=0,padx=5, pady=5)
label2= tk.Label(root,text= "Colored label", bg='green', fg='yellow')
label2.grid(row=0,column=1,padx=5, pady=5)
#Create a image label
786
logo = tk.PhotoImage(file="Python.png")
label3= tk.Label(root,image=logo, text="Image")
label3.grid(row=1,column=0,padx=5, pady=5)
#Create a text label with border
frame=tk.Frame(root, bg='red')
frame.grid(row=1,column=1,padx=5, pady=5)
label2= tk.Label(frame,text= "Label with border", bd=0)
label2.grid(padx=2,pady=2)
#Change the text of a label
button=tk.Button(root, text="Increase label value",
command=changeLabel)
button.grid(row=2, column=1, padx=2, pady=2)
label3= tk.Label(root,textvariable= var) #Label with a variable text
label3.grid(row=2, column=0, padx=2,pady=2)
root.mainloop()
GUI
787
where root is the parent window or container widget, and options are attributes to control
the appearance and behavior of the listbox. Table 16.10 lists commonly used specific
attributes and methods of the listbox widget. For the standard attributes, see table 16.3.
Attribute/method Description
listvariable The listvariable attribute stores a StringVar object which is
connected to all the list items in the listbox. Through this StringVar
object, we can modify the list items. The listvariable StringVar object
is a space-delimited string, i.e., the space acts as the separator of the
list items. To include a list item with spaces, we have to use the raw
Python string, and the spaces should be replaced with ASCII
sequence. For example, the string "Python Program JavaScript" will
create three list items, one for each word in the string. But the string
r"Python\x20Program JavaScript " will create two list items in the
listbox. Example 16.12(a) illustrates the listvariable.
activestyle The activestyle attribute controls the appearance of the active line
(the last clicked list item). It can take any of the following values:
'underline': The active line is underlined. This style is the default
option.
'dotbox': The active line is enclosed in a dotted box.
'none': No special appearance for the active line.
See example 16.12(a).
selectmode The selectmode attribute determines the ways we can select list
items using the mouse. We can use any one of the following modes:
tk.SINGLE: In this mode, we can only select one list item by clicking
on it. If we click on any other item in the list, the previous item is
deselected. We can't drag the mouse to select multiple items.
tk.MULTIPLE: In this mode, we can select multiple items by clicking
on different list items. A selected item is deselected by clicking on it
again, i.e., a click acts as a toggle. We can't drag the mouse to select
multiple items.
788
mouse, the previously selected item is deselected. This mode is the
default.
tk.EXTENDED: In this mode, we click and drag the mouse to select
multiple contiguous list items. This mode does not permit the
selection of multiple non-contiguous items.
See example 16.12(a).
curselection The curselection () method returns the indices of the currently
selected list items as a tuple. The index of the first item is 0. If nothing
is selected, it returns an empty tuple. See example 16.12(a).
delete The delete method removes multiple continuous list items specified
by a range of indices. It has the following syntax:
delete (first, last=None)
where first is the start index of the range, and last is the end index. If
the second argument is omitted, the single line with index first is
deleted. See example 16.12(b).
get The get () method returns the list items specified by a range. It has
the following syntax:
list_items = get ( first, last=None )
where first is the start of the range and last is the end. The list items
are returned as a tuple. If the argument last is omitted, the method
returns the nearest list item to the index first. See example 16.12(b).
size The size() method returns the number of lines in the listbox.
insert The insert () method inserts list items before a specified list index. It
has the following syntax:
insert (index, *elements)
To insert items at the end of the list, use tk.END as the first argument.
The index tk.END refers to the last line in the listbox and the index
tk.ACTIVE refers to the last selected list item. See example 16.12(b).
see The see (index) method adjusts the view of the list so that the list
item with the specified index is visible in the listbox.
xview, The methods yview() and xview()make the listbox vertically
yview scrollable and horizontally scrollable, respectively. We use these
methods to link the listbox view with scrollbars. Example 16.12(c)
illustrates a vertically scrollable listbox.
789
Example 16.12(a): Creating and populating a listbox
import tkinter as tk
root = tk.Tk()
def printList(): #print all the list items
items = var.get()
print(items)
def printSelected(): #Print selected items
indices = listbox.curselection()
if len(indices)==0: print("No selection")
for i in indices:
print( listbox.get(i))
#Create a StringVar object
var=tk.StringVar()
var.set(r"Python\x20Program Perl PHP JavaScript Ruby")
#Populate the list with the StringVar object
listbox = tk.Listbox(root, selectmode=tk.MULTIPLE, listvariable=var,
activestyle='dotbox')
listbox.pack(padx=10, pady=10)
button= tk.Button(root, text= "Print all the list items",
command=printList)
button.pack(padx=10, pady=10)
button= tk.Button(root, text= "Print the selected items",
command=printSelected)
button.pack(padx=10, pady=10)
root.mainloop()
GUI
790
Output
('Python Program', 'Perl', 'PHP', 'JavaScript', 'Ruby')
Perl
JavaScript
import tkinter as tk
root = tk.Tk()
def printList(): #print all the list items
print(listbox.get(0,tk.END))
listbox.delete(0,9)
#Create a listbox
listbox = tk.Listbox(root, selectmode=tk.MULTIPLE)
for i in range(100):
listbox.insert(tk.END, str(i)) #Insert list items
listbox.pack(padx=10, pady=10)
#Create buttons
button= tk.Button(root, text= "Print all the list items",
command=printList)
button.pack(padx=10, pady=5, side='top')
button= tk.Button(root, text= "Print first 10 items",
command=printFirst10)
button.pack(padx=10, pady=5, side='top')
button= tk.Button(root, text= "Delete first 10 items",
command=deleteFirst10)
button.pack(padx=10, pady=5, side='left')
button= tk.Button(root, text= "Insert Previous 10 items",
command=insertPrevious10)
button.pack(padx=10, pady=5, side='left')
button= tk.Button(root, text= "Print the selected items",
command=printSelected)
button.pack(padx=10, pady=5, side='left')
root.mainloop()
GUI
792
Example 16.12(c): A listbox with a scrollbar
import tkinter as tk
root = tk.Tk()
frame= tk.Frame(root)
frame.pack(padx=10,pady=10)
scrollbar = tk.Scrollbar(frame) #Create a scrollbar
scrollbar.pack( side = tk.RIGHT, fill = tk.Y )
#Create a listbox and attach the vertical scrollbar
mylist = tk.Listbox(frame, yscrollcommand = scrollbar.set)
793
GUI
where root is the container window/widget and options are key-value pairs that control
the menu's appearance and functionalities. The menu widget's commonly used specific
attributes and methods are given in table 16.11, along with their brief descriptions; for the
standard attributes, see table 16.3. Example 16.13 illustrates these attributes and methods.
Attribute/method Description
tearoff The tearoff attribute controls the tearing off of the menu from its
parent. For tearoff =0, the menu does not permit tearing off, and for
tearoff=1, the menu permits tearing off. When tearing is permitted,
the first entry in the submenu is a dashed line. A copy of the
submenu as an independent window is created by clicking on the
794
dashed line, which we can place anywhere on the screen. It is
possible to create more than one independent copy of the menu. See
example 16.13.
postcommand The postcommand attribute is used to call a function whenever the
user activates the menu. See example 16.13.
title The title attribute is used to assign the title of the torn-off submenu.
By default, the title of a tear-off menu window is the same as the text
of the menubutton or cascade menu that leads to this menu. See
example 16.13.
add_command The add_command (options) method adds a command submenu. A
command submenu is linked to a method that will be called
whenever the user selects this menu. A typical syntax of the method
is:
795
See example 16.13.
add_separator The add_separator() method is used to add a separator line in the
submenu. A typical syntax of the method is:
add_separator()
# display Menu
root.config(menu=menubar)
GUI
797
Output
Checkbox[0] is selected
Checkbox[1] is not selected
Checkbox[2] is selected
Checkbox[3] is not selected
Radiobutton[2] is selected
798
def myFun(): #Call back function
for i in range(4):
if checkVar[i].get()>0:
print(f"Checkbox[{i}] is selected")
else:
print(f"Checkbox[{i}] is not selected")
print(f"Radiobutton[{optionVar.get()}] is selected")
#Creating a menubutton
menubar = Menubutton ( root, text = "Menubutton", relief = RAISED,
direction='above' )
menubar.place(x=100, y=100)
799
menubar["menu"]=menu
root.mainloop()
GUI
Output
Checkbox[0] is not selected
Checkbox[1] is selected
Checkbox[2] is selected
Checkbox[3] is not selected
Radiobutton[3] is selected
Where root is the parent window or container widget, and options control the appearance
of the widget. Example 16.15 illustrates the Message widget.
800
Example 16.15: The Message widget
import tkinter as tk
root = tk.Tk()
var = tk.StringVar()
#Create a Message widget, set the text justification to right
label = tk.Message( root, textvariable = var, relief = tk.RAISED,
justify=tk.RIGHT )
GUI
where root is the parent window or widget, and options control the appearance and
behavior of the widget.
801
The value attribute stores the value assigned to the control variable of the radio
button group when the radiobutton is turned on by the user. The value can be an IntVar or
a StringVar. The variable attribute is the control variable of the group of radio buttons. Its
current value is equal to the currently selected radio button in the group. Example 16.16
illustrates the radiobutton widget.
# !/usr/bin/python3
import tkinter as tk
gender = ["Male", "Female"]
income = ["0-1000","1001-2000",">2000"]
def yourChoice():
selection = "You gender is " + gender[var1.get()] + " and your
income is in the range" + income[var2.get()]
L3.config(text = selection)
root = tk.Tk()
var1 = tk.IntVar(0)
var2 = tk.IntVar(0)
frame = tk.Frame(root)
frame.grid(row=0, column=0, sticky="n")
frame1 = tk.Frame(root)
frame1.grid(row=0, column=1)
802
R3.grid(row=1, column=1, sticky="w" )
R4 = tk.Radiobutton(frame1, text = "1001-2000", variable = var2, value
= 1, justify="left")
R4.grid(row=2, column=1, sticky="w")
R5 = tk.Radiobutton(frame1, text = ">2000", variable = var2, value = 2,
justify="left")
R5.grid(row=3, column=1, sticky="w")
root.mainloop()
GUI
where root is the parent window and options are key-value pairs that control the scale's
appearance and functionality.
The commonly used specific attributes and methods of the scale widget are given in table
16.12, along with their brief descriptions. Example 16.17 illustrates the scale widget.
803
Table 16.12: Commonly used attributes and methods of scale widget
Name Description
from_ The from_ and to attributes sets the lower and upper range of the scale.
to
orient The orient attribute sets the orientation of the scale. To create a horizontal
scale, set orient = tk.HORIZONTAL and for a vertical scale, set orient =
tk.VERTICAL. The default orientation is vertical.
showvalue The showvalue attribute controls the display of the current value on the
screen. If showvalue = 1, the current value of the scale is displayed. Set
showvalue=0 to suppress the display of the current value.
tickinterval The tickinterval attribute controls the gap between two intermediate scale
tick marks. For example, if from_ = 0, to = 100, and tickinterval = 25, tick
marks will be shown at values 0, 25, 50, 75, and 100. The default value is 0,
which suppresses the display of ticks.
variable The variable attribute is used to link a control variable with the scale. We
can use IntVar, DoubleVar (float), or StringVar as control variables.
get, The get and set methods are used to get and set the current value of the
set scale.
import tkinter as tk
def sel():
current_value = "Value = " + str(var.get()) #Get the current value
label.config(text = current_value)
root = tk.Tk()
var = tk.DoubleVar()
#Create a horizontal scale
scale = tk.Scale( root, variable = var, orient=tk.HORIZONTAL,
tickinterval=25, length=200)
scale.pack(anchor = tk.CENTER)
804
button = tk.Button(root, text = "Set scale pointer in the mid", command
= lambda:scale.set(50))
button.pack(anchor = tk.CENTER)
label = tk.Label(root)
label.pack()
root.mainloop()
GUI
where root is the parent window and options are key-value pairs that control the scrollbar
widget's appearance and functionality. For the standard attributes and methods, see table
13.3. The attribute orient decides the orientation of the slider widget. For, orient =
tk.HORIZONTAL, a horizontal scrollbar is created and for orient = tk.VERTICAL, a vertical
one, is created. Example 16.18 illustrates the scrollbar.
805
Example 16.18: The scrollbar
import tkinter as tk
root = tk.Tk()
frame=tk.Frame(root) #Create a frame
frame.pack(padx=10,pady=10)
806
16.19 Text Widget
The text widget is used to create a multi-line text area. The text widget is used as a
text editor to write and display texts and insert images. The following syntax is used to
create a text widget:
where root is the parent window and options are key-value pairs that control the text
widget's appearance and functionality. For the standard attributes and methods, see table
13.3. The width and height of the text widget are specified in the number of lines and the
number of characters, respectively. We can attach scrolls to scroll the content of the widget
horizontally and vertically. The wrap attribute controls how a long line wraps in the
available width of the text widget. For wrap = tk.WORD, the line will break after the last
word that will fit in the given width, and for wrap = tk.CHAR, the line will break at any
character. The default is wrap = tk.CHAR. Example 16.19(a) illustrates a text widget with a
vertical scroll. We can also add images along with the text in a text widget. Example 16.19(b)
illustrates the same.
807
Example 16.19(a): The text widget
import tkinter as tk
root = tk.Tk()
S = tk.Scrollbar(root) #Create a vertical scroll
T = tk.Text(root, height=6, width=50, wrap = tk.WORD)
S.pack(side=tk.RIGHT, fill=tk.Y) #Pack the scroll to the right side of
the root window
T.pack(side=tk.LEFT, fill=tk.Y, padx=10,pady=10)
S.config(command=T.yview) #Link the yview of the text widget with the
scroll
T.config(yscrollcommand=S.set)
#Long text
text = """The text widget is used to create a multi-line text area.
The text widget can be used as a text editor to write and display texts
and insert images. The following syntax is used to create a text
widget:
text = tk.Text(root, **options)
where root is the parent window and options are key-value pairs that
control the text widget's appearance and functionality. For the
standard attributes and methods, see table 13.3. The width and height
of the text widget are specified in the number of lines and the number
of characters, respectively. We can attach scrolls to scroll the
content of the widget horizontally and vertically."""
T.insert(tk.END, text)
tk.mainloop()
GUI
808
Example 16.19(b): A text widget with images
import tkinter as tk
#Long text
text = """We can insert images along with the text at any cursor
position in a text widget. This example illustrates the same.\n"""
GUI
809
16.20 Toplevel Widget
The Toplevel widget is used to create another independent window that will work
as a container for widgets. We can create any number of top-level windows. Following is
the syntax to the Toplevel widget :
where options are key-value pairs that control the appearance and functionality of the text
widget. Example 16.20 illustrates the Toplevel widget.
GUI
where root is the parent window and options are key-value pairs that control the text
widget's appearance and functionality. For the standard attributes and methods, see table
13.3. The attributes from_ and to sets the lower limit and the upper limit, respectively. For
a tuple of integers, the attribute values is used. The wrap attribute is used to control the
behavior of the spin at the limits of the range. If wrap = 1, the spin cycles through the range,
i.e., after reaching the upper limit, the spin starts from the lower limit. If wrap =0, the spin
stops generating new output on reaching the limit, i.e., after reaching the upper limit, no
action will be taken on clicking the up-arrow of the spin. However, if we click the down-
arrow, it will generate the previous number. Example 16.21 illustrates the spin widget.
811
Example 16.21: Spin widgets
import tkinter as tk
def curValue(): #Get the current values of spin widgets
var.set("Spin1=" + str(spin.get()) + " Spin2 = " +
str(spin1.get()))
var = tk.StringVar()
spin = tk.Spinbox(master, from_ = 0, to = 10) #Create a spinn widget
spin.pack(padx=10, pady=10)
l= tk.Label(master, textvariable=var)
l.pack(padx=10, pady=10)
mainloop()
GUI
812
16.22 Messagebox
The messagebox widget is used to create a dialog box. Dialog boxes are used to
display information, warning messages, and error messages. It can also be used to ask
questions such as Yes-No, OK-Cancel, Yes-No, Retry-Ignore. The question message boxes
return values based on the responses of the user. The following syntax is used to create this
widget.
where title and message are strings, and options are used to customize the message box.
FunctionName decides the type of dialog box that will be created. The possible function
names are showinfo, showwarning, showerror, askquestion, askokcancel, askyesno, and
askretrycancel. Example 16.22 illustrates different types of message boxes.
import tkinter as tk
from tkinter import messagebox
top = tk.Tk()
def showInfo():
messagebox.askquestion("Message box", "World is a beautiful place")
def askQuestion():
x= messagebox.askyesno("Question", "Do you agree that world is a
beautiful place?")
if x == tk.YES :
messagebox.showinfo("Message", "Welcome in this beautiful word")
else:
messagebox.showinfo("Message", "Let us join hand to make the
world beautiful")
813
top.mainloop()
GUI
Chapter Summary
1. The Graphical User Interface (GUI) uses visual objects such as boxes to type in
data and buttons that initiate actions.
2. There are many options, such as Tkinter, wxPython, and JPython, that can be
used to develop GUI-based Python applications
3. In the event-driven programming paradigm, the execution flow of a program is
controlled by a sequence of events
4. The operating system maintains a queue of events and passes it to the relevant
applications.
5. Widgets are graphical components, such as buttons, textboxes, and lists.
6. A user-generated event is generated when a user interacts with a widget with
any input device, such as pressing a mouse's button, moving the mouse pointer,
and pressing a key.
814
7. System-generated events are automatically generated by the operating system,
such as timer events.
8. When a user presses a key, a keypress event is generated. A keypress event
contains the identity of the key pressed.
9. In the case of a mouse or touchpad on a laptop, events are generated by clicking
or double-clicking a mouse button, rotating the scrolls, or moving the mouse
pointer. A mouse event contains information about the x and y coordinate of the
mouse pointer and the button which is pressed.
10. An event listener function is a function that gets executed when a widget receives
an event.
11. Preferred ways to import the tkinter module are import tkinter as tk, from
tkinter import *, or from tkinter import Button, Label.
12. In Tkinter, the main window of an application is created by calling the Tk()
function of the tkinter module.
13. By default, the main application window created by the Tk() function has a title
tk and has three system buttons, including Minimize, Maximize, and Close.
14. For organizing widgets throughout the parent widget area, the tkinter module
provides the following geometry managers: pack, grid, and place.
15. The canvas widget is used to create a rectangular graphical area for drawing
objects such as lines, circles, arcs, texts, and embed images.
16. A checkbox button is a GUI widget used to choose an option from two
mutually exclusive options.
17. The Entry widget is used to get one-line text input from the user.
18. The frame widget is a rectangular container widget, typically used to group
and layout other widgets in the application window or other container widgets.
19. The label widget is used to show non-editable single or multiline texts or an
image.
20. The Listbox widget is used to show a list of items from which the user can
select one or multiple items.
815
21. The menu widget is used to create menus in GUI applications. A menu is a
collection of commands or options from which a user can choose to trigger
actions or set options.
22. The Radiobutton widget creates multiple-choice options, out of which the user
is allowed to choose only one.
24. The Spinbox widget generates integer numbers between a specified range or
from a given tuple of integers.
2. Which of the following widget can be used for entry of data by user?
(a) Text
(b) Frame
(c) Label
(d) None of the above
816
(a) Graphics
(b) Canvas
(c) Paint
(d) All of the above
9. The back ground color of a widget can be changed by which of the following?
(a) background
(b) fg
(c) bg
(d) bground
11. The default window created by the Tk () function has the following:
(a) A title
(b) Minimize button
(c) Maximize button
(d) All of the above
817
12. In Tkinter, we can make an application window resizable in
(a) Horizontal direction
(b) Vertical direction
(c) Both, (a) and (b)
(d) All of the above
14. In Tkinter, which of the following is not a correct value of relief of a widget?
(a) Sunken
(b) Raised
(c) Flat
(d) None of the above
16. In grid geometry manager, the individual grid cell can be accessed using which of the
following?
(a) Row and column indices
(b) Row and Colum coordinates
(c) Both, (a) and (b)
(d) None of the above
17. In grid geometry manager, a widget can occupy how many cells
(a) 1
(b) 2
(c) 3
(d) All of the above
18. In a canvas widget, the attributes width and height are specified in
(a) Pixels
(b) MM
(c) CM
818
(d) All of the above
20. The entry widget can be used to input which of the following?
(a) Single line text
(b) Multiline text
(c) Both (a) and (b)
(d) None of the above
819
(c) Both, (a) and (b)
(d) All of the above
Review Questions
1. State whether the following statements are true or false:
a. GUI programs use event driven programming
b. GUI stands for graphical user interface
c. The tkinter module is used for developing GUI applications
d. Tkinter has no option to draw shapes
e. Radiobutton is a multiple item selection widget
f. Spinbox generates numbers in a sequence only
g. Entry widget can accept multi-line text
h. An event listener function is a function that gets executed when a widget
receives an event.
i. An application window is created by calling the Tk () function of the tkinter
module.
j. A widget can be in the following states: normal, active, and disabled.
k. The tkinter module supports the following relief values: SUNKEN,
RAISED, GROOVE, RIDGE, and FLAT.
l. We cannot change the font of a widget text.
m. We cannot display an image on a widget
n. The grid geometry manager divides the container into rectangular gird
cells.
o. A widget can occupy only one cell in a grid of cells.
p. We can draw a circle on a canvas using create_oval () method.
820
q. The Checkbutton widget is used for selecting multiple options.
r. The entry widget can accept multiline text.
s. Users can edit the text of a label widget.
t. The listbox widget does not permit the selection of non-contiguous items in
the list.
u. The Radiobutton permits multiple selections.
v. The scale widget is used to get a value from a specified range.
w. The spin widget returns value in an ascending sequence only.
x. The spin widget can return values as specified in a tuple.
y. The messagebox widget cannot return a value.
z. Tkinter only support a single window GUI applications.
Programming Assignments
1. Write a program to create a window of size 200x200 and set the window
background RED.
2. Write a GUI program with a button with label Welcome. On pressing the
welcome button, generate a message “Hello, Welcome to Tkinter GUI
programming’.
4. Write a GUI program to calculate the areas of a circle, a rectangle and a triangle.
5. Write a program to create a window of size 200x200 and draw a circle in the
centre of the window of diameter 100 in blue color.
6. Write a GUI program for the currency converter for INR to Dollor. Store the data
into a file and provide facility to update the conversion rate.
821
7. Write a GUI program to create a color pallete. Arrange the colors in a column.
Also modify the program to arrange the color pallete in a 2D grid.
8. Create a GUI user login page with facility to add a new user. Use a file to store
the user ID and password.
9. Create a GUI user login page with facility to add a new user. Use a file to store
the user ID and password.
10. Write a GUI based program to manage contact details of an organisation. The
program should provide the facility to add a new contact, search a contact and
display all contacts.
11. Write a GUI based Python program to manage the reservation system of an
auditorium with 36 seats arranged in a grid of 6x6 to show filled and unfilled
seats.
12. Write a program to create a simple CAD system to draw lines and circles of
different colors.
13. Write a program to show the calender of a chosen month and year.
14. Write a Python program using tkinter to create a simple calculator with facility
of addition, subtraction, multiplication and division using grid layout manager.
822
Index
3D contour plots
3D plots
Accessing a dictionary element
Accessing an element of a list
Accessing binary files
Accessing characters in a string
Adding a grid to a Plot
Adding axis labels and plot titles
Adding legends
Adding ticks and tick-labels
Algorithms and Flowcharts
Animation using Matplotlib
Arithmetic Expressions
Arithmetic Operators
Array shape manipulation
Assertions
Assigning a string literal to a variable
Assignment Operators
Attributes of the ndarray class
Bar charts
Basics of Python Programming
Bitwise operators
Boolean Literals
Box plots
break statement
Broadcasting NumPy arrays
Built-in functions for dictionaries
Built-in functions for sets
Built-in functions for strings
Built-in functions for tuples
823
Button Widget
Calling a function
Canvas Widget
Catching Specific Exceptions
Central Processing Unit
Character Set
Checkbutton Widget
Coding Style
Collection Literals
Command line arguments
Comments in Python
Commonly used built-in function for lists
Complex Number Literals
Components of a Computer
Components of Event driven programming
Computer Software
Constructors and destructor
continue statement
Contour plots
Converting other data types to lists
Create tuples
Creating a GUI Application using the tkinter Module
Creating a matrix from data
Creating an array from data
Creating and Customizing the Main Application Window
Creating arrays in NumPy
Creating Copies of a list
Creating dictionaries
Creating sets
Creating string objects
Creating sub-plots
Creating Widgets
824
CSV files
Customizing a plot
Data Encapsulation
Data structure of NumPy arrays
Decision Making and Branching
Decorator Classes
Deep copy
Define a class in Python
Defining a user-defined function
Delimiters
Dictionaries
Dictionary Literals
Display class attributes and instance methods
Dynamic Binding
Element-wise operations
else statement
Encapsulation in Python
Entry Widget
Eval Function
Event Listener Functions
Events
Exception Handling in Python
Expressions
File and Directory Management
File Handling
Floating-Point Literals
Flowchart
for loop
Format Function
Formatting Numbers and Strings
Formatting with The Format Method of The Str Object
Frame Widget
825
Frozenset
F-String in Python
Generator functions
Geometry Layout Manager
Global variables
Graphics User Interface
GUI Applications using tkinter
Guidelines to Write Algorithms
Handling a general exception
Histogram Plots
History of Python
Identifier Naming Convention
Identifiers
Identity operators
if statement
if-else statement
Importing Mathematic Functions
Indexing and slicing NumPy arrays
Indexing of tuple elements
Inheritance
Inheritance in Python
Input and Output Functions
Input Devices
Input Function
Installing Python
Instance methods
Integer Literals
Introduction to Matplotlib
Iterating over lines in a file
json module
Keyword arguments
Keywords
826
Label Widget
Ladder if (if-elif-else) statement
Lambda function
Line Continuation
List comprehension to create a new list
List creation
List Literals
List operators
List slicing
List traversal
Listbox Widget
Lists
Lists and other mutable sequences as elements of tuples
Lists from data
Literals and Datatypes
Local and global functions
Local variables
Logical Expressions
Logical Operators
Loop Control Statements
Matrix and linear algebra functions
max () and min () functions with a list of complex numbers
max() and min () functions for a list of lists or iterables
Membership Operators
Membership operators: in and not in
Memory
Menu Widget
Menubutton Widget
Message Passing
Message Widget
Messagebox Widget
Method Overloading
827
Method Resolution Order in Python
Methods of the dict class
Methods of the list class
Name mangling
Nested Dictionary
Nested if statement
Nested list comprehension to process matrices
Nested loops
Numeric literals
NumPy
NumPy Arrays
object Class
Object Oriented Programming in Python
Object-Oriented Programming
Objects and classes
Opening a file
Operations on NumPy arrays
Operations on tuples
Operator Overloading
Operator Precedence and Associativity
Operators and Expressions
Operators in Python
Output Devices
Overloading Built-in Python Functions
Overview of Python
Parameters and arguments in a Function
Parameters with default values
pass statement
Passing and returning function objects to a function
Passing arguments to a function
pickle module
Pie chart
828
plot method
Polymorphism
Polymorphism in Python
Positional Parameters
Print Function
Programming Languages
Proper Indentation
Pseudocode
Python Built-in Exceptions
Python built-in functions
Python Command Prompt
Python Distributions
Python IDEs
Python Implementations
Python Programs
Python Statements
Python Token
quit () and exit () functions
Quiver plots
Radiobutton Widget
Raising exceptions
Random reshuffle of the elements of a list
Reading a matrix from the keyboard
Reading from a text file
Reading Multiple Numeric Data Separated with a Delimiter
Reading numbers from a file
Reading Single Numeric Data
Recursive functions
Reduction operations on arrays
Reference copy
Relational (Comparison) Operators
Removing an element from a dictionary
829
Return values from functions
Returning multiple values from a function
Rules for Naming Identifiers
Scale Widget
Scatter plots
Scope and life of a variable
Scrollbar Widget
Seek and tell methods
Serialization in Python
Set Literals
Set methods
Sets
Shallow copy
Slicing of tuple
Slicing operation with a string
Sorting a tuple
Sorting data
Special Literal None
Spinbox Widget
Split a string into a list of words
Standard Attributes of Widgets
Starting Python In Windows
Statements vs Expressions
Steps in file handling
Steps to create a plot in Matplotlib
Steps to create an animation plot using FuncAnimation
Steps to create animation plot using Artist Animation
String class methods
String Expressions
String Literals
String operators
Strings
830
Structure of a Python Program
Structured NumPy Arrays
Structuring Python Programs
Ternary Operator
Text Widget
Toplevel Widget
Traditional % Formatting Operator
Traversing a dictionary
Traversing a string
Traversing sets
Traversing sliced list
Traversing tuples
Tuple
Tuple Literals
Tuple methods
Tuple vs List
Tuples from data
Tuples from other iterables
Tuples, Sets and Dictionaries
Twin axis
Type and Class Membership Tests
Types of Computer Programming Languages
Types of files
Types of Inheritance in Python
Types of System Software
User-defined exception
User-Defined Functions
Using a list as a matrix and an array
Using Comprehension
Using the construction of the string class
Variable number of parameters
Variables
831
Violin plots
While loop
Why Python?
Widgets
Wireframe and surface plots
Writing into a text file
Writing numbers and Booleans in a file
Zipping tuples together
832