Download as pdf or txt
Download as pdf or txt
You are on page 1of 114

Malawi University of Science and Technology

Malawi Institute of Technology

Introduction to Computer Programming


(Comp-122)

Module Study Guide

Compiled By:
Madalitso Nyemba, Kingsley Goliath, Innocent Jailos, Waliko Sichinga

Date
2021
This material is a property of the Malawi University of Science and Technology
This material is not to be sold.

©2021
All rights are reserved. No part of this publication may be reproduced, stored
in a retrieval system, or transmitted in any form or by any means, electronic or
mechanical, including photocopying, recording or otherwise without copyright
clearance from Malawi University of Science and Technology.

Malawi University of Science and Technology


P.O. Box 5196
Limbe
Malawi
Tel: (+265) 1 478 000
Fax: (+265) 1 478 220
Email: registrar@must.ac.mw
Website: www.must.ac.mw
Acknowledgements
This study guide has been compiled based on the main prescribed textbooks for
this module - Think Python. O'Reilly Media, Inc. by A. Downey; Automate the
Boring Stuff with Python: Practical Programming for Total Beginners. No Starch
Press. By A. Sweigart and Learn Python 3 the Hard Way: A Very Simple
Introduction to the Terrifyingly Beautiful World of Computers and Code.
Addison-Wesley Professional. By Z. A. Shaw.

Special thanks also to management of the Malawi University of Science and


Technology (MUST) for its commitment in the establishment of e-Learning.
Table of Contents

Acknowledgements .............................................................................................. 3
Chapter 1: Introduction ........................................................................................ 1
1.1 Introduction ............................................................................................... 1
1.2 Python Versions .......................................................................................... 1
1.2.1 Differences between Python 2.x and Python 3.x .................................... 1
1.2.2 Text Editors and IDEs ............................................................................ 3
1.3 Python Basics .............................................................................................. 6
1.3.1 Downloading the Version You Need ..................................................... 7
1.3.2 Installing Python ................................................................................... 8
1.3.3 How the Python Interpreter Works ..................................................... 13
Chapter 2: Programming Syntax ...........................................................................15
2.1 Storing Values in Variables ......................................................................... 15
2.2 Assignment Statements .............................................................................. 15
2.3 Variable Names......................................................................................... 16
2.4 Comments ................................................................................................ 17
2.5 Syntax Errors............................................................................................. 17
2.5.1 NameError ......................................................................................... 17
2.5.2 TypeError ........................................................................................... 18
2.5.3 IndentionError .................................................................................... 18
2.6 Runtime error ........................................................................................... 19
2.7 Semantic error .......................................................................................... 19
Chapter 3: Numeric Types and Operators ............................................................ 20
3.1 Introduction ............................................................................................. 20
3.2 The Integer, Floating-Point, and String Data Types ..................................... 20
3.2.1 Integer ............................................................................................... 21
3.2.2 Float .................................................................................................. 21
3.2.3 Complex Numbers .............................................................................. 22
3.2.4 Strings ................................................................................................ 22
3.3 Type Conversion ...................................................................................... 22
3.4 String Concatenation and Replication ........................................................ 23
3.5 Type Casting ............................................................................................. 25
3.5.1 Implicit Type Conversion .................................................................... 25
3.5.2 Explicit Type Casting........................................................................... 27
3.6 Boolean Values ......................................................................................... 27
3.3 Comparison Operators .............................................................................. 28
3.4 Boolean Operators.................................................................................... 30
3.4.1 Binary Boolean Operators ................................................................... 30
3.4.2 The not Operator ............................................................................... 31
3.4.3 Mixing Boolean and Comparison Operators ........................................ 31
3.5 Expressions in Python ................................................................................ 32
Chapter 4: Python String..................................................................................... 34
4.1 Introduction ............................................................................................. 34
4.2 String ........................................................................................................ 34
Double Quotes ................................................................................................ 34
Triple Quotes .................................................................................................. 35
4.3 Formatting string output ........................................................................... 35
4.4 String Concatenation, Indexing, and Slicing ................................................ 37
String Concatenation ....................................................................................... 37
String Indexing ................................................................................................ 38
String Slicing .................................................................................................... 40
4.5 String Methods ......................................................................................... 43
The startswith() and endswith() Methods ......................................................... 43
The join() and split() Methods ......................................................................... 44
The find() and replace() Method ...................................................................... 44
The isX() Methods ........................................................................................... 46
Converting String Case .................................................................................... 46
Determine the Length of a String ...................................................................... 47
4.6 Interact With User Input ............................................................................ 48
Chapter 5: Conditional Logic and Flow Control ................................................... 50
5.1 Introduction ............................................................................................. 50
5.2 Conditional Logic ...................................................................................... 50
Boolean expressions ........................................................................................ 50
Logical Operators ............................................................................................ 51
5.3 Controlling the Flow of Your Program ...................................................... 53
The if Statement ............................................................................................. 53
The else Keyword............................................................................................ 55
The if-elif-else Chain (elif) ................................................................................ 56
Nested if Statements ........................................................................................ 57
The while Loop ............................................................................................... 58
The for Loop ................................................................................................... 61
Nested Loops .................................................................................................. 63
5.4 Break Out of the Pattern ........................................................................... 64
if Statements and for Loops ............................................................................. 65
Break .............................................................................................................. 65
Continue ......................................................................................................... 66
Chapter 6: Collective Data Types ........................................................................ 67
6.1 Lists .......................................................................................................... 67
Creating Lists ................................................................................................... 67
Traversing Lists ................................................................................................ 68
Slices in Lists .................................................................................................... 70
Changing Values in a List with Indexes ............................................................. 71
In-operator ..................................................................................................... 71
Built-in List Functions ....................................................................................... 72
List Comprehension ......................................................................................... 77
The Syntax ...................................................................................................... 78
Expression ....................................................................................................... 78
Iterable ........................................................................................................... 78
Condition ....................................................................................................... 79
6.2 Multidimensional Lists ............................................................................... 79
6.3 Lists vs Tuples vs Dictionaries ..................................................................... 79
6.4 Traversing Dictionaries .............................................................................. 80
Restrictions on Dictionary Keys ........................................................................ 82
Restrictions on Dictionary Values ..................................................................... 82
Chapter 7: Functions .......................................................................................... 84
7.1 Writing pseudocode .................................................................................. 84
Advantages of Pseudocode .............................................................................. 84
How to write a Pseudo-code? .......................................................................... 84
7.2 Functions .................................................................................................. 86
Defining function parameters ........................................................................... 87
Positional Arguments ....................................................................................... 87
Keyword Arguments ........................................................................................ 90
Default Values ................................................................................................. 90
The Return Statement ...................................................................................... 92
Chapter 8: An Introduction to a Few OOP Concepts ............................................ 94
8.1 Definitions ................................................................................................ 94
8.2 Python is object oriented........................................................................... 95
What is a class? ................................................................................................ 95
8.3 Creating Instance Objects .......................................................................... 98
Accessing Attributes ......................................................................................... 98
Built-In Class Attributes .................................................................................... 98
Chapter 9: Errors and Exceptions in Python .......................................................... 99
8.4 Importance of Handling Exceptions ......................................................... 100
8.5 Handling Exceptions in Python ................................................................ 100
Catching Specific Exceptions in Python ........................................................... 102
Raising Exceptions in Python.......................................................................... 103
8.6 Python try with else clause ...................................................................... 103
8.7 Python try...finally .................................................................................. 105
Chapter 1: Introduction

1.1 Introduction
Python is a general-purpose, object-oriented, and open-source computer
programming language. It is commonly used for both standalone programs and
scripting applications in a wide variety of domains, by hundreds of thousands of
developers.

Python is designed to optimize developer productivity, software quality, program


portability, and component integration. Python programs run on most platforms in
common use, including mainframes and supercomputers, Unix and Linux, Windows
and Macintosh, Java and .NET, and more.

1.2 Python Versions


Every programming language evolves as new ideas and technologies emerge, and the
developers of Python have continually made the language more versatile and
powerful. As of this writing, the latest version is Python 3.9, but everything in this
book should run on Python 3.6 or later. In this section, we will find out if Python is
already installed on your system and whether you need to install a newer version.
Appendix A contains a comprehensive guide to installing the latest version of Python
on each major operating system as well.

Some old Python projects still use Python 2, but you should use Python 3. If Python 2
is installed on your system, it is probably there to support some older programs that
your system needs. We will leave this installation as is, and make sure you have a
more recent version to work with.

1.2.1 Differences between Python 2.x and Python 3.x


Python 3.x is a multi-paradigm language, which means it has a variety of
classifications for its purposes. With its functionality, Python 3.x is perfect for a broad
range of things like web development, data science, and analytics scripting. With the
“one way to do something” aspect, the unlimited possibilities become more narrow
and simpler for programmers.
1
Python 2.x and Python 3.x have a few key distinctions. Syntax is the major one, like
with the print function. Print “hello” in Python 2 becomes print (“hello”) in Python
3.x. While the addition of some parentheses does not seem too significant, in this
context, it changes print from a statement to a function. Python 3.x has clear, existing
commands already built into the code, making it very user-friendly.

Basis of Python 3.x Python 2.x


comparison
Release Date 2008 2000
Function print print (“hello”) print “hello”
Division of Whenever two integers are When two integers are
Integers divided, you get a float value divided, you always provide
integer value.
Function input In Python 3.x, default data for In Python 2.x, default data
input function is string for input function is integer.
You can also use raw_input
function for string data type
in python 2.x
Syntax The syntax is simpler and easily The syntax of Python 2 was
understandable. comparatively difficult to
understand.
Rules of ordering In this version, Rules of Rules of ordering
Comparisons ordering comparisons have comparison are very
been simplified. complex.
Iteration The new Range() function In Python 2.x, the xrange()
introduced to perform is used for iterations.
iterations.
Exceptions It should be enclosed in It should be enclosed in
parenthesis. notations.
Leak of variables The value of variables never The value of the global
changes. variable will change while
2
using it inside for-loop.
Backward Not difficult to port python Python version 3.x is not
compatibility 2.x to python 3.x but it is backwardly compatible with
never reliable. Python 2.x.
Library Many recent developers are Many older libraries created
creating libraries which you for Python 2.x is not
can only use with Python 3.x. forward compatible.

1.2.2 Text Editors and IDEs


Programmers spend a lot of time writing, reading, and editing code, and using a text
editor or an integrated development environment (IDE) to make this work as efficient
as possible is essential. A good editor will do simple tasks, like highlight your code’s
structure so you can catch common bugs as you are working. However, it will not do
so much that it distracts you from your thinking. Editors also have useful features like
automatic indenting, markers to show appropriate line length, and keyboard shortcuts
for common operations.

An IDE is a text editor with a number of other tools included, like interactive
debuggers and code introspection. An IDE examines your code as you enter it and
tries to learn about the project you are building. For example, when you start typing
the name of a function, an IDE might show you all the arguments that function
accepts. This behavior can be very helpful when everything works and you
understand what you are seeing. However, it can also be overwhelming as a beginner
and difficult to troubleshoot when you are not sure why your code is not working in
the IDE.

1.2.2.1 IDLE

IDLE is a text editor that has included with Python. It is a little less intuitive to work
with than Sublime Text or other text editors, but you will see references to it in other
tutorials aimed at beginners, so you might want to try it.

3
1.2.2.2 Geany

Geany is a simple text editor that lets you run all of your programs directly from the
editor. It displays all of your output in a terminal window, which helps you become
comfortable using terminals. Geany has a very simple interface, but it is powerful
enough that a significant number of experienced programmers still use it.

1.2.2.3 Emacs and Vim

Emacs and Vim are two popular editors favored by many experienced programmers
because they are designed to be used so your hands never have to leave the
keyboard. This makes writing, reading, and modifying code very efficient once you
learn how the editor works. It also means both editors have a fairly steep learning
curve. Vim is included on most Linux and macOS machines, and both Emacs and Vim
can be run entirely inside a terminal. For this reason, they are often used to write
code on servers through a remote terminal session.

Programmers will often recommend that you try them. However, many proficient
programmers forget how much new programmers are already trying to learn. It’s
beneficial to be aware of these editors, but hold off on using them until you’re
comfortable working with code in a simpler editor that lets you focus on learning to
program rather than learning to use an editor.

1.2.2.4 Atom

Atom is a text editor with some features that you would normally find in an IDE. You
can open an individual file you are working on, or you can open a project folder and
Atom will instantly make all the files in that project easily accessible. Atom is
integrated with Git and GitHub, so as you start to use version control, you will be
able to work with local and remote repositories from within your editor instead of
having to do so in a separate terminal. Atom allows you to install packages as well, so
you can extend its behavior in many ways. A number of these packages incorporate
behavior that makes Atom behave more like an IDE.
4
1.2.2.5 Visual Studio Code

Visual Studio Code, also called VS Code, is another editor that acts more like an IDE.
VS Code supports efficient use of a debugger, has integrated version control support,
and offers code completion tools.

1.2.2.6 PyCharm

PyCharm is a popular IDE among Python programmers because it was built to work
specifically with Python. The full version requires a paid subscription, but a free
version called the PyCharm Community Edition is also available that many developers
find useful. PyCharm features a linter, which checks that your coding style matches
common Python conventions, and offers suggestions when you deviate from normal
Python formatting. It also has an integrated debugger to help you resolve errors
proficiently and modes that help you work efficiently with a number of popular
Python libraries.

1.2.2.7 Jupyter Notebooks

Jupyter Notebook is a different kind of tool than traditional text editors or IDEs in
that it’s a web app primarily built of blocks; each block is either a code block or a text
block. The text blocks are rendered in Markdown, so you can include simple
formatting in your text blocks. Jupyter Notebooks were developed to support the use
of Python in scientific applications, but they have since expanded to become useful in
a wide variety of situations. Rather than just writing comments inside a .py file, you
can write clear text with simple formatting, such as headers, bulleted lists, and
hyperlinks in between sections of code. Every code block can be run independently,
allowing you to test small pieces of your program, or you can run all the code blocks
at once. Each code block has its own output area, and you can toggle the output
areas on or off as needed.

Jupyter Notebooks can be confusing at times because of the interactions between


different cells. If you define a function in one cell, that function is available to other
5
cells as well. This is beneficial most of the time, but it can be confusing in longer
notebooks and if you do not fully understand how the Notebook environment
works.

If you are doing any scientific or data-focused work in Python, you will almost
certainly see Jupyter Notebooks at some point

1.2.2.8 Sublime Text Editor

Sublime Text is a simple text editor that can be installed on all modern operating
systems. Sublime Text lets you run almost all of your programs directly from the
editor instead of through a terminal. Your code runs in a terminal session embedded
in the Sublime Text window, which makes it easy to see the output.

Sublime Text is a beginner-friendly editor, but many professional programmers use it


as well. If you become comfortable using it while learning Python, you can continue
using it as you progress to larger and more complicated projects. Sublime Text has a
very liberal licensing policy: you can use the editor free of charge as long as you want,
but the developer’s request that you purchase a license if you like it and want to keep
using it.

If you want to begin programming quickly, you can use Sublime Text to start and
consider other editors once you have gained some experience as a programmer. In
this chapter, I will walk you through installing Sublime Text on your operating system

1.3 Python Basics


The Python programming language has a wide range of syntactical constructions,
standard library functions, and interactive development environment features.

Python emphasizes code readability and a concise syntax that lets you write
applications using fewer lines of code than other programming languages require. In
addition, because of the way Python works, you find it used in all sorts of fields that
are filled with nonprogrammers. Some people view Python as a scripted language,
but it really is so much more.

6
Most programming languages are created with specific goals in mind. These goals help
define the language characteristics and determine what you can do with the language.
There really is not any way to create a programming language that does everything
because people have competing goals and needs when creating applications. When it
comes to Python, the main objective was to create a programming language that
would make programmers efficient and productive. With that in mind, here are the
reasons that you want to use Python when creating an application:

 Less application development time: Python code is usually 2–10 times shorter
than comparable code written in languages like C/C++ and Java, which means
that you spend less time writing your application and more time using it.
 Ease of reading: A programming language is like any other language — you
need to be able to read it to understand what it does. Python code tends to be
easier to read than the code written in other languages, which means you
spend less time interpreting it and more time making essential changes.
 Reduced learning time: The creators of Python wanted to make a
programming language with fewer odd rules that make the language hard to
learn. After all, programmers want to create applications, not learn obscure
and difficult languages.

1.3.1 Downloading the Version You Need


Every platform (combination of computer hardware and operating system software)
has special rules that it follows when running applications. The Python application
hides these details from you. You type code that runs on any platform that Python
supports, and the Python applications translate that code into something the platform
can understand. However, in order for the translation to take place, you must have a
version of Python that works on your particular platform. Some of the platforms
Python supports are:

 Linux
 Mac OS X (comes pre-installed with the OS)
 Microsoft Disk Operating System (MS-DOS)

7
 PalmOS
 PlayStation
 Solaris
 Windows 32-bit (XP and later)
 Windows 64-bit
 Windows CE/Pocket PC

To get the right version for your platform, you need to go to


https://www.python.org. The main part of the page contains links for Windows, Mac
OS X, and Linux downloads. These links provide you with the default setup that is
used in this study guide. The platform-specific links on the left side of the page show
you alternative Python configurations that you can use when the need arises. For
example, you may want to use a more advanced editor than the one provided with
the default Python package, and these alternative configurations can provide one for
you.

1.3.2 Installing Python


After you download your copy of Python, it is time to install it on your system. The
downloaded file contains everything needed to get you started:

 Python interpreter
 Help files (documentation)
 Command-line access
 Integrated Development Environment (IDLE) application
 Uninstaller (only on platforms that require it)

Working with Windows

The installation process on a Windows system follows the same procedure that you
use for other application types. The main difference is in finding the file you
downloaded so that you can begin the installation process. The following procedure
should work fine on any Windows system, whether you use the 32-bit or the 64-bit
version of Python.

8
i. Locate the downloaded copy of Python on your system.

The name of this file varies, but normally it appears as python-3.3.4.msi for 32-bit
systems and python-3.3.4.amd64.msi for 64-bit systems. The version number is
embedded as part of the filename. In this case, the file name refers to version 3.3.4,
which is the version used for this book.

ii. Double-click the installation file.

(You may see an Open File – Security Warning dialog box that asks whether you want
to run this file. Click Run if you see this dialog box pop up.) You will see a Python
Setup dialog box.

iii. Choose a user installation option

Install asks you to provide the name of an installation directory for Python. Using the
default destination will save you time and effort later. However, you can install
Python anywhere you desire.

iv. Type a destination folder name, if necessary, and click Next.

Python asks you to customize its installation. Enabling the Add python.exe to Path
option will save you time later. This feature makes it possible to access Python from
the Command Prompt window. Do not worry too much, about how you use this
feature just yet, but it really is a good feature to have installed. The book assumes that
you have enabled this feature.

v. (Optional) Click the down arrow next to the Add python.exe to Path option
and choose the Will Be Installed on Local Drive option.
vi. Click Next.

You see the installation process start. At some point, you might see a User Account
Control dialog box asking whether you want to perform the install. If you see this

9
dialog box, click Yes. The installation continues and you see an Installation Complete
dialog box.

vii. Click Finish.

Python is ready for use.

Accessing Python on Your Machine

After you have Python installed on your system, you need to know where to find it.
In some respects, Python does everything it can to make this process easy by
performing certain tasks, such as adding the Python path to the machine’s path
information during installation. Even so, you need to know how to access the
installation, which the following sections describe.

Using Windows

A Windows installation creates a new folder in the Start menu that contains your
Python installation. You can access it by choosing Start➪ Python 3.3. The two items
of interest in the folder when creating new applications are IDLE (Python GUI) and
Python (command line).

Clicking IDLE (Python GUI) produces a graphical interactive environment. When you
open this environment, IDLE automatically displays some information so that you
know you have the right application open. For example, you see the Python version
number (which is 3.3.4 in this case). It also tells you what sort of system you are using
to run Python. The Python (command line) option opens a command prompt and
executes the Python command. Again, the environment automatically displays
information such as the Python version and the host platform.

A third method to access Python is to open a command prompt, type Python, and
press Enter. You can use this approach when you want to gain additional flexibility
over the Python environment, automatically load items, or execute Python in a
higher-privilege environment (in which you gain additional security rights). Python

10
provides a significant array of command-line options that you can see by typing
Python /? at the command prompt and pressing Enter.

Testing Your Installation

To ensure that you have a usable installation, you need to test it. It is important to
know that your installation will work as expected when you need it. Of course, this
means writing your first Python application. To get started, open a copy of IDLE. As
previously mentioned, IDLE automatically displays the Python version and host
information when you open it. To see Python work, type print(“Hello World.”) and
press Enter. Python displays the message you just typed. The print() command
displays onscreen whatever you tell it to display. You see the print() command used
quite often in this study guide to display the results of tasks you ask Python to
perform, so this is one of the commands you work with frequently.

Notice that IDLE color-codes the various entries for you so that they are easier to see
and understand. The colors codes are your indicator that you have done something
right. Four-color codes are shown:

 Purple: Indicates that you have typed a command


 Green: Specifies the content sent to a command
 Blue: Shows the output from a command
 Black: Defines non-command entries

You know that Python works now because you were able to issue a command to it,
and it responded by reacting to that command. It might be interesting to see one
more command. Type 3 + 4 and press Enter. Python responds by outputting 7.
Notice that 3 + 4 appears in black type because it is not a command. However, the 7
is still in blue type because it’s output.

11
It is time to end your IDLE session. Type quit () or exit () and press Enter. IDLE may
display a message. Well, you never intended to kill anything, but you will now. Click
OK, and the session dies. Notice that the quit () command has parentheses after it, just
as the print () command does. All commands have parentheses like these two.

That is how you know they are commands. However, you do not need to tell the
quit () command anything, so you simply leave the area between the parentheses
blank.

Typing Commands

After you start the command-line version of Python, you can begin typing commands.
Using commands makes it possible to perform tasks, test ideas that you have for
writing your application, and discover more about Python. Using the command line
lets you gain hands-on experience with how Python actually works — details that
could be hidden by an Interactive Development Environment (IDE) such as IDLE. The
following sections get you started using the command line.

Python, like every other programming language in existence, relies on commands. A


command is simply a step in a procedure. When working with Python, a command,
such as print (), is simply the same thing: a step in a procedure. To tell the computer
what to do, you issue one or more commands that Python understands. Python
translates these commands into instructions that the computer understands, and then
you see the result. A command such as print () can display the results onscreen so that
you get an instant result.

The following procedure helps you see the result of using a command:

1. Start a copy of the Python command-line version.

You see a command prompt where you can type commands.

2. Type print (“This is a line of text.”) at the command line.

Notice that nothing happens. Yes, you typed a command, but you have not

signified that the command is complete.


12
3. Press Enter.

The command is complete.

This exercise shows you how things work within Python. Each command that you
type performs some task, but only after you tell Python that the command is
complete in some way. The print () command displays data onscreen.

1.3.3 How the Python Interpreter Works


The Python interpreter is a virtual machine, meaning that it is software that emulates
a physical computer. This particular virtual machine is a stack machine: it manipulates
several stacks to perform its operations (as contrasted with a register machine, which
writes to and reads from particular memory locations).

The Python interpreter is a bytecode interpreter: its input is instruction sets called
bytecode. When you write Python, the lexer, parser, and compiler generate code
objects for the interpreter to operate on. Each code object contains a set of
instructions to be executed—that is the bytecode—plus other information that the
interpreter will need. Bytecode is an intermediate representation of Python code: it
expresses the source code that you wrote in a way the interpreter can understand. It is
analogous to the way that assembly language serves as an intermediate representation
between C code and a piece of hardware.

When you write a program in C/C++, you have to compile it. Compilation involves
translating your human understandable code to machine understandable code, or
Machine Code. Machine code is the base level form of instructions that can be directly
executed by the CPU. Upon successful compilation, your code generates an
executable file. Executing this file runs the operations in your code systematically.

For the most part, Python is an interpreted language and not a compiled one,
although compilation is a step. Python code, written in .py file is first compiled to
what is called bytecode, which is stored with a .pyc or .pyo format.

Instead of translating source code to machine code like C++, Python code it
translated to bytecode. This bytecode is a low-level set of instructions that can be

13
executed by an interpreter. In most PCs, Python interpreter is installed at
/usr/local/bin/python3.8. Instead of executing the instructions on CPU, bytecode
instructions are executed on a Virtual Machine.

14
Chapter 2: Programming Syntax

2.1 Storing Values in Variables


A variable is like a box in the computer’s memory where you can store a single value.
If you want to use the result of an evaluated expression later in your program, you
can save it inside a variable.

2.2 Assignment Statements


You will store values in variables with an assignment statement. An assignment
statement consists of a variable name, an equal sign (called the assignment operator),
and the value to be stored. If you enter the assignment statement spam = 42, then a
variable named spam will have the integer value 42 stored in it.

For example, enter the following into the interactive shell:

➊ >>> spam = 40
>>> spam
40
>>> eggs = 2
➋ >>> spam + eggs
42
>>> spam + eggs + spam
82
➌ >>> spam = spam + 2
>>> spam
42
A variable is initialized (or created) the first time a value is stored in it ➊. After that,
you can use it in expressions with other variables and values ➋. When a variable is

assigned a new value ➌, the old value is forgotten, which is why spam evaluated to
42 instead of 40 at the end of the example. This is called overwriting the variable.
Enter the following code into the interactive shell to try overwriting a string:

15
>>> spam = 'Hello'
>>> spam
'Hello'
>>> spam = 'Goodbye'
>>> spam
'Goodbye'

2.3 Variable Names


The table below has examples of legal variable names. You can name a variable
anything as long as it obeys the following three rules:
1. It can be only one word.
2. It can use only letters, numbers, and the underscore (_) character.
3. It cannot begin with a number.

Valid variable names Invalid variable names

balance current-balance (hyphens are not


allowed)

currentBalance current balance (spaces are not allowed)

current_balance 4account (can’t begin with a number)

_spam 42 (can’t begin with a number)

SPAM total_$um (special characters like $ are


not allowed)

account4 'hello' (special characters like ' are not


allowed)

Variable names are case-sensitive, meaning that spam, SPAM, Spam, and sPaM are
four different variables. It is a Python convention to start your variables with a
lowercase letter.

A good variable name describes the data it contains. A descriptive name will help
make your code more readable.

16
2.4 Comments
The following line is called a comment.

# This program says hello and asks for my name.


Python ignores comments, and you can use them to write notes or remind yourself
what the code is trying to do. Any text for the rest of the line following a hash mark
(#) is part of a comment.

Sometimes, programmers will put a # in front of a line of code to temporarily remove


it while testing a program. This is called commenting out code, and it can be useful
when you are trying to figure out why a program does not work. You can remove
the # later when you are ready to put the line back in.

2.5 Syntax Errors


“Syntax” refers to the structure of a program and the rules about that structure. For
example, parentheses must come in matching pairs, so (1 + 2) is legal, but 8) is a
syntax error.

If there is a syntax error anywhere in your program, Python displays an error message
and quits, and you will not be able to run the program.

During the first few weeks of your programming career, you might spend a lot of time
tracking down syntax errors. As you gain experience, you will make fewer errors and
find them faster.

2.5.1 NameError
A NameError is raised when you try to use a variable or a function name that is not
valid.

In Python, code runs from top to bottom. This means that you cannot declare a
variable after you try to use it in your code. Python would not know what you
wanted the variable to do.

17
The most common NameError looks like this:

NameError name is not defined


Causes:

1. Misspelled Variable or Function Name


2. Calling a Function Before Declaration
3. Forget to Define a Variable
4. Try to Print a Single Word
5. Declaring a Variable Out of Scope

2.5.2 TypeError
TypeError is one among the several standard Python exceptions. TypeError is raised
whenever an operation is performed on an incorrect/unsupported object type. For
example, using the + (addition) operator on a string and an integer value will raise
TypeError.

The general causes for TypeError being raised are:

1. Unsupported operation between two data types.


2. Calling a non-callable identifier.
3. Incorrect type of list index
4. Iterating through a non-iterative identifier

2.5.3 IndentionError
One of the main reasons for the indentation error is the absence of tabs and or
whitespaces between lines of code. Since python makes use of procedural language, if
you miss adding tabs or spaces between your lines of code, then you will most likely
experience this error.

Although in some cases the entire program will run correctly, in others the error will
come in the middle of the execution and therefore pause the Mentioned below are
some of the common causes of an indentation error in Python:

18
 While coding you are using both the tab as well as space. While in theory both
of them serve the same purpose, if used alternatively in a code, the interpreter
gets confused between which alteration to use and thus returns an error.
 While programming you have placed an indentation in the wrong place. Since
python follows strict guidelines when it comes to arranging the code, if you
placed any indentation in the wrong place, the indentation error is mostly
inevitable.
 Sometimes in the midst of finishing a long program, we tend to miss indenting
the compound statements such as for, while and if and this in most cases will
lead to an indentation error.
 Last but not least, if you forget to use user-defined classes, then an indentation
error will most likely pop up.

2.6 Runtime error


The second type of error is a runtime error, so called because the error does not
appear until after the program has started running. These errors are also called
exceptions because they usually indicate that something exceptional (and bad) has
happened.

Runtime errors are rare in the simple programs you will see in the first few chapters,
so it might be a while before you encounter one.

2.7 Semantic error


The third type of error is “semantic”, which means related to meaning. If there is a
semantic error in your program, it will run without generating error messages, but it
will not do the right thing. It will do something else. Specifically, it will do what you
told it to do. Identifying semantic errors can be tricky because it requires you to work
backward by looking at the output of the program and trying to figure out what it is
doing

19
Chapter 3: Numeric Types and Operators
3.1 Introduction
There are plenty of other operators you can use in Python expressions, too. For
example, the table below lists all the math operators in Python.

Operator Operation Example Evaluates to

** Exponent 2 ** 3 8

% Modulus/remainder 22 % 8 6

// Integer division 22 // 8 2

/ Division 22 / 8 2.75

* Multiplication 3*5 15

- Subtraction 5-2 3

+ Addition 2+2 4

The order of operations (also called precedence) of Python math operators is similar
to that of mathematics. The ** operator is evaluated first; the *, /, //, and %
operators are evaluated next, from left to right; and the + and – operators are
evaluated last (also from left to right). You can use parentheses to override the usual
precedence if you need to.

3.2 The Integer, Floating-Point, and String Data Types


Remember that expressions are just values combined with operators, and they always
evaluate down to a single value. A data type is a category for values, and every value
belongs to exactly one data type. The most common data types in Python are listed
in the table below. The values -2 and 30, for example, are said to be integer values.
The integer (or int) data type indicates values that are whole numbers. Numbers with
a decimal point, such as 3.14, are called floating-point numbers (or floats). Note that
even though the value 42 is an integer, the value 42.0 would be a floating-point
number.

20
Data type Examples

Integers -2, -1, 0, 1, 2, 3, 4, 5

Floating-point numbers -1.25, -1.0, --0.5, 0.0, 0.5, 1.0, 1.25

Strings 'a', 'aa', 'aaa', 'Hello!', '11 cats'

Python programs can also have text values called strings. Always surround your string
in single or double quote characters (as in 'Hello' or “Goodbye cruel world!”) so
Python knows where the string begins and ends. You can even have a string with no
characters in it, ' ', called a blank string.

3.2.1 Integer
Int, or integer, is a whole number, positive or negative, without decimals, of
unlimited length.

Any whole number is an integer. For example, the value 1 is a whole number, so it is
an integer. On the other hand, 1.0 is not a whole number; it has a decimal part to it,
so it is not an integer. Integers are represented by the int data type.

As with storage boxes, variables have capacity limits. Trying to stuff a value that is too
large into a storage box results in an error. On most platforms, you can store numbers
between –9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 within an
int (which is the maximum value that fits in a 64-bit variable). Even though that is a
large number, it is not infinite

3.2.2 Float
Float or "floating point number" is a number, positive or negative, containing one or
more decimals.

Any number that includes a decimal portion is a floating-point value. For example,
1.0 has a decimal part, so it is a floating-point value. Many people get confused about
whole numbers and floating-point numbers, but the difference is easy to remember. If
you see a decimal in the number, then it is a floating-point value. Python stores
floating-point values in the float data type.

21
Floating-point values have an advantage over integer values in that you can store
immensely large or incredibly small values in them. As with integer variables, floating-
point variables have a storage capacity. In their case, the maximum value that a
variable can contain is ±1.7976931348623157 × 10308 and the minimum value that
a variable can contain is ±2.2250738585072014 × 10-308 on most platforms.

3.2.3 Complex Numbers


A complex number consists of a real number and an imaginary number that are
paired together.

Python is one of the few languages that provides a built-in data type to support them.
The imaginary part of a complex number always appears with a j after it. Therefore, if
you want to create a complex number with 3 as the real part and 4 as the imaginary
part, you make an assignment like this:

myComplex = 3 + 4j

Complex numbers are written with a "j" as the imaginary part.

3.2.4 Strings
A string is simply any grouping of characters you place within double quotes.

Strings in python are surrounded by either single quotation marks, or double


quotation marks.

'Hello' is the same as "hello".

You can display a string literal with the print() function.

3.3 Type Conversion


You can convert from one type to another with the int(), float(), and complex()
methods.

22
Example:

x=1 # int

y = 2.8 # float
z = 1j # complex
#convert from int to float:
a = float(x)

#convert from float to int:


b = int(y)

#convert from int to complex:


c = complex(x)
print(a)
print(b)
print(c)

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

3.4 String Concatenation and Replication


The meaning of an operator may change based on the data types of the values next
to it. For example, + is the addition operator when it operates on two integers or
floating-point values. However, when + is used on two string values, it joins the
strings as the string concatenation operator. Enter the following into the interactive
shell:

>>> 'Alice' + 'Bob'


'AliceBob'
23
The expression evaluates down to a single, new string value that combines the text of
the two strings. However, if you try to use the + operator on a string and an integer
value, Python will not know how to handle this, and it will display an error message.

>>> 'Alice' + 42
Traceback (most recent call last):
File "<pyshell#26>", line 1, in <module>
'Alice' + 42
TypeError: Can't convert 'int' object to str implicitly

The error message cannot convert 'int' object to str implicitly means that Python
thought you were trying to concatenate an integer to the string 'Alice'. Your code will
have to explicitly convert the integer to a string, because Python cannot do this
automatically.

The * operator is used for multiplication when it operates on two integer or floating-
point values. But when the * operator is used on one string value and one integer
value, it becomes the string replication operator. Enter a string multiplied by a
number into the interactive shell to see this in action.

>>> 'Alice' * 5
'AliceAliceAliceAliceAlice'

The expression evaluates down to a single string value that repeats the original a
number of times equal to the integer value. String replication is a useful trick, but it is
not used as often as string concatenation. The * operator can be used with only two
numeric values (for multiplication) or one string value and one integer value (for
string replication). Otherwise, Python will just display an error message.

>>> 'Alice' * 'Bob'


Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>

24
'Alice' * 'Bob'
TypeError: can't multiply sequence by non-int of type 'str'
>>> 'Alice' * 5.0
Traceback (most recent call last):
File "<pyshell#33>", line 1, in <module>
'Alice' * 5.0
TypeError: can't multiply sequence by non-int of type 'float'
It makes sense that Python would not understand these expressions: You cannot
multiply two words, and it is hard to replicate an arbitrary string a fractional number
of times.

3.5 Type Casting


There may be times when you want to specify a type on to a variable. This can be
done with casting. Python is an object-orientated language, and as such it uses classes
to define data types, including its primitive types. Type Casting is the method to
convert the variable data type into a certain data type in order to the operation
required to be performed by users.

There are two types of Type Casting in Python:

 Implicit Type Casting

 Explicit Type Casting

3.5.1 Implicit Type Conversion


In this method, Python converts data type into another data type automatically. In
this process, users are not involved in this process.

25
Example:

# Python program to demonstrate

# implicit type Casting

# Python automatically converts


# a to int
a=7
print(type(a))

# Python automatically converts


# b to float
b = 3.0
print(type(b))

# Python automatically converts


# c to float as it is a float addition
c=a+b
print(c)
print(type(c))

# Python automatically converts


# d to float as it is a float multiplication
d=a*b
print(d)
print(type(d))

26
3.5.2 Explicit Type Casting
In this method, Python need user involvement to convert the variable data type into
certain data type in order to the operation required.

Casting in python is therefore done using constructor functions:

 int() - constructs an integer number from an integer literal, a float literal (by
removing all decimals), or a string literal (providing the string represents a
whole number)

 float() - constructs a float number from an integer literal, a float literal or a


string literal (providing the string represents a float or an integer)

 str() - constructs a string from a wide variety of data types, including strings,
integer literals and float literals

Example:

# Python program to demonstrate


# type Casting

# int variable
a=5

# typecast to float
n = float(a)

print(n)
print(type(n))

3.6 Boolean Values


While the integer, floating-point, and string data types have an unlimited number of
possible values, the Boolean data type has only two values: True and False. (Boolean
is capitalized because the data type is named after mathematician George Boole.)

27
When typed as Python code, the Boolean values True and False lack the quotes you
place around strings, and they always start with a capital T or F, with the rest of the
word in lowercase

3.3 Comparison Operators


Comparison operators compare two values and evaluate down to a single Boolean
value. The table below lists the comparison operators.

Operator Meaning

== Equal to

!= Not equal to

< Less than

> Greater than

<= Less than or equal to

>= Greater than or equal to

These operators evaluate to True or False depending on the values you give them. Let
us try some operators now, starting with == and !=.

>>> 42 == 42
True
>>> 42 == 99
False
>>> 2 != 3
True
>>> 2 != 2
False

As you might expect, == (equal to) evaluates to True when the values on both sides
are the same, and != (not equal to) evaluates to True when the two values are
different. The == and != operators can actually work with values of any data type.
28
>>> 'hello' == 'hello'
True
>>> 'hello' == 'Hello'
False
>>> 'dog' != 'cat'
True
>>> True == True
True
>>> True != False
True
>>> 42 == 42.0
True
➊ >>> 42 == '42'
False
Note that an integer or floating-point value will always be unequal to a string value.
The expression 42 == '42' ➊ evaluates to False because Python considers the integer
42 to be different from the string '42'. The <, >, <=, and >= operators, on the
other hand, work properly only with integer and floating-point values.

>>> 42 < 100


True
>>> 42 > 100
False
>>> eggCount = 42
➊ >>> eggCount <= 42
True
>>> myAge = 29
➋ >>> myAge >= 10
True

29
You will often use comparison operators to compare a variable’s value to some other
value.

3.4 Boolean Operators


The three Boolean operators (and, or, and not) are used to compare Boolean values.
Like comparison operators, they evaluate these expressions down to a Boolean value.

3.4.1 Binary Boolean Operators


The and and or operators always take two Boolean values (or expressions), so they
are considered binary operators. The and operator evaluates an expression to True if
both Boolean values are True; otherwise, it evaluates to False. Enter some expressions
using and into the interactive shell to see it in action.
>>> True and True
True
>>> True and False
False
A truth table shows every possible result of a Boolean operator. The table below is
the truth table for the and operator.

Expression Evaluates to

True and True True

True and False False

False and True False

False and False False

On the other hand, the or operator evaluates an expression to True if either of the
two Boolean values is True. If both are False, it evaluates to False.

>>> False or True


True
>>> False or False
False

30
You can see every possible outcome of the or operator in its truth table, shown in the
table below.

Expression Evaluates to

True or True True

True or False True

True or False True

False or True True

False or False False

3.4.2 The not Operator


Unlike and and or, the not operator operates on only one Boolean value (or
expression). The not operator simply evaluates to the opposite Boolean value.

>>> not True


False
➊ >>> not not not not True
True
Much like using double negatives in speech and writing, you can nest not operators
➊, though there’s never not no reason to do this in real programs.

The table below shows the truth table for not.

Expression Evaluates to

not True False

not False True

3.4.3 Mixing Boolean and Comparison Operators


Since the comparison operators evaluate to Boolean values, you can use them in
expressions with the Boolean operators.

31
Recall that the and, or, and not operators are called Boolean operators because they
always operate on the Boolean values True and False. While expressions like 4 < 5
aren’t Boolean values, they are expressions that evaluate down to Boolean values.
Try entering some Boolean expressions that use comparison operators into the
interactive shell.

>>> (4 < 5) and (5 < 6)


True
>>> (4 < 5) and (9 < 6)
False
>>> (1 == 2) or (2 == 2)
True
The computer will evaluate the left expression first, and then it will evaluate the right
expression. When it knows the Boolean value for each, it will then evaluate the
whole expression down to one Boolean value.

3.5 Expressions in Python


An expression is a combination of operators and operands that is interpreted to
produce some other value. In any programming language, an expression is evaluated
as per the precedence of its operators. So that if there is more than one operator in an
expression, their precedence decides which operation will be performed first. We
have many different types of expressions in Python. Let us discuss all types along with
some exemplar codes.

1. Constant Expressions: These expressions have constant values only.


Example:
# Constant Expressions
x = 15 + 1.3
print(x)
2. Arithmetic Expressions: An arithmetic expression is a combination of numeric
values, operators, and sometimes parenthesis. The result of this type of
expression is also a numeric value. The operators used in these expressions are
32
arithmetic operators like addition, subtraction, etc. Here are some arithmetic
operators in Python:

Operators Syntax Functioning


+ x+y Addition
– x–y Subtraction
* x*y Multiplication
/ x/y Division
// x // y Quotient
% x%y Remainder
** x ** y Exponentiation

3. Multiple operators in expression (Operator Precedence)


It is a quite simple process to get the result of an expression if there is only one
operator in an expression. However, if there is more than one operator in an
expression, it may give different results on basis of the order of operators
executed. To sort out these confusions, the operator precedence is defined.
Operator Precedence simply defines the priority of operators that which
operator is to be executed first. Here we see the operator precedence in
Python, where the operator higher in the list has more precedence or priority:

Precedence Name Operator


1 Parenthesis ()[]{}
2 Exponentiation **
3 Unary plus or minus, complement -a , +a , ~a
4 Multiply, Divide, Modulo / * // %
5 Addition & Subtraction + –
6 Shift Operators >> <<
7 Bitwise AND &
8 Bitwise XOR ^
9 Bitwise OR |
10 Comparison Operators >= <= > <
11 Equality Operators == !=
12 Assignment Operators = += -= /=
*=
13 Identity and membership operators is, is not, in, not
in
14 Logical Operators and, or, not

33
Chapter 4: Python String
4.1 Introduction
Strings are amongst the most popular data types in Python. A string is a sequence of
characters, quite simple at first glance, but you can use them in many different ways.
Special functions called string methods are used to manipulate strings. There are string
methods for changing a string from lowercase to uppercase, replacing parts of a string
with different text, and much more

In this chapter, you will learn how to:

● use single, double and triple quotes


● Format string output
● use slicing methods
● use slicing functions/methods
● Use string input and output

Let us get started!

4.2 String
A string is a sequence of characters. We can create them simply by enclosing characters
in quotes. Typing string values in Python code is straightforward: they begin and end
with a single quote. But then, how can you use a quote inside a string? Typing ‘that is
Alice's cat.' Will not work, because Python thinks the string ends after Alice, and the
rest (s cat.') is invalid Python code. Fortunately, there are multiple ways to type
strings.

Double Quotes
Strings can begin and end with double quotes, just as they do with single quotes. One
benefit of using double quotes is that the string can have a single quote character in it.
Enter the following into the interactive shell:

>>> test = "That is Alice's cat."


>>>print(test)

34
Output:

That is Alice’s cat


Since the string begins with a double quote, Python knows that the single quote is
part of the string and not marking the end of the string.

Triple Quotes
While you can use the \n escape character to put a newline into a string, it is often
easier to use multiline strings. A multiline string in Python begins and ends with either
three single quotes or three double quotes. Enter the following into the interactive
shell:

>>> test = ‘’’That


is
Alice's
Cat.’’’
>>>print(test)
Any quotes, tabs, or newlines in between the “triple quotes” are considered part of
the string. Python’s indentation rules for blocks do not apply to lines inside a multiline
string.

4.3 Formatting string output


Suppose you have a string, test = "Alice", and two integers, num1 = 2 and num2 = 3.
You want to display them in the string "Alice has 2 golds and 3 silvers". This is called
string interpolation, which is just a fancy way of saying that you want to insert some
variables into specific locations in a string.

One way to do this is with string concatenation:

>>> test + " has " + str(num1) + " golds and " + str(num2) + " silvers"
'Alice has 2 golds and 3 silvers'

35
This code is not the prettiest and keeping track of what goes inside or outside the
quotes can be tough. Fortunately, there is another way of interpolating strings:
formatted string literals, more commonly known as f-strings.

The easiest way to understand f-strings is to see them in action. Here is what the
above string looks like when written as an f-string:

>>> print(f"{test} has {num1} golds and {num2} silvers")


Alice has 2 golds and 3 silvers

There are two important things to notice about the above example:

1. The string literal starts with the letter f before the opening quotation mark.
2. Variable names surrounded by curly braces ({}) are replaced by their
corresponding values without using str().

You can also insert Python expressions between the curly braces. The expressions are
replaced with their result in the string:

>>> n = 3
>>> m = 4
>>> f"{n} times {m} is {n*m}"
'3 times 4 is 12'

It is a good idea to keep any expressions used in an f-string as simple as possible.


Packing a bunch of complicated expressions into a string literal can result in code that
is difficult to read and difficult to maintain.

Apart from using the f-string for formatting string, python format() function has also
been introduced for handling complex string formatting more efficiently.

This method of the built-in string class provides functionality for complex variable
substitution and value formatting

The general syntax of format() method:

string.format(var1, var2, ….)

36
Formatters work by putting in one or more replacement fields and placeholders
defined by a pair of curly braces {} into a string and calling the str.format() function.

The value we wish to put into the placeholders and concatenate with the string are
passed as parameters into the format function:

name = input("Enter your name: ")

age = input("Enter your age: ")

print("Your name is {} and you are {} years old".format(name, age))

4.4 String Concatenation, Indexing, and Slicing


Now that you know what a string is and how to declare string literals in your code,
let us explore some of the things you can do with strings.

In this section, you will learn about three basic string operations:

1. Concatenation, which joins two strings together

2. Indexing, which gets a single character from a string

3. Slicing, which gets several characters from a string at once

Let us dive in!

String Concatenation
You can combine, or concatenate, two strings using the + operator:

>>> string1 = "Alice"


>>> string2 = "Bob"
>>> string_conc = string1 + string2
>>>string_conc
'AliceBob'
In this example, the string concatenation occurs on the third line. You concatenate
string1 and string2 using +, and then you assign the result to the variable string_conc.
Notice that the two strings are joined without any whitespace between them.

37
String Indexing
Each character in a string has a numbered position called an index. You can access the
character at the nth position by putting the number n between two square brackets ([])
immediately after the string:

>>>test = “Hello, World!”


>>>test[1]
‘e’
test [1] returns the character at position 1 in "Hello, World!", which is e.

Wait. Isn’t H the first character of "Hello, World!"?

In Python—and in most other programming languages—counting always starts at


zero. To get the character at the beginning of a string, you need to access the
character at position 0:

>>> test[0]
‘H’
The following figure shows the index for each character of the string
"Hello, World!":

“ H e l l o , W o r l d ! “

0 1 2 3 4 5 6 7 8 9 10 11 12

If you try to access an index beyond the end of a string, then Python raises an Index
Error:

>>> test[13]
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
test[13]
IndexError: string index out of range

The largest index in a string is always one less than the string’s length. Since "Hello,
World!" has a length of thirteen, the largest index allowed is 12.

38
Strings also support negative indices:

>>> test[-1]
'!'
The last character in a string has index -1, which for "Hello, World!" is the exclamation
point. The second to last character d has index -2, and so on.

The following figure shows the negative index for each character in the string "Hello,
World!":

“ H e l l o , W o r l d ! “

-13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

Just like with positive indices, Python raises an Index Error if you try to access a
negative index less than the index of the first character in the string.

>>> test[-14]
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
test[-14]
IndexError: string index out of range

Negative indices may not seem useful at first, but sometimes they are a better choice
than a positive index.

For example, suppose a string input by a user is assigned to the variable user_input. If
you need to get the last character of the string, how do you know what index to use?
One way to get the last character of a string is to calculate the final index using len():

final_index = len(user_input) - 1
last_character = user_input[final_index]

Getting the final character with the index -1 takes less typing and does not require an
intermediate step to calculate the final index:

last_character = user_input[-1]

39
String Slicing
Suppose you need a string containing just the first three letters of the string "Hello,
World!". You could access each character by index and concatenate them like this:

>>> first_three_letters = test[0] + test[1] + test[2]


>>> first_three_letters
'Hel'

If you need more than just the first few letters of a string, then getting each character
individually and concatenating them together is clumsy and long-winded. Fortunately,
Python provides a way to do this with much less typing.

You can extract a portion of a string, called a substring, by inserting a colon between
two index numbers set inside square brackets like this:

>>> test = "Hello, World!"


>>> test[0:3]
'Hel’

test[0:3] returns the first three characters of the string assigned to test, starting with
the character at index 0 and going up to but not including the character at index 3.
The [0:3] part of the test[0:3] is called a slice. In this case, it returns a slice of "Hello,
World!".

String slices can be confusing because the substring returned by the slice includes the
character whose index is the first number but does not include the character whose
index is the second number.

To remember how slicing works, you can think of a string as a sequence of square
slots. The left and right boundaries of each slot are numbered sequentially from zero
up to the length of the string, and each slot is filled with a character in the string.

Here is what this looks like for the string "Hello, World!":

| H | e | l | l | o | , | W | o | r | l | d | ! |
0 1 2 3 4 5 6 7 8 9 10 11 12

40
So, for "Hello, World", the slice [0:3] returns the string "Hel", and the slice [6:12]
returns the string "World!".

If you omit the first index in a slice, then Python assumes you want to start at index 0:

>>> test[:3]
‘Hel’

The slice [:3] is equivalent to the slice [0:3], so test[:3] returns the first three characters
in the string "Hello, World!". Similarly, if you omit the second index in the slice, then
Python assumes you want to return the substring that begins with the character.

>>> test[6:]
‘World!’

For "Hello, World", the slice [6:] is equivalent to the slice [6:12].
If you omit both the first and second numbers in a slice, you get a string that starts
with the character at index 0 and ends with the last character. In other words,
omitting both numbers in a slice returns the entire string.

It is important to note that, unlike with string indexing, Python will not raise an Index
Error when you try to slice between boundaries that fall outside the beginning or
ending boundaries of a string:

>>> test[:14]
'Hello, World!'
>>> test[15:18]
‘’
In this example, the first line gets the slice from the beginning of the string up to but
not including the fourteenth character. The string assigned to the test has a length of
thirteen, so you might expect Python to throw an error. Instead, it ignores any
nonexistent indices and returns the entire string "Hello, World!".

41
The third line shows what happens when you try to get a slice in which the entire
range is out of bounds. test[15:18] attempts to get the fifteenth and eighteenth
characters, which do not exist. Instead of raising an error, Python returns the empty
string ("").

You can use negative numbers in slices. The rules for slices with negative numbers are
the same as the rules for slices with positive numbers. It helps to visualize the string as
slots with the boundaries labeled with negative numbers:

| H | e | l | l | o | , | W | o | r | l | d | ! |
-12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

Just like before, the slice [x:y] returns the substring starting at index x and going up to
but not including y. For instance, the slice [-12:-9] returns the first three letters of the
string "Hello, World!":

>>> test[-12:-9]
'Hel'

Notice, however, that the rightmost boundary of the string does not have a negative
index. The logical choice for that boundary would seem to be the number 0, but that
does not work.

Instead of returning the entire string, [-12:0] returns the empty string:

>>> test[-12:0]
''

This happens because the second number in a slice must correspond to a boundary
that is to the right of the boundary corresponding to the first number, but both -12
and 0 correspond to the leftmost boundary in the figure.

If you need to include the final character of a string in your slice, then you can omit
the second number:

42
>>> test[-12:]
‘Hello, World!'

Of course, using test[-12:] to get the entire string is a bit odd considering that you can
use the variable test without the slice to get the same result!.

There is an optional third argument, just like in the range statement, that can specify
the step.

>>> name = "Alice"


>>> name[0:5:2]
'Aie'
Steps through the string by twos, selecting the characters at indices 0, 2, and 4.

4.5 String Methods


Strings come bundled with special functions called string methods that you can use to
work with and manipulate strings. There are numerous string methods available, but
we will focus on some of the most commonly used ones.

In this section, you will learn how to:

• Convert a string to uppercase or lowercase

• Determine if a string begins or ends with certain characters

Let us go!

The startswith() and endswith() Methods


The startswith() and endswith() methods return True if the string value they are called
on begins or ends (respectively) with the string passed to the method; otherwise, they
return False. Enter the following into the interactive shell:

>>> test = “Hello, World!”


>>>test.startswith(“Hello”)
True
>>> test.endswith("World!")
True

43
The join() and split() Methods
The join() method is useful when you have a list of strings that need to be joined
together into a single string value. The join() method is called on a string, gets passed
a list of strings, and returns a string. The returned string is the concatenation of each
string in the passed-in list.

For example, enter the following into the interactive shell:

>>>test1 = “Alice”
>>>test2 = “Bob”
>>> “ ”.join([test1, test2])
‘Alice Bob’

Notice that the string join() calls on is inserted between each string of the list
argument. For example, when join([test1, test2]) is called on the “ ” string, the
returned string is 'Alice Bob'.

The split() method does the opposite: It’s called on a string value and returns a list of
strings. Enter the following into the interactive shell:

>>>test = “Alice Bob”


>>>test.split()
[‘Alice’, ‘Bob’]

The find() and replace() Method


One of the most useful string methods is .find(). As its name implies, you can use this
method to find the location of one string in another string—commonly referred to as
a substring.

To use .find(), tack it to the end of a variable or a string literal and pass the string you
want to find in between the parentheses:

>>> test = “I’m a student at MUST”


>>> test.find(“student”)
4

44
The value that .find() returns is the index of the first occurrence of the string you pass
to it. In this case, "student" starts at the fourth character of the string "I’m student at
MUST" which has index 4 because counting starts at 0. If .find() does not find the
desired substring, it will return -1 instead:

>>> test = "I'm student at MUST"


>>> test.find("Student")
-1

If a substring appears more than once in a string, .find() only returns the index of the
first appearance, starting from the beginning of the string:

>>> test = "I'm student and I love my fellow students"


>>> test.find("student")
4
Sometimes you need to find all occurrences of a particular substring and replace them
with a different string. Since .find() only returns the index of the first occurrence of a
substring, you cannot easily use it to perform this operation. Fortunately, string
objects have a .replace() method that replaces each instance of a substring with
another string.

Just like .find(), you tack .replace() on to the end of a variable or string literal. In this
case, though, you need to put two strings inside of the parentheses in .replace() and
separate them with a comma. The first string is the substring to find, and the second
string is the string to replace each occurrence of the substring with.

For example, the following code shows how to replace each occurrence of "MUST" in
the string “I’m student at MUST” with the string “MIT”:

>>> test = "I'm student at MUST"


>>> test.replace("MUST", "MIT")
"I'm student at MIT"

Since strings are immutable objects, .replace() does not alter test If you immediately
type test into the interactive window after running the above example, you will see

45
the original string, unaltered. To change the value of story, you need to reassign to it
the new value returned by .replace():

>>> test = test.replace("MUST", "MIT")


>>> test
"I'm student at MIT"

.replace() can only replace one substring at a time, so if you want to replace multiple
substrings in a string you need to use .replace() multiple times.

The isX() Methods


These methods return a Boolean value that describes the nature of the string. Here are
some common is X string methods:

isalpha(): Returns True if the string consists only of letters and is not blank.
isalnum(): Returns True if the string consists only of letters and numbers and is not
blank.
isdecimal(): Returns True if the string consists only of numeric characters and is not
blank.
isspace(): Returns True if the string consists only of spaces, tabs, and newlines and is
not blank.

istitle(): Returns True if the string consists only of words that begin with an uppercase
letter followed by only lowercase letters.

isupper(): method will return a Boolean True value if the string has at least one letter
and all the letters are uppercase. Otherwise, the method returns False.

islower(): method will return a Boolean True value if the string has at least one letter
and all the letters are lowercase. Otherwise, the method returns False.

Converting String Case


To convert a string to all lowercase letters, you use the string’s .lower() method. This
is done by tacking .lower() onto the end of the string itself:

46
>>>”Hello, World!”.lower()
‘hello, world!’

The dot (.) tells Python that what follows is the name of a method— the lower()
method in this case.

String methods do not just work on string literals. You can also use .lower() on a
string assigned to a variable:

>>>test = “Hello, World!”


>>>test.lower()
‘hello, world!’

The opposite of .lower() is .upper(), which converts every character in a string to


uppercase:

>>>test.upper()
‘HELLO, WORLD!’

Determine the Length of a String


The number of characters contained in a string, including spaces, is called the length of
the string. For example, the string "Alice" has a length of 5, and the string "MUST is
cool" has a length of 12.

To determine a string’s length, you use Python’s built-in len() function. To see how it
works, type the following into IDLE’s interactive window:

>>>test = “MUST is cool”


>>>len(test)
12

len() is a stand-alone function. If you want to determine the length of the name
string, then you call the len() function directly. On the other hand, .upper() and
.lower() must be used in conjunction with a string. They do not exist independently.

47
4.6 Interact With User Input
Now that you have seen how to work with string methods, let us make things
interactive. In this section, you will learn how to get some input from a user with the
input() function. You will write a program that asks a user to input some text and
then display that text back to them in uppercase.

Enter the following into IDLE’s interactive window:

>>> input()

When you press Enter, it looks like nothing happens. The cursor moves to a new line,
but a new >>> does not appear. Python is waiting for you to enter something.
Go ahead and type some text and press Enter:

>>> input()
Hello World!.
'Hello World!.'

The text you entered is repeated on a new line with single quotes. That’s because
input() returns any text entered by the user as a string.

To make input() a bit more user friendly, you can give it a prompt to display to the
user. The prompt is just a string that you put in between the parentheses of input(). It
can be anything you want: a word, a symbol, a phrase—anything that is a valid
Python string.
The input() function displays the prompt and waits for the user to type something on
their keyboard. When the user hits Enter, input() returns their input as a string that
can be assigned to a variable and used to do something in your program. Remember,
input() always returns a string.

To see how input() works, save and run the following script:

48
prompt = "Hey, what's up? "

user_input = input(prompt)

print("You said:", user_input)

When you run this script, you will see Hey, what's up? Displayed in the interactive
window with a blinking cursor.

When you type a response and press Enter, your response is assigned to the
user_input variable.

Here is a sample run of the program:

Hey, what's up? Hello, I'm new here, can you help me please!.
You said: Hello, I'm new here, can you help me please!.

Once you have input from a user, you can do something with it. For example, the
following script takes user input and converts it to uppercase with .upper() and prints
the result:

prompt = "What is the name of your school? "

user_input = input(prompt)

print("You said:", user_input.upper())

What is the name of your School? Malawi University of Science and Technology
You said: MALAWI UNIVERSITY OF SCIENCE AND TECHNOLOGY

49
Chapter 5: Conditional Logic and Flow Control
5.1 Introduction
Nearly all the code you have seen in this book is unconditional. That is, the code does
not make any choices. Every line of code is executed in the order that is written or
that functions are called, with possible repetitions.

In this chapter, you will learn how to write programs that perform different actions
based on different conditions using conditional logic. Paired with if-elif-else statements
and loops, conditional logic allows you to write complex programs that handle many
different situations. Python’s if-elif-else statements allow you to examine the current
state of a program and respond appropriately to that state.

In this chapter, you will learn how to:

● Compare the values of two or more variables


● Write if-elif-else statements to control the flow of your programs
● Apply conditional logic to create simple simulations

Let us get started!

5.2 Conditional Logic


Conditional logic is based on performing different actions depending on whether
some expression, called a conditional, is true or false. This idea is not specific to
computers. Humans use conditional logic all the time to make decisions.

For example, if you score 50% or above in the python test at MUST you are
considered to have passed. The statement “if 50% or above then you have passed” is
an example of conditional logic. The phrase “you score 50% or above” is a
conditional because it may be either true or false.

Boolean expressions
A Boolean expression is an expression that is either true or false. In computer
programming, conditionals often take the form of comparing two values, such as
determining if one value is greater than another, or whether or not two values are
50
equal to each other. A standard set of symbols called relational operators are used to
make comparisons.

The following examples use the operator ==, which compares two operands and
produces True if they are equal and False otherwise:

>>> 2 == 2
True
>>> 2 == 3
False

True and False are special values that belong to the type bool; they are not strings.
Boolean expressions are not limited to comparing numbers. You may also compare
values such as strings.

The following table describes these relational operators:

Relational Operator Example Meaning

> a>b a greater than b

< a<b a less than b

>= a >= b a greater than or equal to b

<= a <= b a less than or equal to b

!= a != b a not equal to b

== a == b a equal to b

Although these operations are probably familiar to you, the Python symbols are
different from the mathematical symbols. A common error is to use a single equal sign
(=) instead of a double equal sign (==). Remember that = is an assignment operator
and == is a relational operator. There is no such thing as =< or =>.

Logical Operators
In addition to relational operators, Python has special keywords called logical
operators that can be used to combine Boolean expressions. There are three logical

51
operators: and, or, and not. The meaning of these operators is similar to their
meaning in English.

For example,

>>>1 < 2 and 3 < 4 is true since 1 is less than 2 and 3 is less than 4. Both conditions
have to be true.

>>>1 < 2 or 3 < 3 is true since one of the conditions is true, that is, 1 is less than 2 is
true. Only the first option or the second option can be true.

Finally, the not keyword reverses the truth-value of a single expression.

>>> not True


False

One thing to keep in mind with not, though, is that it does not always behave the
way you might expect when combined with comparators like ==.

For example, not True == False returns True, but False == not True will raise an
error:

>>>not True == False


True
>>>False == not True
File “<stdin>”, line 1
False == not True
^
SyntaxError: invalid syntax

This happens because Python parses logical operators according to an operator


precedence, just like arithmetic operators have an order of precedence in everyday
math. The order of precedence for logical and relational operators, from highest to
lowest, is described in the following table. Operators on the same row have equal
precedence.

52
Operator Order of Precedence (Highest to Lowest)

<, <=, ==, >=, >

not

and

or

Looking again at the expression, False == not True, not has a lower precedence than
== in the order of operations. This means that when Python evaluates False == not
True, it first tries to evaluate False == not which is syntactically incorrect.

You can avoid the Syntax Error by surrounding not True with parentheses:

>>> False == (not True)


True
Grouping expressions with parentheses is a great way to clarify which operators
belong to which part of a compound expression.

5.3 Controlling the Flow of Your Program


Now that we can compare values to one other with relational operators and build
conditional statements with logical operators, we can add some logic to our code so
that it performs different actions for different conditions. Conditional statements give
us this ability.

The if Statement
An if statement tells Python to only execute a portion of code if a condition is met.
For example, the following if statement will print “Must is cool”. if the conditional 3
+ 3 == 6 is True:

>>> if 3 + 3 == 6:
print("Must is cool.")

Must is cool

53
In English, you can read this as “if 3 + 3 is 6, then print the string ‘Must is cool.’”. The
Boolean expression after if is called the condition. If it is true, the indented statement
runs. If not, nothing happens.

An if statement has three parts:

1. The if keyword
2. A test condition, followed by a colon
3. An indented block of code that is executed if the test condition is True

In the above example, the test condition is 3 +3 == 6. Since this expression is True,
executing the if statement in IDLE displays the text “Must is cool.”.
If the test condition is False (for instance, 3 + 3 == 5), Python skips over the
indented block of code and continues execution on the next non-indented line.

For example, the following if statement does not print anything:


>>> if 3 +3 ==5:
print("Must is cool")

Leaving off the colon (:) after the test condition in an if statement raises a Syntax
Error. Once the indented code block in an if statement is executed, Python will
continue to execute the rest of the program.

Consider the following example:

grade = 95
if grade >= 70:
print("You have passed")

print("Thanks")

The output looks like this:


You have passed
Thanks

54
Since grade is 95, the test condition grade >= 70 is True and the string "You have
passed" is printed. Then the rest of the code is executed and "Thanks" is printed.

If you change the value of grade to 40, the output looks like this:

Thanks

The line print("Thanks") is executed whether or not the grade is greater than or equal
to 70 because it is after the indented code block in the if statement.
A failing student will not know that they failed if all they see from your code is the
text "Thanks".

Let us add another if statement to tell the student they did not pass if their grade is
less than 70:

grade = 40
if grade >= 70:
print("You have passed")
if grade < 70:
print("You failed")
print("Thanks")

The output now looks like this:


You failed
Thanks

In English, we can describe an alternate case with the word “otherwise.” For instance,
“If your grade is 70 or above, you pass. Otherwise, you failed.” Fortunately, there is a
keyword that does for Python what the word “otherwise” does in English.

The else Keyword


The else keyword is used after an if statement in order to execute some code only if
the if statement’s test condition is False.

The following script uses else to shorten the code in the previous script for displaying
whether or not a student passed a test:

55
grade = 40
if grade >= 70:
print("You passed")
else:
print("You failed")
print("Thanks")

The output from the above script is:


You failed
Thanks
In English, the if and else statements together read as ”If the grade is at least 70, then
print the string "You passed"; otherwise, print the string "You failed”.
Notice that the else keyword has no test condition, and is followed by a colon. No
condition is needed, because it executes for any condition that fails the if statement’s
test condition.

As with an if statement, Leaving off the colon (:) from the else keyword will raise a
Syntax Error.

The line that prints "Thanks" still runs, even if the indented block of code after the else
is executed.

The if and else keywords work together nicely if you only need to test a condition
with exactly two states. Sometimes, you need to check three or more conditions. For
that, you use elif statements.

The if-elif-else Chain (elif)


Often, you will need to test more than two possible situations, and to evaluate these
you can use Python’s if-elif-else syntax. Python executes only one block in an if-elif-
else chain. It runs each conditional test in order until one passes. When a test passes,
the code following that test is executed and Python skips the rest of the tests.

Just like if statements, elif statements have three parts:

1. The elif keyword


2. A test condition, followed by a colon
56
3. An indented code block that is executed if the test condition evaluates to True

The following script combines if, elif, and else to print the letter grade a student
earned in a test:

grade = 85
if grade >= 75:
print("You have passed with distinction")
elif grade >=65:
print("you passed with strong credit")
elif grade >= 50:
print("You have passed")
else:
print("Fail")

print("Thanks")

Executing the script has the following output:


You have passed with distinction
Thanks

Leaving off the colon (:) at the end of an elif statement raises a Syntax Error.

The if, elif, and else keywords are some of the most commonly used keywords in the
Python language. They allow you to write code that responds to different conditions
with different behavior.

The if statement allows you to solve more complex problems than code without any
conditional logic. You can even nest an if statement inside another one to write code
that handles tremendously complex logic.

Nested if Statements
You can nest an if statement inside another to create complicated decision-making
structures.

57
Consider the following scenario, if you score marks between 75% – 80% you are
considered to have scored weak distinction while when the score is between 81% –
100% you are considered to have scored strong distinction.

The following program solves this using nested if statements:


grade = 85
if grade >= 75:
if grade <= 80:
print("You have passed with weak distinction")
else:
print("You have passed with strong distinction, keep it up!")
elif grade >=65:
print("you passed with strong credit")
elif grade >= 50:
print("You have passed")
else:
print("Fail")

print("Thanks")
The output of the script depends on the grade. Here is a sample execution using 85%:
You have passed with strong distinction, keep it up!
Thanks

The complexity that results from using deeply nested if statements may make it
difficult to predict how your program will behave under given conditions. For this
reason, nested if statements are generally discouraged.

The while Loop


while loops repeat a section of code while some condition is true.
There are two parts to every while loop:

1. The while statement starts with the while keyword, followed by a test
condition, and ends with a colon (:).
2. The loop body contains the code that is repeated at each step of the loop.
Each line is indented four spaces.

58
When a while loop is executed, Python evaluates the test condition and determines if
it is true or false. If the test condition is true, then the code in the loop body is
executed. Otherwise, the code in the body is skipped and the rest of the program is
executed.

If the test condition is true and the body of the loop is executed, then once Python
reaches the end of the body, it returns to the while statement and re-evaluates the test
condition.

If the test condition is still true, the body is executed again. If it is false, the body is
skipped.
This process repeats repeatedly until the test condition fails, causing Python to loop
over the code in the body of the while loop.

Let us look at an example. Type the following code into the interactive window:
>>> current_number = 1
>>> while current_number <=3:
print("Current Number")
current_number += 1

Current Number
Current Number
Current Number
In the first line, we start counting from 1 by assigning current_number the value 1. The
while loop is then set to keep running as long as the value of current_number is less
than or equal to 3.

The code inside the loop prints the string “Current Number” and then adds 1 to that
value with current_number += 1. (The += operator is shorthand for current_number
= current_number + 1.)

Python repeats the loop as long as the condition current_number <= 3 is true.
Because 1 is less than 3, Python prints first Current Number and then adds 1, making
the current number 2. Because 2 is less than 3, Python prints second Current Number

59
and adds 1 again, making the current number 3. Once the value of current_number is
greater than 3, the loop stops running and the program ends.

If you are not careful, you can create an infnite loop. This happens when the test
condition is always true. An infinite loop never terminates. The loop body keeps
repeating forever.

Here is an example of an infinite loop:

>>> current_number = 1
>>> while current_number < 3:
print("Current Number")

Current Number
Current Number
Current Number
Current Number
……….

The only difference between this while loop and the previous one is that
current_number is never incremented in the loop body. At each step of the loop,
current_number is equal to 1. That means the test condition current_number < 3 is
always true, and the string ‘Current Number’ is printed repeatedly forever.

Let us look at an example of a while loop in practice. One use of a while loop is to
check whether or not user input meets some condition and, if not, repeatedly ask the
user for new input until valid input is received.

For instance, the following program continuously asks a user for a positive number
until a positive number is entered:

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


while num <= 0:
print("Number entered is not positive!")
num = float(input("Enter a positive number:"))

60
First, the user is prompted to enter a positive number. The test condition num <= 0
determines whether or not num is less than or equal to 0.

If num is positive, then the test condition fails. The body of the loop is skipped and
the program ends. Otherwise, if num is 0 or negative, the body of the loop executes.
The user is notified that their input was incorrect, and they are prompted again to
enter a positive number.

while loops are perfect for repeating a section of code while some condition is met.
They are not well suited, however, for repeating a section of code a specific number
of times.

The programs you use every day most likely contain while loops. For example, a
game needs a while loop to keep running as long as you want to keep playing, and so
it can stop running as soon as you ask it to quit. Programs would not be fun to use if
they stopped running before we told them to or kept running even after we wanted
to quit, so while loops are quite useful.

The for Loop


A for loop executes a section of code once for each item in a collection of items. The
number of items in the collection determines the number of times that the code is
executed.
Like its while counterpart, the for loop has two main parts:

1. The for statement begins with the for keyword, followed by a membership
expression, and ends in a colon (:).
2. The loop body contains the code to be executed at each step of the loop, and
is indented four spaces (tab).

Let us look at an example. The following for loop prints each letter of the string
"MUST" one at a time:

61
>>> for new in "MUST":
print(new)
M
U
S
T

In this example, the for statement is for new in "MUST". The membership expression
is new in "MUST". At each step of the loop, the variable new is assigned the next
letter in the string "MUST", and then the value of letter is printed.

The loops runs once for each character in the string "MUST", so the loop body
executes four times.

To see why for loops are better for looping over collections of items, let us rewrite
the for loop in the previous example as a while loop. To do so, we can use a variable
to store the index of the next character in the string. At each step of the loop, we will
print out the character at the current index and then increment the index.

The loop will stop once the value of the index variable is equal to the length of the
string. Remember, indices start at zero, so the last index of the string "MUST" is three.

Here is how you might write that code:

word = "MUST"
index = 0
while index < len(word):
print(word[index])
index = index + 1
Program output:
M
U
S
T
That is significantly more complex than the for loop version. Not only is the for loop
less complex, the code itself looks more natural.

62
Sometimes it is useful to loop over a range of numbers. Python has a handy built-in
function range() that produces just that — a range of numbers.

For example, range(3) returns the range of integers starting with 0 and up to, but not
including, 3. That is, range(3) is the range of numbers 0, 1, and 2.

You can use range(n), where n is any positive number, to execute a loop exactly n
times.

For instance, the following for loop prints the string "MUST" three times:

>>> for n in range(3):


print("MUST")
You can also give a range a starting point. For example, range(1, 5) is the range of
numbers 1, 2, 3, and 4. The first argument is the starting number, and the second
argument is the endpoint, which is not included in the range.

Using the two-argument version of range(), the following for loop prints the square
of every number starting with 10 and up to, but not including, 20:

>>> for n in range(10,20):


print(n * n)

Nested Loops
As long as you indent the code correctly, you can even put loops inside of other
loops.

Type the following into IDLE’s interactive window:

for n in range(1, 4):


for j in range(4, 7):
print(f"n = {n} and j = {j}")

When Python enters the body of the first for loop, the variable n is assigned the value
1. Then the body of the second for loop is executed and j is assigned the value 4. The
first thing printed is n = 1 and j = 4.

63
After executing the print() function, Python returns to the inner for loop, assigns to j
the value of 5, and then prints n = 1 and j = 5. Python does not return the outer for
loop because the inner for loop, which is inside the body of the outer for loop, is not
executed. Next, j is assigned the value 6 and Python prints n = 1 and j = 6. At this
point, the inner for loop is done executing, so control returns to the outer for loop.

The variable n gets assigned the value 2, and the inner for loop executes a second
time. That is, j is assigned the value 4 and n = 2 and j = 4 is printed to the console.

The two loops continue to execute in this fashion, and the final output looks like this:

n = 1 and j = 4
n = 1 and j = 5
n = 1 and j = 6
n = 2 and j = 4
n = 2 and j = 5
n = 2 and j = 6
n = 3 and j = 4
n = 3 and j = 5
n = 3 and j = 6
A loop inside of another loop is called a nested loop , and they come up more often
than you might expect. You can nest while loops inside of for loops, and vice versa,
and even nest loops more than two levels deep!

5.4 Break Out of the Pattern


You learned how to repeat a block of code many times using a for or while loop.
Loops are useful for performing a repetitive task and for applying some processing to
many different inputs.

Combining if statements with for loops opens up powerful techniques for controlling
how code is run.

In this section, you will learn how to write if statements that are nested in for loops
and learn about two keywords — break and continue — that allow you to control
the flow of execution more precisely through a loop.

64
if Statements and for Loops
The block of code in a for loop is just like any other block of code. That means you
can nest an if statement in a for loop just like you can anywhere else in your code.
The following example uses a for loop with an if statement to compute and display
the sum of all even integers less than 50:

sum_of_evens = 0
for n in range(1, 50):
if n % 2 == 0:
sum_of_evens = sum_of_evens + n

print(sum_of_evens)

First, the sum_of_evens variable is initialized to 0. Then the program loops over the
numbers 1 to 49 and adds the even values to sum_of_evens. The final value of
sum_of_evens is 600.

Break
The break keyword tells Python to literally break out of a loop. That is, the loop
stops completely and any code after the loop is executed.

For example, the following code loops over the numbers 1 to 5, but stops the loop
when the number 3 is encountered:

for n in range(1, 6):


if n == 3:
break
print(n)
print(f"Code finished with n = {n}")

Output:
1
2
Code finished with n = 3

65
Continue
The continue keyword is used to skip any remaining code in the loop body and
continue on to the next iteration.

For example, the following code loops over the numbers 1 to 5, printing each number
as is goes, but skips the number 3:

for n in range(1, 6):


if n == 3:
continue
print(n)
print("Code continued without printing 3")

All the numbers except for 3 are printed in the output:


1
2
4
5
Code continued without printing 3

To summarize, the break keyword is used to stop a loop if a certain condition is met,
and the continue keyword is used to skip an iteration of a loop when a certain
condition is met.

66
Chapter 6: Collective Data Types
6.1 Lists
A list is a collection of items in a particular order. In other words, a list is a value that
contains multiple values in an ordered sequence. You can make a list that includes the
letters of the alphabet, the digits from 0–9, or the names of all the people in your
family. This means you can put anything you want into a list, and the items in your
list don’t have to be related in any way. Because a list usually contains more than one
element, it’s a good idea to make the name of your list plural, such as letters, digits,
or names. A list begins with an opening square bracket and ends with a closing square
bracket, []. Values inside the list are also called items. Items are separated with
commas.

A list value looks like this: ['cat', 'bat', 'rat', 'elephant']

Creating Lists
There are several ways to create a new list; the simplest is to enclose the elements in
square brackets ([ and ]):

[10, 20, 30, 40]


['blantyre', 'mzuzu', 'lilongwe']

The first example is a list of four integers. The second is a list of three strings. The
elements of a list don’t have to be the same type. The following list contains a string,
a float and an integer:

['spam', 2.0, 5]

A list that contains no elements is called an empty list; you can create one with empty
brackets, [].

67
As you might expect, you can assign list values to variables:

>>> districts = ['Likoma', 'Mzimba', 'Dedza']


>>> numbers = [117, 1223]
>>> empty = []
>>> print districts, numbers, empty
['Likoma', 'Mzimba', 'Dedza'] [117, 1223] []

Traversing Lists
Lists are ordered collections, so you can access any element in a list by telling Python
the position, or index, of the item desired. To access an element in a list, write the
name of the list followed by the index of the item enclosed in square brackets.

>>> districts = ['zomba', 'balaka', 'ntcheu']


>>> print(districts[0])

Python considers the first item in a list to be at position 0, not position 1. This is true
of most programming languages, and the reason has to do with how the list
operations are implemented at a lower level. If you’re receiving unexpected results,
determine whether you are making a simple off-by-one error. The second item in a
list has an index of 1. Using this simple counting system, you can get any element you
want from a list by subtracting one from its position in the list. For instance, to access
the fourth item in a list, you request the item at index 3.

The following asks for the names at index 1 and index 3:

>>> names = ['Dennis', 'Edward', 'George', 'Doreen']


>>> print(names[1])
Edward
>>> print(names[3])
Doreen

Python has a special syntax for accessing the last element in a list. By asking for the
item at index -1, Python always returns the last item in the list:

68
>>> names = ['Dennis', 'Edward', 'George', 'Doreen']
>>> print(names[-1])
Doreen

This code returns the value Doreen. This syntax is quite useful, because you’ll often
want to access the last items in a list without knowing exactly how long the list is. This
convention extends to other negative index values as well. The index -2 returns the
second item from the end of the list, the index -3 returns the third item from the end,
and so forth.

You will often want to run through all entries in a list, performing the same task with
each item. For example, in a game you might want to move every element on the
screen by the same amount, or in a list of numbers you might want to perform the
same statistical operation on every element. Or perhaps you’ll want to display each
headline from a list of articles on a website. When you want to do the same action
with every item in a list, you can use Python’s for loop.

Let us say we have a list of students’ names, and we want to print out each name in
the list. We could do this by retrieving each name from the list individually, but this
approach could cause several problems. For one, it would be repetitive to do this
with a long list of names. Also, we’d have to change our code each time the list’s
length changed. A for loop avoids both issues by letting Python manage these issues
internally.

Let’s use a for loop to print out each name in a list of students:

1- students = ['Jessica', 'David', 'Joseph']


2- for student in students:
3- print(students)

We begin by defining a list at 1. At 2, we define a for loop. This line tells Python to
pull a name from the list students and store it in the variable student. At 3 we tell
Python to print the name that was just stored in student. Python then repeats lines 2

69
and 3, once for each name in the list. It might help to read this code as “For every
student in the list of students, print the student’s name.”

The output is a simple printout of each name in the list:

Jessica
David
Joseph

Slices in Lists
Just as an index can get a single value from a list, a slice can get several values from a
list, in the form of a new list. A slice is typed between square brackets, like an index,
but it has two integers separated by a colon. Notice the difference between indexes
and slices.

• spam[2] is a list with an index (one integer).

• spam[1:4] is a list with a slice (two integers).

In a slice, the first integer is the index where the slice starts. The second integer is the
index where the slice ends. A slice goes up to, but will not include, the value at the
second index. A slice evaluates to a new list value. Enter the following into the
interactive shell:

>>> spam = ['cat', 'bat', 'rat', 'elephant']


>>> spam[0:4]
['cat', 'bat', 'rat', 'elephant']
>>> spam[1:3]
['bat', 'rat']
>>> spam[0:-1]
['cat', 'bat', 'rat']

As a shortcut, you can leave out one or both of the indexes on either side of the
colon in the slice. Leaving out the first index is the same as using 0, or the beginning
of the list. Leaving out the second index is the same as using the length of the list,
which will slice to the end of the list. Enter the following into the interactive shell:

70
>>> spam = ['cat', 'bat', 'rat', 'elephant']
>>> spam[:2]
['cat', 'bat']
>>> spam[1:]
['bat', 'rat', 'elephant']
>>> spam[:]
['cat', 'bat', 'rat', 'elephant']

Changing Values in a List with Indexes


Normally, a variable name goes on the left side of an assignment statement, like spam
= 42. However, you can also use an index of a list to change the value at that index.
For example, spam[1] = 'aardvark' means “Assign the value at index 1 in the list spam
to the string 'aardvark'.” Enter the following into the

interactive shell:

>>> spam = ['cat', 'bat', 'rat', 'elephant']


>>> spam[1] = 'aardvark'
>>> spam
['cat', 'aardvark', 'rat', 'elephant']
>>> spam[2] = spam[1]
>>> spam
['cat', 'aardvark', 'aardvark', 'elephant']
>>> spam[-1] = 12345
>>> spam
['cat', 'aardvark', 'aardvark', 12345]

In-operator
You can determine whether a value is or is not in a list with the in and not in
operators. Like other operators, in and not in are used in expressions and connect two
values: a value to look for in a list and the list where it may be found. These
expressions will evaluate to a Boolean value. Enter the following into the interactive
shell:

71
>>> 'howdy' in ['hello', 'hi', 'howdy', 'heyas']
True
>>> spam = ['hello', 'hi', 'howdy', 'heyas']
>>> 'cat' in spam
False
>>> 'howdy' not in spam
False
>>> 'cat' not in spam
True

For example, the following program lets the user type in a pet name and then checks
to see whether the name is in a list of pets.

myPets = ['Zophie', 'Pooka', 'Fat-tail']


print('Enter a pet name:')
name = input()
if name not in myPets:
print('I do not have a pet named ' + name)
else:
print(name + ' is my pet.')

The output may look something like this:

Enter a pet name:

Footfoot
I do not have a pet named Footfoot

Built-in List Functions


Append, Insert

To add new values to a list, use the append() and insert() methods. Enter the
following into the interactive shell to call the append() method on a list value stored
in the variable spam:

72
>>> spam = ['cat', 'dog', 'bat']
>>> spam.append('moose')
>>> spam
['cat', 'dog', 'bat', 'moose']

The append() method call adds the argument (covered in next topic) to the end of
the list. The insert() method can insert a value at any index in the list. The first
argument to insert() is the index for the new value, and the second argument is the
new value to be inserted. Enter the following into the interactive shell:

>>> spam = ['cat', 'dog', 'bat']


>>> spam.insert(1, 'chicken')
>>> spam
['cat', 'chicken', 'dog', 'bat']

Notice that the code is spam.append('moose') and spam.insert(1, 'chicken'), not spam
= spam.append('moose') and spam = spam.insert(1, 'chicken'). Neither append() nor
insert() gives the new value of spam as its return value. Rather, the list is modified in
place.

Remove, Del, Pop

The remove() method is passed the value to be removed from the list it is called on.
Enter the following into the interactive shell:

>>> spam = ['cat', 'bat', 'rat', 'elephant']


>>> spam.remove('bat')
>>> spam
['cat', 'rat', 'elephant']

Attempting to delete a value that does not exist in the list will result in a ValueError
error. If the value appears multiple times in the list, only the first instance of the value
will be removed. The remove() method is useful when you know the value you want
to remove from the list.

73
You can remove an item from any position in a list using the del statement. The del
statement is good to use when you know the index of the value you want to remove
from the list. For example:

>>> spam = ['cat', 'bat', 'rat', 'elephant']


>>> del spam[1]
>>> spam
['cat', 'rat', 'elephant']

You may decide that you want to remove a specific item from a list. For example, say
you are writing a program that stores a list of books available in a library. When a
book is checked out, you may want to remove and return the book from your list of
available books.

The Python language includes a built-in function that can be used to remove an
element from a list: pop(). The pop() method removes an element from a specified
position in a list and returns the deleted item. If no position is specified, the last item
in the list is removed.

>>> motorcycles = ['honda', 'yamaha', 'suzuki']


>>> print(motorcycles)
['honda', 'yamaha', 'suzuki']
>>> popped_motorcycle = motorcycles.pop()
>>> print(motorcycles)
['honda', 'yamaha']
>>> print(popped_motorcycle)
Suzuki

Sort

Lists of number values or lists of strings can be sorted with the sort() method. For
example:

74
>>> spam = [2, 5, 3.14, 1, -7]
>>> spam.sort()
>>> spam
[-7, 1, 2, 3.14, 5]
>>> spam = ['ants', 'cats', 'dogs', 'badgers', 'elephants']
>>> spam.sort()
>>> spam
['ants', 'badgers', 'cats', 'dogs', 'elephants']

You can also pass True for the reverse keyword argument to have sort() sort the
values in reverse order. For example:

>>> spam.sort(reverse=True)
>>> spam
['elephants', 'dogs', 'cats', 'badgers', 'ants']

There are three things you should note about the sort() method.

First, the sort() method sorts the list in place; don’t try to capture the return value by
writing code like spam = spam.sort().

Second, you cannot sort lists that have both number values and string values in them,
since Python doesn’t know how to compare these values. For example:

>>> spam = [1, 3, 2, 4, 'Alice', 'Bob']


>>> spam.sort()
Traceback (most recent call last):
File "<pyshell#70>", line 1, in <module>
spam.sort()
TypeError: '<' not supported between instances of 'str' and 'int'

Third, sort() uses “ASCIIbetical order” rather than actual alphabetical order for sorting
strings. This means uppercase letters come before lowercase letters. Therefore, the
lowercase a is sorted so that it comes after the uppercase Z. For an example, enter the
following into the interactive shell:

75
>>> spam = ['Alice', 'ants', 'Bob', 'badgers', 'Carol', 'cats']
>>> spam.sort()
>>> spam
['Alice', 'Bob', 'Carol', 'ants', 'badgers', 'cats']

If you need to sort the values in regular alphabetical order, pass str.lower for the key
keyword argument in the sort() method call.

>>> spam = ['a', 'z', 'A', 'Z']


>>> spam.sort(key=str.lower)
>>> spam
['a', 'A', 'z', 'Z']

This causes the sort() function to treat all the items in the list as if they were lowercase
without actually changing the values in the list.

TIP

To maintain the original order of a list but present it in a sorted order, you can use
the sorted() function. The sorted() function lets you display your list in a particular
order but doesn’t affect the actual order of the list. Syntax: sorted(<list>).

LEN

The len() function will return the number of values that are in a list value passed to it,
just like it can count the number of characters in a string value. Enter the following
into the interactive shell:

>>> spam = ['cat', 'dog', 'moose']


>>> len(spam)
3

76
Random.choice, random.shuffle

The random module has a couple functions that accept lists for arguments. The
random.choice() function will return a randomly selected item from the list. For
example:

>>> import random


>>> pets = ['Dog', 'Cat', 'Moose']
>>> random.choice(pets)
'Dog'
>>> random.choice(pets)
'Cat'
>>> random.choice(pets)
'Cat'

The random.shuffle() function will reorder the items in a list. This function modifies
the list in place, rather than returning a new list. For example:

>>> import random


>>> people = ['Alice', 'Bob', 'Carol', 'David']
>>> random.shuffle(people)
>>> people
['Carol', 'David', 'Alice', 'Bob']
>>> random.shuffle(people)
>>> people
['Alice', 'David', 'Bob', 'Carol']

List Comprehension
List comprehension offers a shorter syntax when you want to create a new list based
on the values of an existing list.

Example:

Based on a list of fruits, you want a new list, containing only the fruits with the letter
"a" in the name.

Without list comprehension you will have to write a for statement with a conditional
test inside:
77
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
newlist = []

for x in fruits:
if "a" in x:
newlist.append(x)

print(newlist)

With list comprehension you can do all that with only one line of code:
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]

newlist = [x for x in fruits if "a" in x]

print(newlist)

The Syntax
newlist = [expression for item in iterable if condition == True]
The return value is a new list, leaving the old list unchanged.

Expression
The expression is the current item in the iteration, but it is also the outcome, which
you can manipulate before it ends up like a list item in the new list:

newlist = [x.upper() for x in fruits]


#This sets the values in the new list to upper case

You can set the outcome to whatever you like:

newlist = ['hello' for x in fruits]


#Set all values in the new list to ‘hello’

Iterable
The iterable can be any iterable object, like a list, tuple, set etc.

newlist = [x for x in districts]

78
Same example, but with a condition:

newlist = [x for x in range(10) if x < 5]


#Accept only numbers lower than 5

Condition
The condition is like a filter that only accepts the items that valuate to True.
newlist = [x for x in fruits if x != "apple"]
#Only accept items that are not “apple”
The condition if x != "apple" will return True for all elements other than "apple",
making the new list contain all fruits except "apple".
The condition is optional and can be omitted:
newlist = [x for x in fruits]
#With no if statement

6.2 Multidimensional Lists


['spam', 2.0, 5, [10, 20]]
A list within another list is nested. There can be more than one additional dimension
to lists in Python. Keeping in mind that a list can hold other lists, that basic principle
can be applied over and over. Multi-dimensional lists are the lists within lists. Usually,
a dictionary will be the better choice rather than a multi-dimensional list in Python.
All methods in previous chapter work for multidimensional lists.

6.3 Lists vs Tuples vs Dictionaries


Lists work well for storing sets of items that can change throughout the life of a
program. The ability to modify lists is particularly important when you are working
with a list of users on a website or a list of characters in a game. However, sometimes
you will want to create a list of items that cannot change. Tuples allow you to do just
that. Python refers to values that cannot change as immutable, and an immutable list
is called a tuple. A tuple looks just like a list except you use parentheses instead of
square brackets. Once you define a tuple, you can access individual elements by using
each item’s index, just as you would for a list.

79
For example, if we have a rectangle that should always be a certain size, we can
ensure that its size doesn’t change by putting the dimensions into a tuple:

>>> dimensions = (200, 50)


>>> print(dimensions[0])

A dictionary is a key:value pair, similar to an associative array found in other


programming languages. A dictionary is like an address-book where you can find the
address or contact details of a person by knowing only his/her name i.e. we associate
keys (name) with values (details). Note that the key must be unique just like you
cannot find out the correct information if you have two persons with the exact same
name. For example:

my_dictionary = {1: 'one', 2: 'two', 3: 'three'}

6.4 Traversing Dictionaries


The Python dictionary allows the programmer to iterate over its keys using a simple
for loop. Let’s take a look:

my_dictionary = {1: 'one', 2: 'two', 3: 'three'}


for key in my_dictionary:
print(key)
Output
1
2
3

Python 3 changed things up a bit when it comes to dictionaries. In Python 2, you


could call the dictionary’s keys() and values() methods to return Python lists of keys
and values respectively:

80
But in Python 3, you will get views returned:

# Python 3

>>> my_dictionary = {1: 'one', 2: 'two', 3: 'three'}


>>> my_dictionary.keys()
dictionary_keys([1, 2, 3])
>>> my_dictionary.values()
dictionary_values(['one', 'two', 'three'])
>>> my_dictionary.items()
dictionary_items([(1, 'one'), (2, 'two'), (3, 'three')])

A view object has some similarities to the range object we saw earlier — it is a lazy
promise, to deliver its elements when they are needed by the rest of the program. We
can iterate over the view, or turn the view into a list like this:

>>> my_dictionary = {1: 'one', 2: 'two', 3: 'three'}


>>> print(list(my_dictionary.keys()))
[1, 2, 3]

The values method is similar; it returns a view object which can be turned into a list:
>>> my_dictionary = {1: 'one', 2: 'two', 3: 'three'}
>>> print(list(my_dictionary.values()))
['one', 'two', 'three']

Alternatively, to get list of keys as an array from dictionary in Python 3, You can use *
operator to unpack dictionary_values:

>>> my_dictionary = {1: 'one', 2: 'two', 3: 'three'}


>>> print([*my_dictionary.keys()])
[1, 2, 3]
>>> my_dictionary = {1: 'one', 2: 'two', 3: 'three'}
>>> print([*my_dictionary.values()])
['one', 'two', 'three']

81
Restrictions on Dictionary Keys
Almost any type of value can be used as a dictionary key in Python, e.g. integer, float,
and Boolean objects. However, there are a couple restrictions that dictionary keys
must abide by.

First, a given key can appear in a dictionary only once. Duplicate keys are not
allowed.

Secondly, a dictionary key must be of a type that is immutable. A tuple can also be a
dictionary key because tuples are immutable:

>>> d = {(1, 1): 'a', (1, 2): 'b', (2, 1): 'c', (2, 2): 'd'}
>>> d[(1,1)]
'a'
>>> d[(2,1)]
'c'

However, neither a list nor another dictionary can serve as a dictionary key, because
lists and dictionaries are mutable.

Restrictions on Dictionary Values


By contrast, there are no restrictions on dictionary values. Literally none at all. A
dictionary value can be any type of object Python supports, including mutable types
like lists and dictionaries, and user-defined objects, which you will learn about in
upcoming tutorials.

There is also no restriction against a particular value appearing in a dictionary multiple


times:

To check if a key exists in a Python dictionary, there is often a need to extract the
value of a given key from a dictionary; however, it is not always guaranteed that a
specific key exists in the dictionary.

When you index a dictionary with a key that does not exist, it will throw an error.

82
Hence, it is a safe practice to check whether or not the key exists in the dictionary
prior to extracting the value of that key. For that purpose, Python offers two built-in
functions:

has_key()
if-in statement

However, the has_key method has been removed from Python3.

The code snippet below illustrates the usage of the if-in statement to check for the
existence of a key in a dictionary:

>>> Stocks = {'a': "Apple", 'b':"Microsoft", 'c':"Google"}


>>> key_to_lookup = 'a'
>>> if key_to_lookup in Stocks:
>>> print "Key exists"
>>> else:
>>> print "Key does not exist"

83
Chapter 7: Functions
7.1 Writing pseudocode
Pseudo code is a term which is often used in programming and algorithm-based fields.
It is a methodology that allows the programmer to represent the implementation of
an algorithm. Simply, we can say that it’s the cooked-up representation of an
algorithm. Often at times, algorithms are represented with the help of pseudo codes
as they can be interpreted by programmers no matter what their programming
background or knowledge is. Pseudo code, as the name suggests, is a false code or a
representation of code which can be understood by even a layman with some school
level programming knowledge.

Algorithm: It’s an organized logical sequence of the actions or the approach towards a
particular problem. A programmer implements an algorithm to solve a problem.
Algorithms are expressed using natural verbal but somewhat technical annotations.

Pseudo code: It’s simply an implementation of an algorithm in the form of


annotations and informative text written in plain English. It has no syntax like any of
the programming language and thus can’t be compiled or interpreted by the
computer.

Advantages of Pseudocode
Improves the readability of any approach. It’s one of the best approaches to start
implementation of an algorithm.

Acts as a bridge between the program and the algorithm or flowchart. Also works as a
rough documentation, so the program of one developer can be understood easily
when a pseudo code is written out. In industries, the approach of documentation is
essential. And that’s where a pseudo-code proves vital.

The main goal of a pseudo code is to explain what exactly each line of a program
should do, hence making the code construction phase easier for the programmer.

How to write a Pseudo-code?


Arrange the sequence of tasks and write the pseudocode accordingly.
84
Start with the statement of a pseudo code which establishes the main goal or the aim.

Example:

This program will allow the user to check the number whether it's even or odd.

The way the if-else, for, while loops are indented in a program, indent the statements
likewise, as it helps to comprehend the decision control and execution mechanism.
They also improve the readability to a great extent.

Example:

if "1"
print response
"I am case 1"
if "2"
print response
"I am case 2"

Use appropriate naming conventions. The human tendency follows the approach to
follow what we see. If a programmer goes through a pseudo code, his approach will
be the same as per it, so the naming must be simple and distinct.

Use appropriate sentence casings, such as CamelCase for methods, upper case for
constants and lower case for variables.

Elaborate everything which is going to happen in the actual code. Don’t make the
pseudo code abstract.

Use standard programming structures such as ‘if-then’, ‘for’, ‘while’, ‘cases’ the way
we use it in programming.

Check whether all the sections of a pseudo code is complete, finite and clear to
understand and comprehend.

Don’t write the pseudo code in a complete programmatic manner. It is necessary to


be simple to understand even for a layman or client, hence don’t incorporate too
many technical terms.

85
7.2 Functions
A function is a named block of code that is designed to do one specific job. When you
want to perform a particular task that you have defined in a function, you call the
name of the function responsible for it. If you need to perform that task multiple
times throughout your program, you do not need to type all the code for the same
task again and again; you just call the function dedicated to handling that task, and
the call tells Python to run the code inside the function.

Here’s a simple function named greet_user() that prints a greeting:

1- def greet_user():
2- """Display a simple greeting."""
3- print("Hello!")
4- greet_user()

This example shows the simplest structure of a function. The line at 1 uses the
keyword def to inform Python that you’re defining a function. This is the function
definition, which tells Python the name of the function and, if applicable, what kind
of information the function needs to do its job. The parentheses hold that
information. In this case, the name of the function is greet_user(), and it needs no
information to do its job, so its parentheses are empty. (Even so, the parentheses are
required.) Finally, the definition ends in a colon.

Any indented lines that follow def greet_user(): make up the body of the function.
The text at 2 is a comment called a docstring, which describes what the function does.
Docstrings are enclosed in triple quotes, which Python looks for when it generates
documentation for the functions in your programs.

The line print("Hello!") is the only line of actual code in the body of this function, so
greet_user() has just one job: print("Hello!"). When you want to use this function, you
call it. A function call tells Python to execute the code in the function. To call a
function, you write the name of the function, followed by any necessary information
in parentheses, as shown at 4. Because no information is needed here, calling our
function is as simple as entering greet_user(). As expected, it prints Hello!.
86
Defining function parameters
Parameters vs Arguments

1- def greet_user(username):
2- """Display a simple greeting."""
3- print("Hello, " + username.title() + "!")
4- greet_user('jesse')

Entering greet_user('jesse') calls greet_user() and gives the function the information it
needs to execute the print statement. The function accepts the name you passed it and
displays the greeting for that name:

Hello, Jesse!

In the preceding greet_user() function, we defined greet_user() to require a value for


the variable username. Once we called the function and gave it the information (a
person’s name), it printed the right greeting. The variable username in the definition
of greet_user() is an example of a parameter, a piece of information the function
needs to do its job. The value 'jesse' in greet user('jesse') is an example of an
argument. An argument is a piece of information that is passed from a function call to
a function. When we call the function, we place the value we want the function to
work with in parentheses. In this case the argument 'jesse' was passed to the function
greet_user(), and the value was stored in the parameter username.

Because a function definition can have multiple parameters, a function call may need
multiple arguments. You can pass arguments to your functions in a number of ways.
You can use positional arguments, which need to be in the same order the parameters
were written; keyword arguments, where each argument consists of a variable name
and a value; and lists and dictionaries of values.

Positional Arguments
When you call a function, Python must match each argument in the function call with
a parameter in the function definition. The simplest way to do this is based on the
order of the arguments provided. Values matched up this way are called positional

87
arguments. To see how this works, consider a function that displays information
about pets. The function tells us what kind of animal each pet is and the pet’s name,
as shown here:

def describe_pet(animal_type, pet_name):


"""Display information about a pet."""
print("My " + animal_type + "'s name is " + pet_name + ".")
describe_pet('hamster', 'harry')

The definition shows that this function needs a type of animal and the animal’s name.
When we call describe_pet(), we need to provide an animal type and a name, in that
order. For example, in the function call, the argument 'hamster' is stored in the
parameter animal_type and the argument 'harry' is stored in the parameter pet_name.
In the function body, these two parameters are used to display information about the
pet being described.

The output describes a hamster named Harry:

My hamster's name is Harry.

Multiple Function Calls

You can call a function as many times as needed. Describing a second, different pet
requires just one more call to describe_pet():

def describe_pet(animal_type, pet_name):


"""Display information about a pet."""
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')

In this second function call, we pass describe_pet() the arguments 'dog' and 'willie'. As
with the previous set of arguments we used, Python matches 'dog' with the parameter
animal_type and 'willie' with the parameter pet_name.

88
As before, the function does its job, but this time it prints values for a dog named
Willie. Now we have a hamster named Harry and a dog named Willie:

My hamster's name is Harry.


My dog's name is Willie.

Calling a function multiple times is a very efficient way to work. The code describing
a pet is written once in the function. Then, anytime you want to describe a new pet,
you call the function with the new pet’s information.

Even if the code for describing a pet were to expand to ten lines, you could still
describe a new pet in just one line by calling the function again.

You can use as many positional arguments as you need in your functions. Python
works through the arguments you provide when calling the function and matches
each one with the corresponding parameter in the function’s definition.

Order Matters in Positional Arguments

You can get unexpected results if you mix up the order of the arguments in a function
call when using positional arguments:

def describe_pet(animal_type, pet_name):


"""Display information about a pet."""
print("I have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet('harry', 'hamster')

In this function call we list the name first and the type of animal second. Because the
argument 'harry' is listed first this time, that value is stored in the parameter
animal_type. Likewise, 'hamster' is stored in pet_name. Now we have a “harry”
named “Hamster”:

I have a harry.
My harry's name is Hamster.

89
If you get funny results like this, check to make sure the order of the arguments in
your function call matches the order of the parameters in the function’s definition.

Keyword Arguments
A keyword argument is a name-value pair that you pass to a function. You directly
associate the name and the value within the argument, so when you pass the
argument to the function, there’s no confusion (you won’t end up with a harry
named Hamster). Keyword arguments free you from having to worry about correctly
ordering your arguments in the function call, and they clarify the role of each value in
the function call.

Let’s rewrite snippet above using keyword arguments to call describe_pet():

def describe_pet(animal_type, pet_name):


"""Display information about a pet."""
print("\nI have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(animal_type='hamster', pet_name='harry')

The function describe_pet() hasn’t changed. But when we call the function, we
explicitly tell Python which parameter each argument should be matched with. When
Python reads the function call, it knows to store the argument 'hamster' in the
parameter animal_type and the argument 'harry' in pet_name. The output correctly
shows that we have a hamster named Harry.

The order of keyword arguments doesn’t matter because Python knows where each
value should go. The following two function calls are equivalent:

describe_pet(animal_type='hamster', pet_name='harry')
describe_pet(pet_name='harry', animal_type='hamster')

Default Values
When writing a function, you can define a default value for each parameter. If an
argument for a parameter is provided in the function call, Python uses the argument
value. If not, it uses the parameter’s default value. So, when you define a default

90
value for a parameter, you can exclude the corresponding argument you’d usually
write in the function call. Using default values can simplify your function calls and
clarify the ways in which your functions are typically used.

For example, if you notice that most of the calls to describe_pet() are being used to
describe dogs, you can set the default value of animal_type to 'dog'. Now anyone
calling describe_pet() for a dog can omit that information:

def describe_pet(pet_name, animal_type='dog'):


"""Display information about a pet."""
print("I have a " + animal_type + ".")
print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='willie')

We changed the definition of describe_pet() to include a default value, 'dog', for


animal_type. Now when the function is called with no animal_type specified, Python
knows to use the value 'dog' for this parameter:

I have a dog.
My dog's name is Willie.

Note that the order of the parameters in the function definition had to be changed.
Because the default value makes it unnecessary to specify a type of animal as an
argument, the only argument left in the function call is the pet’s name. Python still
interprets this as a positional argument, so if the function is called with just a pet’s
name, that argument will match up with the first parameter listed in the function’s
definition. This is the reason the first parameter needs to be pet_name. The simplest
way to use this function now is to provide just a dog’s name in the function call:

describe_pet('willie')

This function call would have the same output as the previous example. The only
argument provided is 'willie', so it is matched up with the first parameter in the
definition, pet_name. Because no argument is provided for animal_type, Python uses

91
the default value 'dog'. To describe an animal other than a dog, you could use a
function call like this:

describe_pet(pet_name='harry', animal_type='hamster')

Because an explicit argument for animal_type is provided, Python will ignore the
parameter’s default value.

The Return Statement


A function doesn’t always have to display its output directly. Instead, it can process
some data and then return a value or set of values. The value the function returns is
called a return value. The return statement takes a value from inside a function and
sends it back to the line that called the function. Return values allow you to move
much of your program’s grunt work into functions, which can simplify the body of
your program.

Let’s look at a function that takes a first and last name, and returns a neatly formatted
full name:

def get_formatted_name(first_name, last_name):


"""Return a full name, neatly formatted."""
full_name = first_name + ' ' + last_name
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)

The definition of get_formatted_name() takes as parameters a first and last name. The
function combines these two names, adds a space between them, and stores the result
in full_name. The value of full_name is converted to title case, and then returned to
the calling. When you call a function that returns a value, you need to provide a
variable where the return value can be stored. In this case, the returned value is stored
in the variable musician. The output shows a neatly formatted name made up of the
parts of a person’s name:

92
Jimi Hendrix

This might seem like a lot of work to get a neatly formatted name when we could
have just written:

print("Jimi Hendrix")

But when you consider working with a large program that needs to store many first
and last names separately, functions like get_formatted_name() become very useful.
You store first and last names separately.

93
Chapter 8: An Introduction to a Few OOP Concepts
8.1 Definitions
Class − A user-defined prototype for an object that defines a set of attributes that
characterize any object of the class. The attributes are data members (class variables
and instance variables) and methods, accessed via dot notation.

Class variable − A variable that is shared by all instances of a class. Class variables are
defined within a class but outside any of the class's methods. Class variables are not
used as frequently as instance variables are.

Data member − A class variable or instance variable that holds data associated with a
class and its objects.

Function overloading − The assignment of more than one behavior to a particular


function. The operation performed varies by the types of objects or arguments
involved.

Instance variable − A variable that is defined inside a method and belongs only to the
current instance of a class.

Inheritance − The transfer of the characteristics of a class to other classes that are
derived from it.

Instance − An individual object of a certain class. An object obj that belongs to a class
Circle, for example, is an instance of the class Circle.

Instantiation − The creation of an instance of a class.

Method − A special kind of function that is defined in a class definition.

Object − A unique instance of a data structure that's defined by its class. An object
comprises both data members (class variables and instance variables) and methods.

94
8.2 Python is object oriented
Classes provide a means of bundling data and functionality together. Creating a new
class creates a new type of object, allowing new instances of that type to be made.
Each class instance can have attributes attached to it for maintaining its state. Class
instances can also have methods (defined by its class) for modifying its state.

Compared with other programming languages, Python’s class mechanism adds classes
with a minimum of new syntax and semantics. It is a mixture of the class mechanisms
found in C++ and Modula-3. Python classes provide all the standard features of
Object Oriented Programming: the class inheritance mechanism allows multiple base
classes, a derived class can override any methods of its base class or classes, and a
method can call the method of a base class with the same name. Objects can contain
arbitrary amounts and kinds of data. As is true for modules, classes partake of the
dynamic nature of Python: they are created at runtime, and can be modified further
after creation.

Python is an object-oriented programming language, and we have in fact been using


many object oriented concepts already. The key notion is that of an object. An object
consists of two things: data and functions (called methods) that work with that data.
As an example, strings in Python are objects. The data of the string object is the actual
characters that make up that string. The methods are things like lower, replace, and
split. In Python, everything is an object. That includes not only strings and lists, but
also integers, floats, and even functions themselves.

What is a class?
A class is a template for objects. It contains the code for all the object’s methods.
Below is an example:

Class creation- example 1

95
Point to note

 To create a class, we use the class statement. Class names usually start with a
capital.
 Most classes will have a method called __init__. The underscores indicate that
it is a special kind of method. It is called a constructor, and it is automatically
called when someone creates a new object from your class. The constructor is
usually used to set up the class’s variables. In the above program, the
constructor takes two values, a and b, and assigns the class variables a and b to
those values.
 The first argument to every method in your class is a special variable called self.
Every time your class refers to one of its variables or methods, it must precede
them by self. The purpose of self is to distinguish your class’s variables and
methods from other variables and functions in the program.
 To create a new object from the class, you call the class name along with any
values that you want to send to the constructor. You will usually want to
assign it to a variable name. This is what the line e=Example (8, 6) does.
 To use the object’s methods, use the dot operator, as in e.addmod().

Class creation- example 2

The class statement creates a new class definition. The name of the class in this case
Student immediately follows the keyword class followed by a colon as follows:

96
The class has a documentation string, which can be accessed via Student.__doc__.
Class creation- example 3

The variable empCount is a class variable whose value is shared among all instances of
a class. This can be accessed as Employee.empCount from inside the class or outside
the class.The first method __init__() is a special method, which is called class
constructor or initialization method that Python calls when you create a new instance
of this class.

You declare other class methods like normal functions with the exception that the first
argument to each method is self. Python adds the self argument to the list for you;
you do not need to include it when you call the methods.

97
8.3 Creating Instance Objects
To create instances of a class, you call the class using class name and pass in whatever
arguments its __init__ method accepts.

Accessing Attributes
You access the object's attributes using the dot operator with object. Class variable
would be accessed using class name as follows:

Built-In Class Attributes


Every Python class keeps following built-in attributes and they can be accessed using
dot operator like any other attribute:

__dict__ − Dictionary containing the class's namespace.

__doc__ − Class documentation string or none, if undefined.

__name__ − Class name.

98
Chapter 9: Errors and Exceptions in Python
It is not all the times that the programs that we write get executed correctly.
Computer programs are written by humans who are not machines hence there is
always room for them to make some errors as they are writing these programs.
Unlike in other programming languages where errors and exceptions are the same
thing, python tries to make a distinction between errors and exceptions.

Errors cannot be handled, while Python exceptions can be handled at the run time.
An error can be a syntax (parsing) error, while there can be many types of exceptions
that could occur during the execution. An Error might indicate critical problems that a
reasonable application should not try to catch, while an Exception might indicate
conditions that an application should try to catch. Errors are mostly caused by the
environment in which an application is running while the application itself causes
exceptions. Errors are a form of an unchecked exception and are irrecoverable like an
OutOfMemoryError.

Examples of errors in python

1. Syntax error
2. Recursion error
3. Out of memory error
4. Indentation error

Examples of exceptions in python

1. Type error
2. Value error
3. Attribute error
4. Key error
5. Index error
6. Import error
7. Assertion error
8. Overflow error

99
9. Floating point error
10. Zero division error
11. Division by Zero
12. Accessing a file which does not exist.
13. Addition of two incompatible types
14. Trying to access a nonexistent index of a sequence
15. Removing the table from the disconnected database server.
16. ATM withdrawal of more than the available amount

8.4 Importance of Handling Exceptions


1. Exception handling allows you to separate error-handling code from normal
code.
2. As with code comments, exceptions helps you to remind yourself of what the
program expects.
3. It clarifies the code and enhances readability.
4. Raising an exception helps you to break the current code execution and returns
the exception back to expection until it is handled.
5. Makes the program more robust by eliminating potential failures when it is
deployed.

8.5 Handling Exceptions in Python


Programmers must be always mindful of possible errors that may arise in their
programs. When designing a program, one must anticipate the exceptional
circumstances that may arise and take appropriate measures to handle them. The
Python interpreter handles errors by terminating immediately and printing an error
message, so that programmers can address issues as soon as they arise. In any case,
programmers must make conscious choices about how their programs should react to
exceptional conditions.

Python has many built-in exceptions that are raised when your program encounters
an error (something in the program goes wrong).When these exceptions occur, the
Python interpreter stops the current process and passes it to the calling process until it

100
is handled. If not handled, the program will crash. For example, let us consider a
program where we have a function A that calls function B, which in turn calls function
C. If an exception occurs in function C but is not handled in C, the exception passes to
B and then to A. If never handled, an error message is displayed and our program
comes to a sudden unexpected halt.

In Python, exceptions can be handled using a try statement. The critical operation
which can raise an exception is placed inside the try clause. The code that handles the
exceptions is written in except clause. We can thus choose what operations to
perform once we have caught the exception. Here is a simple example.

When the above code is run, it will ask the user to enter a number and if he enters a
valid number, it will get printed out on the screen. However, we should not run
away from the fact that a user may enter text instead of a number which will bring
unexpected result to our program hence it will crash if we do not handle such an
error. This is why our program has the except clause to handle that error and upon
receiving an input which is not a number then it will go in the except block and print
that you did not enter a valid number.

101
Output

Catching Specific Exceptions in Python


In the above example, we did not mention any specific exception in the except
clause. This is not a good programming practice as it will catch all exceptions and
handle every case in the same way. We can specify which exceptions an except clause
should catch. A try clause can have any number of except clauses to handle different
exceptions, however, only one will be executed in case an exception occurs. We can
use a tuple of values to specify multiple exceptions in an except clause. Here is an
example.

102
Raising Exceptions in Python
In Python programming, exceptions are raised when errors occur at runtime. We can
also manually raise exceptions using the raise keyword. We can optionally pass values
to the exception to clarify why that exception was raised. Look at the example
below:

The program asks the user to enter the age of their kid. A user is given to enter any
age except negative numbers because age cannot be negative. If a user tries to enter a
number that is negative as the age, the program raises an exception that is also
handled in the same program. This tells a user that the number that was entered as
the age for their kid is not a positive number. This is one of the cases where raising an
exception would be useful.

8.6 Python try with else clause


In some situations, you might want to run a certain block of code if the code block
inside try ran without any errors. For these cases, you can use the optional else
keyword with the try statement.

Note: Exceptions in the else clause are not handled by the preceding except clauses.

Let's look at an example:

103
The code above asks the user to enter an even number and once this number is
entered then an assertion is made that this number is an even number. When the
number entered is really even then the program goes ahead by skipping the except
block and prints out the number that was entered and this is done in the else clause.

See the output below:

However, it is possible that the user cannot enter an even number hence an exception
is raised by using the assert statement in this case and this exception is raised and
caught using the except clause where a user is told that the number that was entered is
not even.

104
See the output below:

8.7 Python try...finally


The try statement in Python can have an optional finally clause. This clause is
executed no matter what, and is generally used to release external resources. For
example, we may be connected to a remote data center through the network or
working with a file or a Graphical User Interface (GUI).

In all these circumstances, we must clean up the resource before the program comes
to a halt whether it successfully ran or not. These actions (closing a file, GUI or
disconnecting from network) are performed in the finally clause to guarantee the
execution.

Here is an example of file operations to illustrate this.

This type of construct makes sure that the file is closed even if an exception occurs
during the program execution.

105
The program above performs a simple function. It first opens a file named Tamala.txt
by using the open() method and this file is opened in append mode which allows us
to write to the file without erasing the contents that are in the file. Upon opening the
file, it asks the user to enter their name. The program goes ahead to check that the
name is a valid name using the assert keyword and the isalpha() method which
returns True if the name is a valid name. in the case that the name is a valid one, the
program writes this name to a file named Tamala.txt which it opened earlier and skips
the except method and then closes this file in the finally block.

Checking the output of the file Tamala.txt would look something like this:

The above image shows the entry added to the file if the user entered the name king
to it. However, we should not run away from the fact that a user may enter a
different input which may not be a valid name e.g. king.3527/+. In such a case, the
file Tamala.txt would have been opened already by the program and then upon
finding that the name is not valid the program would raise an exception using the
assert statement and this exception would be handled in the except clause where a
user would be told that the name that was entered is not a valid one. Suppose the
finally statement was not included, the program would end without closing the file
106
that was opened at the beginning which is not good programming practice. Every file
has to be closed once opened in the program because leaving it not closed consumes
resources as other services and users may not be able to use the file on the server. We
therefore make use of the finally statement which always executes whether an
exception occurred or did not occur, in this case we close the file in the finally clause.
With no presence of the finally clause then the file which was opened earlier would
not be closed.

107

You might also like