0% found this document useful (0 votes)
18 views

RST Python Book (1)

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views

RST Python Book (1)

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 150

The RST Forum

Python Programming
Guide

.
m
ru
Fo
ST
R
ht
ig
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


1
Chapter 1: Introduction to Programming and Python........................................................ 8
1.1 Understanding Programming....................................................................................... 8
1.2 Python's Role in the Programming World.....................................................................8
1.3 Why Choose Python?...................................................................................................8
1.4 Applications of Python..................................................................................................9
1.5 Guido van Rossum and the Genesis of Python......................................................... 10
Chapter 2: Installing and Setting Up Python..................................................................... 11
2.1 Installing Python on Windows.....................................................................................11
2.2 Installing Python on Linux.......................................................................................... 12
2.3 Installing Python on macOS....................................................................................... 12

.
m
2.4 Setting Up the Python Development Environment..................................................... 13
Chapter 3: Data Types and Variables................................................................................. 15
3.1 Introduction to Data Types......................................................................................... 15

ru
3.2 Data Types in Python................................................................................................. 15
3.3 Python's Integer Type (int)......................................................................................... 16

Fo
3.4 Python's Float Type (float)..........................................................................................17
Aside: PEMDAS - Order of Operations in Python...................................................... 18
3.5 Variables: The Concept and Python Implementation................................................. 19
ST
3.5.1 The Concept of Variables.................................................................................. 19
3.5.2 Variables and Memory.......................................................................................19
3.5.3 Variables in Python............................................................................................19
3.5.3.1 Variable Naming Conventions and Restrictions....................................... 20
R

3.5.4 Dynamic Typing and Static Typing.................................................................... 21


3.5.4.1 The Concept of Typing............................................................................. 21
ht

3.5.4.2 Dynamic Typing vs. Static Typing.............................................................21


3.5.4.3 Python's Dynamic Typing......................................................................... 21
ig

3.5.4.4 Python's Type Hints.................................................................................. 22


3.6 Strings in Python........................................................................................................ 23
yr

3.6.1 Creating Strings.................................................................................................23


3.6.2 Escape Sequences in Strings........................................................................... 23
3.6.3 String Formatting: f-strings................................................................................ 24
op

3.6.4 String Methods.................................................................................................. 24


3.6.4.1 upper(), lower(), capitalize(), and title().....................................................24
3.6.4.2 strip(), lstrip(), and rstrip()......................................................................... 25
C

3.6.4.3 find() and replace()................................................................................... 25


3.6.4.4 split() and join().........................................................................................25
3.6.4.5 startswith() and endswith()....................................................................... 25
3.6.4.6 isdigit(), isalpha(), and isalnum().............................................................. 26
3.6.4.7 count()...................................................................................................... 26
3.6.4.8 index().......................................................................................................26
3.6.4.9 center()..................................................................................................... 26
3.6.4.10 zfill()........................................................................................................ 26
3.6.4.11 swapcase()............................................................................................. 26

© Copyright RSTForum. Sharing of this material is illegal.


2
3.6.4.12 partition()................................................................................................ 27
3.6.4.13 ljust(), rjust()............................................................................................27
3.6.4.14 isupper(), islower()..................................................................................27
3.6.4.15 isspace()................................................................................................. 27
3.6.4.16 istitle()..................................................................................................... 28
3.6.4.17 expandtabs()...........................................................................................28
3.7 Boolean Data Type in Python.....................................................................................28
3.8 None Data Type in Python......................................................................................... 29
3.9 Data Type Conversion in Python................................................................................30
3.10 Practice code............................................................................................................32
Chapter 4: Branching and Conditionals............................................................................ 39

.
m
4.1 The input() Function................................................................................................... 39
4.2 Conditional (Relational) Operators............................................................................. 40
4.3 Introduction to Branching and Conditionals................................................................41

ru
4.3.1 If/Elif/Else Statements in Python....................................................................... 41
4.3.1.1 if Statement.............................................................................................. 41

Fo
4.3.1.2 elif Statement............................................................................................42
4.3.1.3 else Statement..........................................................................................43
4.3.1.4 Chaining if, elif, and else.......................................................................... 43
ST
4.3.2 More Examples of Conditionals in Python.........................................................44
4.4 Truthy and Falsy Values............................................................................................. 45
4.5 Logical Operators....................................................................................................... 47
R

4.5.1 and Operator..................................................................................................... 47


4.5.2 or Operator........................................................................................................ 47
4.5.3 not Operator...................................................................................................... 47
ht

4.7 Rock, Paper, Scissors Game..................................................................................... 48


Chapter 5: Loops..................................................................................................................50
ig

5.1 The Concept of Loops................................................................................................ 50


5.2 For Loops in Python................................................................................................... 50
yr

5.2.1 Basic Example of a For Loop............................................................................ 50


5.2.2 The Range Function..........................................................................................51
5.2.3 For Loop with Range Function.......................................................................... 51
op

5.2.4 Examples of For Loops..................................................................................... 52


5.2.5 FizzBuzz in Python............................................................................................ 54
5.3 The while Loop in Python........................................................................................... 55
C

5.4 The break Statement..................................................................................................57


5.4.1 Concept............................................................................................................. 57
5.4.2 Examples...........................................................................................................57
5.5 The continue Statement............................................................................................. 59
5.5.1 Concept............................................................................................................. 59
5.5.2 Examples...........................................................................................................59
5.5.3 Applying Loops to the Rock, Paper, Scissors Game.........................................60
Chapter 5: Data Structures..................................................................................................63
5.1 Understanding Data Structures.................................................................................. 63

© Copyright RSTForum. Sharing of this material is illegal.


3
5.2 Python Lists................................................................................................................63
5.2.1 Creating Lists.................................................................................................... 63
5.2.2 Accessing Elements.......................................................................................... 63
5.2.3 Modifying Elements........................................................................................... 64
5.2.4 Adding Elements............................................................................................... 64
5.2.5 Removing Elements.......................................................................................... 64
5.2.6 The pop() Method..............................................................................................65
5.2.7 The del Statement............................................................................................. 65
5.2.8 Other Python List Methods................................................................................65
5.2.8.1 The extend() Method................................................................................ 65
5.2.8.2 The insert() Method.................................................................................. 66

.
m
5.2.8.3 The index() Method.................................................................................. 66
5.2.8.4 The count() Method.................................................................................. 66
5.2.8.5 The sort() Method..................................................................................... 66

ru
5.2.8.6 The reverse() Method............................................................................... 67
5.2.8.7 The copy() Method (Continued)................................................................67

Fo
5.2.8.8 The clear() Method................................................................................... 67
5.2.9 The in Keyword and Lists.................................................................................. 68
5.2.9.1 Basic Usage............................................................................................. 68
ST
5.2.9.2 The not in Keyword...................................................................................68
5.2.9.3 The in Keyword with a Loop..................................................................... 68
5.2.10 List Slicing....................................................................................................... 69
R

5.2.10.1 Basic Slicing........................................................................................... 69


5.2.10.2 Omitting Indices......................................................................................69
5.2.10.3 Negative Indices..................................................................................... 69
ht

5.2.10.4 Step Parameter...................................................................................... 70


5.2.10.5 Slicing and Modifying Lists..................................................................... 70
ig

5.2.11 Python List Swapping...................................................................................... 70


5.2.12 Python List Comprehensions.......................................................................... 71
yr

5.2.13 Nested Lists.....................................................................................................74


5.2.13.1 Accessing Elements............................................................................... 75
5.2.13.2 Modifying Elements................................................................................ 75
op

5.2.13.3 Looping Over Nested Lists..................................................................... 75


Nested List Comprehensions............................................................................... 75
5.3 Python Dictionaries.................................................................................................... 76
C

5.3.1 Dictionary Creation............................................................................................ 76


5.3.2 Accessing Dictionary Values............................................................................. 76
5.3.3 Modifying and Adding Dictionary Key-Value Pairs............................................ 77
5.3.4 Deleting Key-Value Pairs...................................................................................77
5.3.5 Checking If a Key Exists....................................................................................77
5.3.6 Looping Through a Dictionary........................................................................... 77
5.3.7 Dictionary Methods............................................................................................78
5.3.7.1 clear()....................................................................................................... 78
5.3.7.2 copy()........................................................................................................78

© Copyright RSTForum. Sharing of this material is illegal.


4
5.3.7.3 fromkeys(keys, value)...............................................................................78
5.3.7.4 keys()........................................................................................................78
5.3.7.5 values().....................................................................................................79
5.3.7.6 items().......................................................................................................79
5.3.7.7 popitem().................................................................................................. 79
5.3.7.8 update([other]).......................................................................................... 79
5.3.8 Dictionary Comprehension................................................................................ 79
5.4 Python Tuples............................................................................................................ 81
5.4.1 Introduction........................................................................................................81
5.4.2 Accessing Elements.......................................................................................... 81
5.4.3 Tuple Unpacking................................................................................................82

.
m
5.4.4 Looping Over a Tuple........................................................................................ 82
5.4.5 Tuple Methods...................................................................................................82
5.4.6 Immutability of Tuples........................................................................................83

ru
5.4.7 Tuples vs Lists...................................................................................................83
5.4.8 Tuple Packing and Unpacking...........................................................................84

Fo
5.4.9 Tuple Comprehension....................................................................................... 84
5.5 Python Sets................................................................................................................ 85
5.5.1 Introduction........................................................................................................85
ST
5.5.2 Accessing Elements.......................................................................................... 85
5.5.3 Set Operations.................................................................................................. 85
5.5.3.1 Union........................................................................................................ 85
R

5.5.3.2 Intersection............................................................................................... 86
5.5.3.3 Difference................................................................................................. 86
5.5.3.4 Symmetric Difference............................................................................... 86
ht

5.5.4 Set Methods...................................................................................................... 87


5.5.4.1 add()......................................................................................................... 87
ig

5.5.4.2 remove()................................................................................................... 87
5.5.4.3 discard()....................................................................................................87
yr

5.5.4.4 pop()......................................................................................................... 87
5.5.4.5 clear()....................................................................................................... 88
5.5.5 Set Comprehension...........................................................................................88
op

5.6 More Examples.......................................................................................................... 88


Chapter 6: Python Functions.............................................................................................. 92
6.1 The Concept of Functions in Programming................................................................92
C

6.2 Python Functions and Their Syntax........................................................................... 92


6.3 Function Parameters and Arguments.........................................................................93
6.4 Parameters vs Arguments in Python Functions......................................................... 93
6.4.1 Parameters........................................................................................................ 93
6.5.2 Arguments......................................................................................................... 94
6.5 The Return Keyword and Return Values....................................................................94
6.5.1 Simple Return Values........................................................................................ 94
6.5.2 Multiple Return Values.......................................................................................95
6.5.3 Return Statements and Program Flow.............................................................. 95

© Copyright RSTForum. Sharing of this material is illegal.


5
6.6 Python Function Scoping: Understanding Local, Non-local and Global.....................96
6.6.1 Local Scope.......................................................................................................96
6.6.2 Non-local (Enclosing) Scope............................................................................. 96
6.6.3 Global Scope.....................................................................................................97
6.6.4 The global Keyword...........................................................................................97
6.6.5 The nonlocal Keyword.......................................................................................97
6.7 Documenting Python Functions................................................................................. 98
6.7.1 What is a Docstring?......................................................................................... 98
6.7.2 Accessing Docstrings........................................................................................ 98
6.7.3 Writing Effective Docstrings...............................................................................99
6.8 *args, **kwargs and Parameter Ordering in Python Functions.................................. 99

.
m
6.8.1 The *args Argument........................................................................................ 100
6.8.2 The **kwargs Argument.................................................................................. 100
6.8.3 Using *args and **kwargs Together.................................................................100

ru
6.8.4 Parameter Ordering.........................................................................................101
6.9 Argument Unpacking and Dictionary Unpacking in Python Functions..................... 101

Fo
6.9.1 Argument Unpacking with *............................................................................. 101
6.9.2 Dictionary Unpacking with **........................................................................... 102
6.9.3 Mixed Unpacking with * and **........................................................................ 102
ST
6.10 Lambda Functions in Python..................................................................................103
6.10.1 Understanding Lambda Functions................................................................ 103
6.10.2 Why Use Lambda Functions?....................................................................... 103
R

6.10.3 Lambda Functions with filter(), map(), and reduce()..................................... 103


6.10.4 More Examples............................................................................................. 104
6.11 Built-in Functions in Python.................................................................................... 106
ht

6.12 Sample practice programs......................................................................................110


6.12.1 Contact Management System....................................................................... 110
ig

6.12.2 To-Do List Manager....................................................................................... 112


6.12.3 Inventory Management System..................................................................... 114
yr

6.12.4 Student Grade Calculator.............................................................................. 116


6.12.5 Word Frequency Analyzer............................................................................. 118
Chapter 7: Debugging........................................................................................................120
op

7.1 Understanding Debugging........................................................................................120


7.2 Python Exceptions....................................................................................................120
7.3 Handling Exceptions in Python: try/except............................................................... 123
C

7.3.1 More Advanced Exception Handling: try/except/else/finally............................124


7.4 Raising Exceptions: The raise keyword................................................................... 125
7.4.1 Using raise to trigger built-in exceptions......................................................... 126
7.4.2 Creating custom exceptions............................................................................ 126
7.5 Debugging with PDB, the Python Debugger............................................................ 127
7.5.1 Starting a debugging session.......................................................................... 127
7.5.2 PDB commands.............................................................................................. 128
7.5.3 Post-mortem debugging.................................................................................. 129
Chapter 8: Object-Oriented Programming (OOP) in Python.......................................... 130

© Copyright RSTForum. Sharing of this material is illegal.


6
8.1 Introduction to Object-Oriented Programming..........................................................130
8.1.1 Procedural vs. Object-Oriented Programming................................................ 130
8.1.2 The Concept of Classes and Objects..............................................................131
8.1.3 Benefits and Applications of OOP................................................................... 131
8.2 Classes and Objects in Python................................................................................ 132
8.2.1 Understanding Classes and Objects............................................................... 132
8.2.2 Defining a Class in Python.............................................................................. 132
8.2.3 Creating an Instance of a Class...................................................................... 133
8.2.4 Adding Methods to a Class............................................................................. 133
8.2.5 The __init__ Method and Object Initialization................................................. 133
8.2.6 Instance Variables and Class Variables.......................................................... 133

.
m
8.2.7 Real-World Example........................................................................................134
8.3 Inheritance and Polymorphism.................................................................................136
8.3.1 Concept of Inheritance, Subclasses, and Superclasses................................. 136

ru
8.3.2 Implementing Inheritance in Python................................................................ 136
8.3.3 Method Overriding (Polymorphism in OOP)....................................................137

Fo
8.3.4 The super() Function....................................................................................... 137
8.3.5 Multiple Inheritance......................................................................................... 137
8.3.6 Real-World Example........................................................................................138
ST
8.4 Special (Dunder) Methods........................................................................................139
8.4.1 Understanding Special Methods..................................................................... 139
8.4.2 Overloading Operators in Python.................................................................... 139
R

8.4.3 Real-World Example........................................................................................140


8.6 Working with Class and Static Methods................................................................... 142
8.6.1 Understanding @classmethod........................................................................ 142
ht

8.6.2 Understanding @staticmethod........................................................................ 142


8.6.3 Differences and use-cases for class and static methods................................ 143
ig

8.6.4 Real-World Example........................................................................................143


8.6.4.1 isinstance() function................................................................................145
yr

8.7 Python's Built-In OOP Features............................................................................... 146


8.8.1 The isinstance function....................................................................................146
8.7.2 The issubclass function................................................................................... 147
op

8.7.3 The hasattr, getattr, setattr, and delattr functions............................................ 148


8.7.4 Real-World Example........................................................................................148
C

© Copyright RSTForum. Sharing of this material is illegal.


7
Chapter 1: Introduction to Programming and
Python

1.1 Understanding Programming


In the most basic sense, programming is a way to instruct a computer to perform various
tasks. It's the process of writing, testing, debugging, and maintaining the source code of
computer programs. This source code is written in a programming language, which the
computer understands and follows to execute specific tasks.

.
Every action that a computer performs, from complex scientific calculations and rendering

m
video game graphics to browsing the web and even displaying the time, is guided by
programming. Even the simplest tasks like making coffee using a smart coffee machine

ru
involve some form of programming.

Programming languages allow us to interface with computers and utilize their processing

Fo
power. While computers are incredibly fast and accurate at doing repetitive tasks, they
require detailed instructions to perform these tasks. This need for explicit instruction is where
programming languages come in.
ST
1.2 Python's Role in the Programming World
R

Enter Python, one of the most popular programming languages in the world. Python was
created by Guido van Rossum, and it was first released in 1991. Named not after the snake,
but after the British comedy show "Monty Python's Flying Circus," Python is renowned for its
ht

design philosophy, which emphasizes code readability and syntax that allows programmers
to express concepts in fewer lines of code than might be possible in other languages.
ig

Python is an interpreted, high-level, general-purpose programming language. It means


Python code is not converted to machine-readable code before it is run but is read and
yr

executed line by line by the Python interpreter, which is software that executes code directly
and freely available on most platforms. This feature of Python makes it easier to debug and
op

also makes Python suitable for rapid application development.

Moreover, Python is a versatile language, used in various fields like web and software
C

development, data analysis, machine learning, artificial intelligence, scientific computing, etc.
It is used by some of the world's largest organizations, including NASA, Google, and IBM, as
well as individual programmers and hobbyists.

1.3 Why Choose Python?


Python is often chosen as a first programming language because it's simple to read and
write. The simplicity and clarity of Python, combined with its powerful capabilities, make it a
favorite of both beginners and experts.

Some of the reasons why we choose Python over other languages include:

© Copyright RSTForum. Sharing of this material is illegal.


8
1. Readability and Simplicity: Python's syntax is clear, intuitive, and almost
English-like, which makes it a superb language for beginners to learn programming.

2. Broad Standard Library: Python comes with a vast standard library that includes
areas like internet protocols, string operations, web services tools, and operating
system interfaces. Many high use programming tasks are already scripted into the
standard library which reduces the length of code to be written significantly.

3. Scalability and Speed: Python's productivity and speed are quite substantial which
makes it a popular choice in industries. Companies that prioritize productivity and
speed in project development choose Python.

.
m
4. Wide Support for Libraries and Frameworks: Python is also rich with several
libraries and frameworks that make the application development process faster and
easier. For example, libraries like NumPy and SciPy are useful for scientific

ru
computation, Pandas is for data analysis and manipulation, and frameworks like
Django and Flask assist in web development.

Fo
5. Thriving Community: Python has a large, active community of developers who are
always ready to provide help and support. This community also consistently
contributes to developing and upgrading Python libraries and frameworks, making
ST
Python ever more powerful and user-friendly.

1.4 Applications of Python


R

Python, owing to its simplicity, versatility, and powerful standard library, has wide-ranging
applications across diverse domains. From automating small tasks on your computer to
ht

running large web servers, Python has the breadth and depth to cater to various use cases.

1. General-Purpose Programming: Python is an excellent language for


ig

general-purpose programming. Its clear syntax and expressive style make it a


popular choice for applications ranging from simple scripts to complex object-oriented
yr

software. Python is powerful enough to create advanced applications and yet simple
enough to write quick scripts to automate repetitive tasks.
op

2. Scripting and Automation: Python is often used as a scripting language. Scripts


are small programs that perform a specific task. If you find yourself doing a repetitive
task, such as renaming files, you can write a Python script to automate it. Python's
C

extensive library support makes it easy to interact with your operating system,
manipulate files and directories, and automate many other tasks. Libraries like os,
sys, shutil, and glob provide functionalities for these purposes.

3. Web Development: Python is a great language for web development. It offers


several excellent frameworks like Django, Flask, Pyramid, and more, which simplify
the process of developing complex web applications. Django, for example, is a
high-level Python web framework that encourages rapid development and clean,
pragmatic design. It takes care of much of the hassle of web development, so you
can focus on writing your app without needing to reinvent the wheel. On the other

© Copyright RSTForum. Sharing of this material is illegal.


9
hand, Flask is a micro web framework that gives you the basics to build a web
application but remains flexible for additions according to your needs.

4. Data Analysis and Visualization: Python is a popular tool in data analysis and data
visualization. Libraries like Pandas make it easy to manipulate large datasets, while
Matplotlib and Seaborn are excellent tools for creating static, animated, and
interactive visualizations in Python. Data scientists, statisticians, and analysts often
use these libraries to gain insights from data and present these findings in a visually
appealing and understandable way.

5. Machine Learning and Artificial Intelligence: Python is one of the primary


languages for machine learning (ML), deep learning, and artificial intelligence (AI).

.
Libraries like Scikit-learn provide simple and efficient tools for predictive data

m
analysis, while libraries like TensorFlow and PyTorch provide the tools to work with
artificial neural networks for deep learning models. Additionally, libraries like Keras

ru
provide a high-level interface to other libraries, like TensorFlow, making it even easier
to create deep learning models.

Fo
6. Network Programming and Automation: Python is often used in network
programming and automation tasks. With libraries such as Scapy, network
programmers can create, manipulate, send, and receive network packets. In network
automation, Python is frequently used to automate various network configuration
ST
tasks, monitor network status, and perform network diagnostics. Network engineers
use Python to interact with APIs to integrate network devices and applications,
implement SDN (Software-Defined Networking), and more.
R

7. Game Development: While Python might not be as commonly used for game
development as languages like C# (used in Unity) or C++ (used in Unreal Engine), it
ht

still has uses in this field. Pygame is a Python library that is great for learning game
development. It's also used for prototyping games, and even for developing
full-fledged indie games.
ig

8. Cybersecurity: Python is also popular in the cybersecurity field due to its simplicity
yr

and wide range of libraries that can scan, spoof, and script cybersecurity tasks.
Libraries such as Nmap, Yara, and Requests can help with network scanning,
malware analysis, and sending HTTP requests, respectively.
op

9. Scientific Computing: Python's mathematical libraries are widely used in scientific


computing.
C

1.5 Guido van Rossum and the Genesis of Python


Guido van Rossum, a Dutch programmer known as the "Benevolent Dictator For Life"
(BDFL) in the Python community, is the creator of Python. The story of Python's creation is
an interesting tale of innovation and thoughtful design.

During the late 1980s, van Rossum was part of a team at Centrum Wiskunde & Informatica
(CWI), a research institute in the Netherlands, working on a language called ABC. ABC was

© Copyright RSTForum. Sharing of this material is illegal.


10
a powerful yet simple language, designed for teaching and as a scripting language for
Unix-like operating systems. Although ABC was not widely adopted, its principles deeply
influenced van Rossum's development of Python.

In December 1989, during the Christmas holidays, van Rossum decided to start a project to
keep himself occupied. Being unsatisfied with the complexity of languages like C++ and the
limitations of scripting languages like ABC and Unix shell, he aimed to create a language
that struck a balance between simplicity and power.

Van Rossum wanted a language that:

● Was easy to read with clear, plain English keywords

.
m
● Provided users a way to create their own types
● Was suitable for daily tasks, allowing for short development times

ru
With these goals in mind, he began work on Python. The language was named after the
British comedy series "Monty Python's Flying Circus," of which van Rossum was a fan. He

Fo
wanted a name that was short, unique, and slightly mysterious, so he decided that Python fit
the bill.

Python was first released in 1991, and over the years, it has been updated and improved
ST
through various versions. Python has always emphasized simplicity and beauty, striving to
make complex tasks accessible and user-friendly. This philosophy has made Python a
popular choice for beginners and experts alike.
R

Van Rossum remained Python’s chief decision-maker and project leader for many years,
making the final say in any disputes or decisions in the Python development process.
ht

Despite stepping down from his role as the BDFL in July 2018, van Rossum's vision and
philosophy continue to guide Python's development and its community.
ig

His creation, Python, has grown to be one of the most popular and influential programming
languages in the world. Today, it is used by millions of developers and is at the forefront of
yr

cutting-edge technology and innovation.


op

Chapter 2: Installing and Setting Up Python


Installing Python on your system is the first step towards becoming a Python programmer.
C

Regardless of your operating system - be it Windows, Linux, or macOS, we have got you
covered. Let's break down the process for each operating system.

2.1 Installing Python on Windows


Step 1: Download Python Installer
● Visit the official Python website's download page at
https://www.python.org/downloads/.

© Copyright RSTForum. Sharing of this material is illegal.


11
● You will see a button to download the latest version of Python. As of my knowledge
cutoff in September 2021, the latest version is Python 3.9.7. However, there should
be a newer version by now.

Step 2: Install Python


● Run the installer file you just downloaded.
● You will be greeted with the first install window that has an important option at the
bottom. Make sure to check the box that says Add Python to PATH before clicking
Install Now.

Step 3: Verify Installation

.
● To verify the installation, open a new Command Prompt window (search cmd in

m
Windows search and hit Enter).
● Type python --version and hit Enter. This command should return the version of

ru
Python that you just installed.

2.2 Installing Python on Linux

Fo
Most Linux distributions come preinstalled with Python. However, it might not be the latest
version. Here's how you can install the latest Python on Ubuntu (a popular Linux
ST
distribution).

Step 1: Update Package Lists


● Open a Terminal window.
R

● Update the package lists for upgrades and new package installations: sudo apt
update
ht

Step 2: Install Python


● To install Python, type: sudo apt install python3
ig

Step 3: Verify Installation


yr

● Once the installation is complete, you can verify the installed version by typing
python3 --version.
op

● If you want to install Python on other Linux distributions, the steps are similar, but the
commands might vary slightly according to the package manager the distribution
uses.
C

2.3 Installing Python on macOS


macOS, like Linux, also comes with Python preinstalled. However, it's typically an older
version. To install the latest Python on macOS, follow these steps.

Step 1: Download Python Installer


● Visit the official Python website's download page at
https://www.python.org/downloads/.

© Copyright RSTForum. Sharing of this material is illegal.


12
● You will see a button to download the latest version of Python.

Step 2: Install Python


● Open the Python installer dmg file you just downloaded.
● You should see a Python.pkg file. Double-click it to run the installer.
● Proceed through the installer steps. You'll need to agree to the license, choose the
install location, and enter your password.

Step 3: Verify Installation


● To verify the installation, open a new Terminal window.
● Type python3 --version and hit Enter. This command should return the version of

.
Python that you just installed.

m
With Python installed on your system, you're now ready to start writing Python programs!

ru
2.4 Setting Up the Python Development Environment

Fo
While Python is now installed on your system, you might find the basic command-line
interface a bit hard to work with. For a more productive setup, you may consider installing a
code editor or an Integrated Development Environment (IDE).
ST
Some popular choices for Python development include:

● Visual Studio Code (VS Code): A lightweight but powerful source code editor
R

available for Windows, Linux, and macOS. It comes with built-in support for Python,
and other languages can be added via extensions.
ht

● PyCharm: A full-featured IDE developed by JetBrains, specifically for Python


development. It offers features like intelligent code completion, on-the-fly error
ig

checking, quick-fixes, automated code refactoring, and superior navigation


capabilities. PyCharm is available for Windows, macOS, and Linux. There's a
community edition that is free to use, and a professional edition with extra features
yr

for web development and data science.


op

● Jupyter Notebook: Particularly popular among data scientists, Jupyter Notebook is


an open-source web application that allows the creation and sharing of documents
that contain live code, equations, visualizations, and narrative text. Its uses include
C

data cleaning and transformation, numerical simulation, statistical modeling, data


visualization, machine learning, and more.

● Sublime Text: A sophisticated text editor for code, markup, and prose. It's
lightweight, powerful, and highly extendable. With a Python plugin, Sublime Text can
be a great Python development tool.

The choice of code editor or IDE generally depends on your specific needs and preferences,
so it's good to experiment and find the one that suits you best.

© Copyright RSTForum. Sharing of this material is illegal.


13
Finally, Python programming often involves installing additional packages that are not part of
the Python Standard Library. For managing these packages, Python uses a tool called pip,
which should be installed on your system along with Python. You can install new packages
using pip from your command line like so: pip install package-name

With Python installed and a development environment set up, you're now ready to start your
journey with Python programming!

In the next chapter, we'll cover Python basics, starting with Python syntax, variables, data
types, and then move on to more complex topics such as control flow and functions. Stay
tuned!

.
m
ru
Fo
ST
R
ht
ig
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


14
Chapter 3: Data Types and Variables

3.1 Introduction to Data Types


In programming languages, a fundamental concept exists that helps to define and categorize
different types of data that we want to use in our programs. This is known as "data types".
Data types essentially serve as a blueprint for the different types of values that can exist in a
program. They determine what kind of operations can be performed on these values, and
how much storage space they need in the computer's memory.

For instance, if we're dealing with whole numbers like 1, 2, or 500, we have a specific data

.
m
type for that. Similarly, if we need to work with decimal numbers or true and false values,
there are different data types for these as well.

ru
While it's important to note that different programming languages may have different data
types and ways of handling them, the core concept remains similar across languages. This

Fo
understanding will be crucial as we dive deeper into programming, because it allows us to
predict how our data will behave and interact, and to write code that's more efficient and less
prone to errors.
ST
At this point, you might be wondering, "how do we use these data types in our code?" This is
where an important concept comes in that we'll delve into shortly: the concept of 'variables'.
But before we dive into that, we first took a detailed look at two very important data types in
R

Python: numbers (int and float). These data types, which represent whole numbers and
decimal numbers respectively, form the backbone of numerical operations in Python. Once
we've grasped these, we'll be ready to explore variables, and how they tie into the concept of
ht

data types.

Here are some of the basic types found in many programming languages:
ig

● Integer: Represents whole numbers, without a fractional component.


yr

● Floating-Point: Represents real numbers, with both an integer and fractional


component.
op

● Boolean: Represents two values, True and False.


● String: Represents a sequence of characters.
● Array or List: Represents an ordered collection of items.
C

● Dictionary or Map: Represents a collection of key-value pairs.

Understanding these data types is important as they form the basis of data manipulation,
data structure design, and complex problem solving.

3.2 Data Types in Python


Python, being a dynamically typed language, does not require explicit declaration of the data
type of a variable when it is created. The interpreter infers the data type based on the value
it is assigned.
© Copyright RSTForum. Sharing of this material is illegal.
15
Python's standard data types are:
1. Numbers: Including Integer (int), Floating point (float), and Complex numbers
(complex).
2. String (str): To store sequences of Unicode characters.
3. List (list): To store an ordered sequence of values.
4. Tuple (tuple): Similar to lists, but unlike lists, tuples are immutable.
5. Dictionary (dict): To store key-value pairs.
6. Set (set): An unordered collection of unique elements.
7. Boolean (bool): To represent True and False.
8. None: This is a special type representing the absence of a value or a null value.

.
m
Let's delve into the details of int and float.

ru
3.3 Python's Integer Type (int)
In Python, the int type is used to represent integer values - positive or negative whole

Fo
numbers without a fractional component.

Here is an example of an integer in Python:


ST
10
R

In this example, 10 is an integer value.

Python supports a variety of operations on integers, including addition (+), subtraction (-),
ht

multiplication (*), division (/), floor division (//), modulus (%), and exponentiation (**). Here
are examples of these operations:
ig

# addition
yr

print(10 + 2) # Output: 12
op

# subtraction
print(10 - 2) # Output: 8
C

# multiplication
print(10 * 2) # Output: 20

# division
print(10 / 2) # Output: 5.0

# floor division
print(10 // 2) # Output: 5

# modulus

© Copyright RSTForum. Sharing of this material is illegal.


16
print(10 % 2) # Output: 0

# exponentiation
print(10 ** 2) # Output: 100

3.4 Python's Float Type (float)


In Python, the float type represents real numbers, i.e., numbers with both integer and
fractional components. They are specified with a decimal point. Optionally, the character e or
E followed by a positive or negative integer may be appended to specify scientific notation.

.
Here's how we can use a floating-point number in Python:

m
ru
3.14

Operations similar to integers like addition (+), subtraction (-), multiplication (*), division (/),

Fo
floor division (//), modulus (%), and exponentiation (**) can also be performed on floats.

# addition
ST
print(10.5 + 2.3) # Output: 12.8

# subtraction
R

print(10.5 - 2.3) # Output: 8.2

# multiplication
ht

print(10.5 * 2.3) # Output: 24.15


ig

# division
print(10.5 / 2.3) # Output: 4.565217391304348
yr

# floor division
print(10.5 // 2.3) # Output: 4.0
op

# modulus
print(10.5 % 2.3) # Output: 0.1999999999999993
C

# exponentiation
print(10.5 ** 2.3) # Output: 199.5262314968879

While the int and float types in Python are used to represent numbers, there's more to
Python data types than these. But before we explore those, it will be beneficial to understand
how we can store these int or float values for repeated use in our programs. That's where
the concept of 'variables' will come into play, which we will discuss in the upcoming sections.

© Copyright RSTForum. Sharing of this material is illegal.


17
Aside: PEMDAS - Order of Operations in Python
PEMDAS is an acronym that stands for Parentheses, Exponents, Multiplication and
Division, Addition and Subtraction. This is the order in which operations are performed in
a mathematical expression. Python, like many programming languages, follows this rule for
its mathematical operations. Here's a closer look at each step:

Parentheses (): Expressions enclosed in parentheses are evaluated first. This is useful
when you want to change the normal order of operations.

.
Exponents **: Next, exponents are evaluated. Python uses the ** operator for

m
exponentiation.

ru
Multiplication * and Division /: After exponents, multiplication and division are performed.
If there are multiple multiplication and division operations in a row, they are evaluated from
left to right.

Fo
Addition + and Subtraction -: Lastly, addition and subtraction operations are carried out.
Again, if there are multiple operations in a row, they are performed from left to right.
ST
Let's look at some examples to illustrate PEMDAS:
R

# Without parentheses
result = 3 + 2 * 2
print(result) # Output: 7, not 10
ht

# With parentheses
ig

result = (3 + 2) * 2
print(result) # Output: 10, not 7
yr

# Exponents
result = 2 ** 3 * 2
op

print(result) # Output: 16, not 64

# Division and Multiplication


C

result = 20 / 2 * 5
print(result) # Output: 50, not 2

# All together now


result = (3 + 2) * 2 ** 2 / 5
print(result) # Output: 4.0

© Copyright RSTForum. Sharing of this material is illegal.


18
3.5 Variables: The Concept and Python Implementation

3.5.1 The Concept of Variables


In programming, a variable can be thought of as a container used to store data. This data
could be a number, a character, a string of text, a list of values, or even more complex types
of data. A variable allows us to label data with a descriptive name, so our programs can be
understood and modified more easily.

One way to conceptualize variables is to think of them like the cells in a spreadsheet. Each
cell doesn't hold the information you put into it, but rather a reference to where that
information is stored. So if you write a formula in one cell to manipulate the contents of other

.
m
cells, what you're actually doing is telling the spreadsheet how to use those references to
find the actual data, do something with it, and then store the result in a new place.

ru
In programming languages, we have the concept of variable "assignment". This is the
process of storing a value in a variable. For instance, we can assign the number 10 to a

Fo
variable called my_number, or the text "hello world" to a variable called greeting.

3.5.2 Variables and Memory


ST
To understand variables more deeply, it helps to have a basic understanding of how
computer memory works.

When your program runs, it's loaded into a part of your computer's memory called RAM
R

(Random Access Memory). This is the workspace your computer uses to execute your
program, store data, perform calculations, and so forth. Each location in RAM can be
ht

identified by an address, much like how houses on a street have unique addresses.

When you create a variable in your program, the computer allocates a piece of its memory to
ig

hold the variable's value. The variable's name is then associated with this memory location.
When your program uses this variable, the computer knows to look in the associated
yr

memory location to find the value.


op

However, as a programmer, you generally don't need to worry about exactly where in
memory your variables are stored. This is managed by the computer and the programming
language you're using. What's important to understand is that when you assign a value to a
variable, that value is stored somewhere in memory, and you can use the variable's name to
C

access it.

3.5.3 Variables in Python


In Python, variables are created when you assign a value to them. Python uses the equals
sign (=) for assignment. To the left of the = is the variable's name. To the right of the =
is the value that's being assigned to the variable.

Here's an example:

© Copyright RSTForum. Sharing of this material is illegal.


19
score = 10

In this line of code, Python stores the integer 10 in a memory location and associates that
location with the name score. From this point forward, whenever score is used in the
program, Python will substitute the value that's stored in the associated memory location.

3.5.3.1 Variable Naming Conventions and Restrictions


When creating variables in Python, there are certain rules and conventions that you should
follow.

.
Rules:

m
1. Variable names must start with a letter or an underscore character.
2. A variable name can only contain alphanumeric characters and underscores (A-z,
0-9, and _ ).

ru
3. Variable names are case-sensitive (age, Age and AGE are three different variables).

Fo
Conventions:

1. Descriptive Names: Variable names should always be as descriptive as possible to


make your code easier to read. For example, student_name is better than s, and
ST
salary is better than x.
2. Lowercase with Underscores: Python's official style guide, PEP 8, recommends
using lowercase letters and underscores to separate words in variable names. This is
R

also known as snake_case. For example, number_of_students.


3. Avoid Reserved Words: Do not use Python keywords or function names as variable
names. For instance, don't use names like print, for, while, etc.
ht

4. Constants: By convention, constants are always named in capital letters, with


underscores separating words. For example, PI, MAX_THRESHOLD.
ig

Let's take a look at some examples of variable assignment:


yr

# Valid variable names


op

my_variable = 10
variable1 = 20
_variable = 30
C

PI = 3.14

# Invalid variable names


1variable = 10 # starts with a number
variable-name = 20 # contains a character other than alphanumeric and
underscore
for = 30 # uses a Python keyword

In Python, how you name your variables is crucial. A good variable name describes the data
it contains. Following these conventions can make your code more readable and

© Copyright RSTForum. Sharing of this material is illegal.


20
understandable to you and others.

3.5.4 Dynamic Typing and Static Typing

3.5.4.1 The Concept of Typing


In programming, "typing" refers to the kind of data a variable or expression can have.
The type of a variable determines what kind of operations can be performed on it. For
instance, you can add and subtract numbers, but you can't subtract one string from another.
Types help us categorize data, and they provide rules about how that data can be
manipulated.

.
m
Typing is necessary in programming languages because it enables the compiler or
interpreter (the system that reads and runs your code) to understand how to work with your

ru
data. By knowing the type of a variable, the system can predict how much memory it needs
to allocate for that variable, what operations can be performed on it, and how the results of
those operations should be interpreted.

3.5.4.2 Dynamic Typing vs. Static Typing

Fo
There are two primary approaches to typing in programming languages: dynamic typing and
ST
static typing.

In statically-typed languages, the type of a variable is checked at compile-time, before the


R

program is run. This means that you must declare the type of a variable when you create it,
and you can't change the type of the variable later. Examples of statically-typed languages
include C++, Java, and Rust.
ht

On the other hand, dynamically-typed languages perform type checking at runtime, while the
program is being executed. This means that you don't have to declare the type of a variable
ig

when you create it, and you can change the type of a variable as many times as you want.
Examples of dynamically-typed languages include Python, JavaScript, and Ruby.
yr

3.5.4.3 Python's Dynamic Typing


op

Python is a dynamically-typed language. As we mentioned earlier, this means that you can
assign a value of any type to a variable, and you can change the type of a variable's value at
any time.
C

Here's an example:

x = 10 # Here, x is an integer
print(x)

x = "Hello, World!" # Now, x is a string


print(x)

© Copyright RSTForum. Sharing of this material is illegal.


21
When you run this code, Python first assigns the integer 10 to the variable x. Then, it
changes x to refer to the string "Hello, World!". Both of these operations are perfectly valid in
Python.

While dynamic typing adds flexibility and ease of use, it can also lead to runtime errors. For
instance, if you try to perform an operation that's not valid for a variable's current type,
Python will throw an error:

x = 10
x = x + "Hello, World!" # This will cause a TypeError

.
This code causes a TypeError because Python doesn't know how to add an integer (x) and

m
a string ("Hello, World!").

ru
3.5.4.4 Python's Type Hints
Type hints are optional and are not enforced by Python's interpreter. The Python language

Fo
still remains dynamically-typed and it doesn't restrict the type of value you can assign to a
variable, even if you've provided a type hint. However, type hints can greatly improve code
readability and can be used by various tools to catch potential type-related errors before
ST
runtime.

Let's look at an example of how to use type hints with simple data types:
R

age: int = 20
name: str = "Alice"
ht

In this example, age: int is a type hint that indicates that age should be an integer, and
ig

name: str indicates that name should be a string. As mentioned earlier, these type hints
are optional and mainly serve for documentation and linting purposes.
yr

Now, if you were to use a tool like mypy, a static type checker for Python, it could analyse
op

your code and warn you if the variable was ever assigned a value that didn't match its type
hint. For instance, if later in your code you did:
C

age: int = 20
name: str = "Alice"

mypy would notify you of a type hint inconsistency, even though Python itself wouldn't raise
an error until runtime (and only if you used age in a context where a string wasn't
acceptable).

In conclusion, while Python's dynamic typing provides flexibility, type hints can be used as a
form of documentation to help programmers understand what types of values should be
assigned to variables, and can assist static type checking tools in identifying potential errors.

© Copyright RSTForum. Sharing of this material is illegal.


22
As we progress and learn more about Python's other data types and their capabilities, we'll
continually see how dynamic typing and type hints play their part in making Python a
versatile language suitable for a variety of tasks.

3.6 Strings in Python


Strings in Python are used to store textual data, i.e., sequences of characters. They are
among the most commonly used data types in programming, and Python offers powerful
features to manipulate and work with strings.

3.6.1 Creating Strings

.
In Python, strings can be created by enclosing a sequence of characters within either single

m
quotes (') or double quotes ("):

ru
name = "Alice"
greeting = 'Hello, World!'

Fo
Both of these are valid ways to create strings in Python. You can choose either way based
on your preference or the requirement of your code.
ST
3.6.2 Escape Sequences in Strings
R

Sometimes, we may need to include special characters within our strings. For example, let's
say we need a string that includes a quote (" or ') character. Python provides escape
sequences for such requirements. Escape sequences start with a backslash (\) and are
ht

followed by the character we want to insert.


ig

For example, if we want to insert a double quote inside a string, we can do it as follows:
yr

quote = "He said, \"Hello, World!\""


op

Similarly, we can use \n for a newline, \t for a tab space, and \\ to include a backslash
itself.
C

● The newline escape sequence \n:

print("Hello\nWorld")

# Hello
# World

The string after \n appears on a new line.

● The tab escape sequence \t:

© Copyright RSTForum. Sharing of this material is illegal.


23
print("Hello\tWorld")

# Hello World

A tab space is inserted where \t is placed.

● The backslash escape sequence \\:

print("Hello\\World")

.
m
# Hello\World

ru
The double backslash \\ is used to insert a single backslash in the string. It's necessary
because the backslash character is used to introduce escape sequences, and we need a
way to include an actual backslash in a string.

Fo
Using these escape sequences, you can include special characters and formatting in your
Python strings.
ST
3.6.3 String Formatting: f-strings
Python provides several ways to format strings, and f-strings (formatted string literals) are a
R

very convenient method introduced in Python 3.6. They are prefixed with 'f' and use curly
braces {} to evaluate variables or expressions inside the string.
ht

name = "Alice"
age = 25
ig

print(f"My name is {name} and I am {age} years old.")


yr

In the above example, the variables name and age are directly placed inside the string.
Python replaces {name} with the value of the variable name, and {age} with the value of
op

age.

3.6.4 String Methods


C

Python provides a set of built-in methods that you can use on strings. Below are examples of
some commonly used string methods.

3.6.4.1 upper(), lower(), capitalize(), and title()


These methods are used to change the case of the string.

text = "hello, world"


print(text.upper()) # Output: HELLO, WORLD
print(text.lower()) # Output: hello, world

© Copyright RSTForum. Sharing of this material is illegal.


24
print(text.capitalize()) # Output: Hello, world
print(text.title()) # Output: Hello, World

3.6.4.2 strip(), lstrip(), and rstrip()


These methods are used to remove leading and trailing spaces (or other specified
characters) from the string.

text = " hello, world "


print(text.strip()) # Output: "hello, world"
print(text.lstrip()) # Output: "hello, world "

.
print(text.rstrip()) # Output: " hello, world"

m
3.6.4.3 find() and replace()

ru
find() is used to find the index of a substring in a string. replace() is used to replace a
specified value with another value.

Fo
text = "hello, world"
print(text.find("world")) # Output: 7
ST
print(text.replace("world", "Python")) # Output: hello, Python

3.6.4.4 split() and join()


R

split() is used to break a string into a list of substrings based on a specified delimiter. By
default, it splits at each space.
ht

text = "hello, world"


print(text.split()) # Output: ['hello,', 'world']
ig

The join() method is used to concatenate a list of strings into a single string. It uses the
yr

string it was called on as the delimiter.


op

words = ['hello', 'world']


print(" ".join(words)) # Output: "hello world"
C

3.6.4.5 startswith() and endswith()


These methods are used to check if a string starts or ends with a specified substring
respectively.

text = "hello, world"


print(text.startswith("hello")) # Output: True
print(text.endswith("Python")) # Output: False

© Copyright RSTForum. Sharing of this material is illegal.


25
3.6.4.6 isdigit(), isalpha(), and isalnum()
These methods are used to check if the string contains digit characters only, non-digit
characters only, or a mix of digit and non-digit characters, respectively.

text1 = "123"
text2 = "abc"
text3 = "abc123"
print(text1.isdigit()) # Output: True
print(text2.isalpha()) # Output: True
print(text3.isalnum()) # Output: True

.
m
3.6.4.7 count()

ru
The count() method returns the number of times a specified value appears in the string.

Fo
text = "hello, world, world"
print(text.count("world")) # Output: 2
ST
3.6.4.8 index()
The index() method is similar to find(), but raises an exception if the value is not found.
R

text = "hello, world"


print(text.index("world")) # Output: 7
ht
ig

3.6.4.9 center()
The center() method centers a string, padding it with specified characters.
yr

text = "hello"
op

print(text.center(20, "-")) # Output: '-------hello--------'


C

3.6.4.10 zfill()
The zfill() method adds zeros at the beginning of the string, until it reaches the specified
length.

text = "hello"
print(text.zfill(10)) # Output: '00000hello'

3.6.4.11 swapcase()
The swapcase() method returns a string where uppercase characters are converted to
© Copyright RSTForum. Sharing of this material is illegal.
26
lowercase, and vice versa.

text = "Hello, World"


print(text.swapcase()) # Output: 'hELLO, wORLD'

3.6.4.12 partition()
The partition() method searches for a specified string, and splits the string into a tuple
containing three elements.

● The part before the specified string

.
m
● The specified string
● The part after the string

ru
text = "I have 30 apples"
print(text.partition("30")) # Output: ('I have ', '30', ' apples')

3.6.4.13 ljust(), rjust()


Fo
ST
The ljust() and rjust() methods return a left-justified or right-justified version of the
string padded with a specified character (default is space).
R

text = "hello"
print(text.ljust(20, "-")) # Output: 'hello---------------'
ht

print(text.rjust(20, "-")) # Output: '---------------hello'


ig

3.6.4.14 isupper(), islower()


yr

The isupper() and islower() methods return True if all the cased characters in the string
are uppercase or lowercase respectively.
op

text1 = "HELLO"
text2 = "hello"
C

print(text1.isupper()) # Output: True


print(text2.islower()) # Output: True

3.6.4.15 isspace()
The isspace() method returns True if all the characters in the string are whitespace
characters, False otherwise.

text = " "

© Copyright RSTForum. Sharing of this material is illegal.


27
print(text.isspace()) # Output: True

3.6.4.16 istitle()
The istitle() method returns True if the string is a titlecased string, False otherwise.

text1 = "Hello, World"


text2 = "Hello, world"
print(text1.istitle()) # Output: True
print(text2.istitle()) # Output: False

.
m
3.6.4.17 expandtabs()

ru
The expandtabs() method sets the tab size to the specified number of whitespaces.

Fo
text = "H\tello, W\torld"
print(text.expandtabs(4)) # Output: 'H ello, W orld'
ST
This is not an exhaustive list. Python provides many other methods to manipulate and work
with strings. However, these are some of the most commonly used ones and a good starting
R

point for exploring string manipulations in Python.

Remember, strings are an essential part of any programming language and Python provides
ht

a rich set of tools to work with them. With the understanding of strings, you can effectively
manipulate textual data in your Python applications. Practice using these string methods and
you will soon find them second nature.
ig
yr

3.7 Boolean Data Type in Python


The Boolean data type, also known simply as bool, is a fundamental data type in Python.
op

This data type is named after George Boole, who first defined an algebraic system of logic in
the mid 19th century.
C

Boolean is the simplest data type with only two possible values: True and False. These are
not just words in Python, but they represent the two states of a Boolean value. In fact, the
Python interpreter recognizes them as special keywords. The primary usage of bool data
types is to represent truth values in logical expressions.

Here's how you can create variables with Boolean values:

is_student = True
is_teacher = False

© Copyright RSTForum. Sharing of this material is illegal.


28
In these examples, is_student and is_teacher are variable names, and True and
False are Boolean values. Remember, these keywords are case-sensitive, and you must
capitalize the first letter.

In Python, booleans are also a subtype of integers. Here's a unique aspect: when you
convert booleans to integers or use them in arithmetic operations, True is treated as 1, and
False is treated as 0.

print(int(True)) # Output: 1
print(int(False)) # Output: 0

.
print(True + True) # Output: 2

m
print(True + False) # Output: 1
print(False - True) # Output: -1

ru
Python also has a built-in function bool() that can convert values of other types to a

Fo
Boolean value. By default, certain values are considered "falsy"—they are interpreted as
False in a boolean context, such as None, 0, an empty string "", and empty containers like
[], {}, set() (more on these in the coming sections). All other values are considered
"truthy" and would be converted to True.
ST
print(bool(5)) # Output: True
print(bool(0)) # Output: False
R

print(bool('Hello')) # Output: True


ht

print(bool('')) # Output: False

print(bool([1, 2, 3])) # Output: True


ig

print(bool([])) # Output: False


yr

Remember that while bool data type might seem simple on the surface, it forms the
foundation of complex logic and decision-making in your Python programs. You'll find it plays
op

a pivotal role when you start dealing with conditional statements and loops.

3.8 None Data Type in Python


C

In Python, None is a special data type that represents the absence of a value or a null value.
It is an object of its own datatype, the NoneType. We cannot create multiple None objects
but can assign it to variables. These variables will be equal to one another.

We use None to indicate that a variable has no value. When we print a variable with the
value None, Python outputs None.

Here's how you can create a variable with a None value:

© Copyright RSTForum. Sharing of this material is illegal.


29
x = None

In this example, x is a variable and its value is None. We can also use None to represent an
empty state for a variable.

student_name = None

In this case, we might be planning to get the student's name later in the program, but at this
point, we're just declaring the student_name variable with no specific value.

.
We can check if a variable's value is None using the is operator:

m
x = None

ru
print(x is None) # Output: True

Fo
Unlike other programming languages, where you might use null, nil, or undefined, in
Python, we use None. However, the idea is the same: it's a way to say "this variable exists,
but it doesn't have a value yet."
ST
It's also worth noting that if you pass None to the bool() function, it will return False, which
allows None to be used in Boolean contexts.
R

print(bool(None)) # Output: False


ht

Python's None type is an important concept to understand, as it allows you to differentiate


between an "empty" value and a value that doesn't exist. This distinction can be especially
ig

crucial when dealing with data structures and when retrieving data that might not exist.
yr

3.9 Data Type Conversion in Python


Data type conversion, also known as typecasting, is the process of converting data from
op

one type to another. In Python, you might want to do this for various reasons, such as to
perform certain operations on variables, to meet function argument requirements, or to make
your code more readable and efficient.
C

Python provides several built-in functions that you can use for basic data type conversion.
These functions return a new object representing the converted value.

Here are some of the most commonly used data type conversion functions:

1. int(): Converts a number or a string to an integer.


2. float(): Converts a number or a string to a floating point number.
3. str(): Converts an object to a string representation.
4. bool(): Converts an object to a Boolean value (True or False).

© Copyright RSTForum. Sharing of this material is illegal.


30
5. list(): Converts an object to a list.
6. tuple(): Converts an object to a tuple.
7. set(): Converts an object to a set.
8. dict(): Converts a tuple of order (key,value) into a dictionary.

Let's see some examples of these functions in action:

# int() conversion
print(int(2.8)) # Output: 2
print(int("10")) # Output: 10

.
# float() conversion

m
print(float(2)) # Output: 2.0
print(float("2.8")) # Output: 2.8

ru
# str() conversion
print(str(25)) # Output: '25'

Fo
print(str(True)) # Output: 'True'

# bool() conversion
ST
print(bool(0)) # Output: False
print(bool(1)) # Output: True
print(bool(None)) # Output: False
R

print(bool('')) # Output: False


print(bool('Hello')) # Output: True
ht

# list(), tuple() and set() conversion


sample_str = 'Hello'
print(list(sample_str)) # Output: ['H', 'e', 'l', 'l', 'o']
ig

print(tuple(sample_str)) # Output: ('H', 'e', 'l', 'l', 'o')


print(set(sample_str)) # Output: {'e', 'H', 'l', 'o'}
yr

# dict() conversion
op

tuple_pairs = (('apple', 1), ('banana', 2))


print(dict(tuple_pairs)) # Output: {'apple': 1, 'banana': 2}
C

Remember, not all conversions are possible, and some may result in data loss or errors. For
example, trying to convert a string that doesn't represent a number into an integer or a float
will result in a ValueError.

print(int('Hello')) # Raises ValueError: invalid literal for int() with


base 10: 'Hello'

In Python, understanding how and when to convert data types is an important skill. It allows
you to work more flexibly with your data and is a key part of many Python techniques and

© Copyright RSTForum. Sharing of this material is illegal.


31
constructs.

Note: You may notice some unfamiliar terms in the data conversion examples above such
as list, tuple, set, and dict. Please do not worry about these yet. These are more complex
data types in Python, and they are used to store collections of data. We will discuss these
in great detail in upcoming chapters. For now, it's enough to know that Python provides
functions to convert data into these types, just like it does for int, float, str, and bool. As
you move forward in your Python journey, all of these concepts will start making more
sense.

.
m
3.10 Practice code

ru
1. Creating and Printing Variables

Fo
# Create two variables, 'a' and 'b', and assign them values of 3 and 4
respectively
a = 3
ST
b = 4

# Print the values of 'a' and 'b'


print("The value of a is:", a)
R

print("The value of b is:", b)


ht

2. Basic Arithmetic Operations


ig

# Add 'a' and 'b' and print the result


sum_ab = a + b
yr

print("The sum of a and b is:", sum_ab)

# Subtract 'b' from 'a' and print the result


op

difference_ab = a - b
print("The difference between a and b is:", difference_ab)
C

# Multiply 'a' and 'b' and print the result


product_ab = a * b
print("The product of a and b is:", product_ab)

# Divide 'a' by 'b' and print the result


quotient_ab = a / b
print("The quotient of a divided by b is:", quotient_ab)

3. String Manipulation

© Copyright RSTForum. Sharing of this material is illegal.


32
# Create a string variable and print it
my_string = "Hello, Python!"
print("My string is:", my_string)

# Print the length of the string using the 'len()' function


print("The length of my string is:", len(my_string))

# Print the first character of the string


print("The first character of my string is:", my_string[0])

# Print the last character of the string

.
print("The last character of my string is:", my_string[-1])

m
4. String Concatenation

ru
# Concatenate and print two strings

Fo
greeting = "Hello"
name = "Alice"
message = greeting + ", " + name + "!"
ST
print(message)

5. String Repetition
R

# Repeat a string multiple times and print it


cheer = "Go team! " * 3
ht

print(cheer)
ig

6. String Case Conversion


yr

# Convert a string to uppercase and print it


uppercase_string = my_string.upper()
op

print("Uppercase string:", uppercase_string)

# Convert a string to lowercase and print it


C

lowercase_string = my_string.lower()
print("Lowercase string:", lowercase_string)

7. String Replace

# Replace a substring within a string and print the result


new_string = my_string.replace("Python", "World")
print("Replaced string:", new_string)

© Copyright RSTForum. Sharing of this material is illegal.


33
8. Using Escape Characters

# Print a string with a newline escape sequence


print("Hello\nWorld")

# Print a string with a tab escape sequence


print("Hello\tWorld")

# Print a string with a backslash


print("Hello\\World")

.
9. Input and Output

m
ru
# Use the 'input()' function to get a user's name and greet them
name = input("What's your name? ")
print("Hello,", name, "!")

Fo
10. Input, Conversion, and Arithmetic
ST
# Ask the user for two numbers, convert them to integers, add them, and
print the result
num1 = int(input("Enter the first number: "))
R

num2 = int(input("Enter the second number: "))


print("The sum of the two numbers is:", num1 + num2)
ht

11. Formatting Strings with f-string


# Create two variables, 'name' and 'age', and assign them some values
ig

name = "Alice"
age = 25
yr

# Print a formatted string using f-string


op

print(f"My name is {name} and I am {age} years old.")

12. PEMDAS
C

# Calculate and print the result of the expression 3 + 4 * 2


print("Result of the expression 3 + 4 * 2 is:", 3 + 4 * 2)

# Now, change the order of operations using parentheses and print the
result
print("Result of the expression (3 + 4) * 2 is:", (3 + 4) * 2)

13. Multi-line Strings

© Copyright RSTForum. Sharing of this material is illegal.


34
# Create a multi-line string and print it
multi_line_string = """
Hello,
This is a multi-line string.
"""
print(multi_line_string)

14. String Slicing

.
# Create a string

m
text = "Hello, Python!"

ru
# Print the first 5 characters of the string
print("The first 5 characters:", text[:5])

Fo
# Print the last 5 characters of the string
print("The last 5 characters:", text[-5:])
ST
# Print characters from index 3 to 8
print("Characters from index 3 to 8:", text[3:8])

15. Checking String Start/End


R

# Check if the string starts with "Hello" and print the result
ht

print("Does the string start with 'Hello'? ", text.startswith("Hello"))


ig

# Check if the string ends with "Python!" and print the result
print("Does the string end with 'Python!'? ", text.endswith("Python!"))
yr

16. Data Type Conversion


op

# Convert an integer to a string and print its type


num = 5
C

num_str = str(num)
print("Type of num after conversion:", type(num_str))

# Convert a string to a float and print its type


float_str = "3.14"
float_num = float(float_str)
print("Type of float_num after conversion:", type(float_num))

17. Dynamic Typing

© Copyright RSTForum. Sharing of this material is illegal.


35
# Create a variable and assign it an integer value
x = 10
print("Type of x is:", type(x))

# Assign a string to the same variable


x = "Hello"
print("Now, type of x is:", type(x))

18. Python Type Hints

.
# Use type hints while declaring a variable

m
x: int = 10
print("Value of x is:", x)

ru
19. Python Boolean Type

Fo
# Assign boolean values to two variables and print them
x = True
y = False
ST
print("Values of x and y are:", x, y)

20. Python None Type


R

# Assign the None value to a variable and print it


ht

x = None
print("Value of x is:", x)
ig

21. Splitting a String


yr
op

# Create a string with several words


sentence = "Python is a great programming language."

# Use the 'split()' method to split the string into words and print the
C

result
words = sentence.split()
print("Words in the sentence:", words)

22. Joining a List of Strings

# Create a list of strings


words = ["Python", "is", "fun"]

© Copyright RSTForum. Sharing of this material is illegal.


36
# Use the 'join()' method to join the strings into a sentence and print
the result
sentence = " ".join(words)
print("Joined sentence:", sentence)

23. Swapping Values of Two Variables

# Create two variables, 'a' and 'b', and assign them some values
a = 3
b = 4

.
m
# Swap their values without using a temporary variable and print them
a, b = b, a

ru
print("Swapped values: a =", a, ", b =", b)

24. Using the 'find()' Method

# Create a string
text = "Hello, Python!"
Fo
ST
# Use the 'find()' method to find the index of the substring "Python"
and print the result
R

index = text.find("Python")
print("Index of 'Python':", index)
ht

25. Using the 'isdigit()' Method


ig

# Create a string
num_str = "1234"
yr

# Check if the string is made of digits and print the result


op

is_digit = num_str.isdigit()
print("Is the string made of digits?", is_digit)
C

26. Formatting Floats

# Create a float
pi = 3.14159

# Print the float with 2 decimal places


print(f"Value of Pi up to 2 decimal places: {pi:.2f}")

27. Zfill

© Copyright RSTForum. Sharing of this material is illegal.


37
# Use the 'zfill()' method to add leading zeros to a number and print
the result
num_str = "7"
print("Number with leading zeros:", num_str.zfill(3))

28. Check String Contains

# Check if a string contains a certain word and print the result


sentence = "Python is easy to learn."

.
print("Does the sentence contain the word 'easy'? ", "easy" in sentence)

m
29. String Strip

ru
# Remove leading and trailing spaces from a string and print the result

Fo
text = " Hello, Python! "
print("String after stripping spaces:", text.strip())
ST
30. Calculating Exponentials

# Calculate 2 raised to the power of 5 and print the result


R

print("2 raised to the power of 5 is:", 2**5)


ht
ig
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


38
Chapter 4: Branching and Conditionals

4.1 The input() Function


The input() function is a built-in Python function that reads a line from input, converts it
into a string, and returns that string. It's a crucial function for interacting with the user, making
your scripts and programs more dynamic and interesting.

Here is the simplest way to use input():

.
name = input()

m
print(name)

ru
When this code runs, it will wait for the user to type something and press Enter. Whatever
the user types will then be stored in the name variable and printed out.

Fo
The input() function can also take one argument: a string that is printed out as a prompt
before the function starts waiting for input:
ST
name = input("What's your name? ")
print("Hello, " + name + "!")
R

In this case, the user will see the text "What's your name? " before typing their input. The
response will then be stored in the name variable. The final line concatenates the strings and
prints out a personalized greeting for the user.
ht

Now, it's important to remember that input() always returns a string. Even if the user
ig

enters a number, it will be returned as a string. If you want to use the input as a number,
you'll need to convert it using int() or float():
yr

age = input("How old are you? ")


op

age = int(age) # convert the string to an integer

Now, let's put all this knowledge together to build a simple currency converter program:
C

print("Welcome to the Simple Currency Converter!")

# Ask the user for the amount in USD


usd = input("Please enter the amount in USD: ")
usd = float(usd) # convert the input to a float

# We'll use a conversion rate of 0.85 USD to 1 EUR for this example
conversion_rate = 0.85

© Copyright RSTForum. Sharing of this material is illegal.


39
# Calculate the equivalent amount in EUR
eur = usd * conversion_rate

print("That's equivalent to", eur, "EUR.")

This simple program first prints a welcome message. Then it asks the user to input an
amount in USD, converts the string input to a float, and calculates the equivalent amount in
EUR. The result is then printed out.

Remember, input() is a powerful tool for creating interactive programs. As we move

.
forward and learn about conditionals and loops, you'll see how we can use input() to

m
create more complex and interesting programs.

ru
4.2 Conditional (Relational) Operators

Fo
Conditional operators, also known as relational operators, form the backbone of
decision-making in Python. These operators are used to compare values, and they return
either True or False depending on whether the condition they are testing is fulfilled.
ST
Python has the following conditional operators:

1. Equal to (==): This operator checks if the values of two operands are equal. If yes,
R

the condition becomes true.

print(5 == 5) # True
ht

print(5 == 4) # False
ig

2. Not equal to (!=): This operator checks if the values of two operands are not equal.
If the values are not equal, the condition becomes true.
yr

print(5 != 5) # False
op

print(5 != 4) # True

3. Greater than (>): This operator checks if the value of the left operand is greater than
C

the value of the right operand. If yes, the condition becomes true.

print(5 > 4) # True


print(5 > 5) # False
print(4 > 5) # False

4. Less than (<): This operator checks if the value of the left operand is less than the
value of the right operand. If yes, the condition becomes true.

© Copyright RSTForum. Sharing of this material is illegal.


40
print(5 < 4) # False
print(5 < 5) # False
print(4 < 5) # True

5. Greater than or equal to (>=): This operator checks if the value of the left operand is
greater than or equal to the value of the right operand. If yes, the condition becomes
true.

print(5 >= 4) # True


print(5 >= 5) # True

.
print(4 >= 5) # False

m
6. Less than or equal to (<=): This operator checks if the value of the left operand is

ru
less than or equal to the value of the right operand. If yes, the condition becomes
true.

Fo
print(5 <= 4) # False
print(5 <= 5) # True
print(4 <= 5) # True
ST
Remember, these operators form the core of decision-making and flow control in Python, so
it's important to understand how they work. In the next section, we will use these operators
R

to introduce the concept of conditional statements in Python.


ht

4.3 Introduction to Branching and Conditionals


ig

In the real world, we make decisions based on certain conditions: "If it is raining, I will take
an umbrella. Otherwise, I won't." Similarly, in programming, we often need to perform
yr

different actions based on different conditions. This is where the concept of 'branching'
comes into play.
op

Branching, or conditional execution, refers to the ability of a program to execute different


sequences of instructions depending on the truth value of a condition. This introduces a
non-linear flow to the execution of a program, allowing it to 'branch out' and follow different
C

paths based on the inputs or state of the program.

4.3.1 If/Elif/Else Statements in Python


Python, like many other programming languages, provides a way to implement this
decision-making ability through the use of if, elif (stands for "else if"), and else
statements.

4.3.1.1 if Statement
The if statement is the most straightforward way to control the flow of a program. It checks

© Copyright RSTForum. Sharing of this material is illegal.


41
a condition, and if that condition evaluates to True, then the code block under the if
statement is executed. If the condition is False, then the code block is skipped.

Here's the basic syntax of an if statement:

if condition:
# code to execute if the condition is True

Let's see a simple example:

.
x = 10

m
if x > 5:
print("x is greater than 5")

ru
In this case, the condition is x > 5, which evaluates to True as 10 is indeed greater than 5.
Therefore, the statement "x is greater than 5" gets printed.

4.3.1.2 elif Statement

Fo
The elif statement allows you to check multiple expressions for True and execute a block
ST
of code as soon as one of the conditions evaluates to True.

Similar to else, the elif statement is optional. However, unlike else, for which there can be
R

at most one statement, there can be an arbitrary number of elif statements following an if.

Here's the basic syntax of an elif statement:


ht

if condition1:
ig

# code to execute if condition1 is True


elif condition2:
yr

# code to execute if condition2 is True


op

Let's see an example:

x = 20
C

if x > 30:
print("x is greater than 30")
elif x > 10:
print("x is greater than 10 but not greater than 30")

In this case, the first condition x > 30 is False, so Python skips the first print statement and
checks the next condition x > 10, which is True, so the statement "x is greater than
10 but not greater than 30" gets printed.

© Copyright RSTForum. Sharing of this material is illegal.


42
4.3.1.3 else Statement
The else statement complements the if statement. An if/else pair says: "If this condition
is true, execute this code block; otherwise, execute that code block."

Here's the basic syntax of an else statement:


if condition:
# code to execute if the condition is True
else:
# code to execute if the condition is False

.
Let's see an example:

m
x = 5

ru
if x > 10:
print("x is greater than 10")
else:

Fo
print("x is not greater than 10")

In this example, the condition x > 10 is False as 5 is not greater than 10. Therefore, the
ST
else block is executed, and the statement "x is not greater than 10" gets printed.

Keep in mind, an else statement always comes after any if and elif statements, and gets
R

executed when none of the previous conditions are True.

4.3.1.4 Chaining if, elif, and else


ht

We can chain if, elif, and else statements to create more complex decision-making
structures. Here is an example:
ig

x = 15
yr

if x > 20:
print("x is greater than 20")
op

elif x > 10:


print("x is greater than 10 but not greater than 20")
else:
C

print("x is not greater than 10")

In this case, the first condition x > 20 is False, so Python checks the next condition x >
10, which is True, so the statement "x is greater than 10 but not greater than
20" gets printed. The else block is not executed as one of the preceding conditions is
True.

This should provide a solid understanding of how to use branching and conditionals in
Python. Keep in mind that understanding the logic and flow of conditionals is key to
developing complex programs. Practice with a variety of scenarios to become more

© Copyright RSTForum. Sharing of this material is illegal.


43
comfortable with using if, elif, and else statements in Python.

4.3.2 More Examples of Conditionals in Python


Now that we have discussed the basic if, elif, and else statements in Python, let's take a look
at some more complex, real-world examples to further illustrate their use.

1. Determining an individual's age group based on their age

age = 25

.
m
if age < 13:
print("Child")
elif age < 20:

ru
print("Teenager")
elif age < 60:

Fo
print("Adult")
else:
print("Senior")
ST
In this example, an individual's age group is determined based on their age. Depending on
the age input, the program will print whether the individual is a "Child", "Teenager", "Adult",
or "Senior".
R

2. Temperature alert system


ht

temperature = 30
ig

if temperature < 0:
print("Extreme Cold Alert!")
yr

elif temperature < 20:


print("Cold Alert!")
op

elif temperature > 40:


print("Extreme Heat Alert!")
else:
C

print("Temperature is normal.")

This example simulates a simple temperature alert system. If the temperature falls below 0
degrees, it alerts "Extreme Cold Alert!". If it's between 0 and 20, it alerts "Cold Alert!". If the
temperature rises above 40 degrees, it alerts "Extreme Heat Alert!". Otherwise, it simply
prints that the temperature is normal.

3. Movie rating system

© Copyright RSTForum. Sharing of this material is illegal.


44
movie_rating = 7.5

if movie_rating >= 8:
print("Great movie!")
elif movie_rating >= 5:
print("Average movie.")
else:
print("Below average movie.")

In this example, a movie is rated based on its score. If the movie score is 8 or more, it's
considered a "Great movie!". If it's between 5 and 8, it's an "Average movie.". Otherwise, it's

.
a "Below average movie.".

m
4. Exam Grade System

ru
exam_score = 85

Fo
if exam_score >= 90:
print("Grade: A")
ST
elif exam_score >= 80:
print("Grade: B")
elif exam_score >= 70:
print("Grade: C")
R

elif exam_score >= 60:


print("Grade: D")
else:
ht

print("Grade: F")
ig

In this example, an exam grade is determined based on an exam score. If the score is 90 or
above, the grade is 'A'. For scores between 80 and 90, the grade is 'B'. For scores between
yr

70 and 80, the grade is 'C'. For scores between 60 and 70, the grade is 'D'. For any score
below 60, the grade is 'F'.
op

Remember, these examples still follow the basic structure of if, elif, and else statements. The
conditions have simply become more complex. Practice writing your own examples and think
about how you can use branching and conditionals to make your code more dynamic and
C

flexible.

4.4 Truthy and Falsy Values


In Python, every object has a boolean value, and can be considered either True or False
when evaluating in a boolean context. This idea is key to understanding how Python treats
different objects and values when using conditionals, and it introduces us to the concept of
"truthiness" and "falsiness".

By default, an object is considered True unless its class defines a boolean value to be

© Copyright RSTForum. Sharing of this material is illegal.


45
False or the object has a __bool__() method that returns False. (more on this later, in the
Object Orientation section)

Here are some of the most common "falsy" values in Python:

1. Constants defined to be false: None and False.


2. Zero of any numeric type: 0, 0.0, 0j.
3. Empty sequences and collections: '', (), [], {}, set(), range(0).

In all other situations, an object is considered "truthy".

Here are some examples:

.
m
# False because the string is empty

ru
if '':
print("The string is not empty.")
else:

Fo
print("The string is empty.") # This will be printed

# True because the string is not empty


ST
if 'Hello':
print("The string is not empty.") # This will be printed
else:
print("The string is empty.")
R

# False because the number is zero


ht

if 0:
print("The number is not zero.")
else:
ig

print("The number is zero.") # This will be printed


yr

# True because the number is not zero


if 1:
op

print("The number is not zero.") # This will be printed


else:
print("The number is zero.")
C

In these examples, the if statement is evaluating the "truthiness" or "falsiness" of the values.
When used with if statements, Python automatically checks whether a value is True or
False. If it's True (i.e., truthy), the if block is executed. If it's False (i.e., falsy), the else
block (if present) is executed.

Understanding this concept is key when working with conditionals in Python. In the following
sections, we will see how this is crucial for creating effective, efficient, and flexible
conditional logic in our Python programs.

© Copyright RSTForum. Sharing of this material is illegal.


46
4.5 Logical Operators
Logical operators in Python are used to combine conditional statements. They provide a way
to create more complex rules and conditions for your code to follow. There are three logical
operators in Python:

1. and: Returns True if both the operands are true


2. or: Returns True if either of the operands is true
3. not: Returns True if the operand is false (complements the operand)

4.5.1 and Operator

.
The and operator returns True if both conditions on its left and right are True.

m
print(True and True) # Returns: True

ru
print(True and False) # Returns: False
print(False and True) # Returns: False

Fo
print(False and False) # Returns: False
ST
4.5.2 or Operator
The or operator returns True if at least one of the conditions on its left or right is True.
R

print(True or True) # Returns: True


print(True or False) # Returns: True
ht

print(False or True) # Returns: True


print(False or False) # Returns: False
ig

4.5.3 not Operator


yr

The not operator reverses the truthiness of the condition that follows it.
op

print(not True) # Returns: False


print(not False) # Returns: True
C

These logical operators can be combined with the relational operators to create complex
conditions. Let's see an example:

age = 25
country = 'India'

if age >= 18 and country == 'India':


print("You are eligible to vote in India.")

© Copyright RSTForum. Sharing of this material is illegal.


47
else:
print("You are not eligible to vote in India.")

In this code, we are checking if the person is at least 18 years old and if they are in India.
Only if both conditions are True will they be allowed to vote.

Complex Example
Now, let's create a more complex example:

age = 25

.
country = 'India'

m
has_voter_id = False

if age >= 18 and country == 'India':

ru
if not has_voter_id:
print("Sorry, you must have a valid voter ID to vote in India.")

Fo
else:
print("You are eligible to vote in India.")
else:
ST
print("You are not eligible to vote in India.")

In this example, we added a has_voter_id variable. We are checking if the person is at


least 18 years old, if they are in India, and if they have a valid voter ID. Only if all conditions
R

are True will they be allowed to vote. The not operator is used to reverse the
has_voter_id boolean, meaning the if condition will pass if has_voter_id is False.
ht

4.7 Rock, Paper, Scissors Game


ig

In this section, we'll put all that we've learned together to create a simple rock, paper,
scissors game. Here's how the game is played: rock beats scissors, scissors beats paper,
yr

and paper beats rock.


op

print("Welcome to Rock, Paper, Scissors Game!")

# Player 1's turn


C

player1 = input("Player 1, please enter your choice


(rock/paper/scissors): ")

# Player 2's turn


player2 = input("Player 2, please enter your choice
(rock/paper/scissors): ")

if player1 == player2:
print("It's a draw!")
elif player1 == "rock":

© Copyright RSTForum. Sharing of this material is illegal.


48
if player2 == "scissors":
print("Player 1 wins!")
else:
print("Player 2 wins!")
elif player1 == "scissors":
if player2 == "paper":
print("Player 1 wins!")
else:
print("Player 2 wins!")
elif player1 == "paper":
if player2 == "rock":

.
print("Player 1 wins!")

m
else:
print("Player 2 wins!")

ru
else:
print("Invalid input! You have not entered rock/paper/scissors, try
again.")

Fo
In the above code, we're using the input() function to get the choices of the two players.
We're then using conditionals and nested conditionals to determine the winner based on the
ST
rules of the game.

First, we check if both players have made the same choice. If so, the game is a draw.
R

If not, we check each possibility for Player 1's choice.


ht

1. If Player 1 chose rock, and Player 2 chose scissors, Player 1 wins. Otherwise
(meaning Player 2 must have chosen paper), Player 2 wins.
2. If Player 1 chose scissors, and Player 2 chose paper, Player 1 wins. Otherwise
ig

(meaning Player 2 must have chosen rock), Player 2 wins.


3. If Player 1 chose paper, and Player 2 chose rock, Player 1 wins. Otherwise (meaning
yr

Player 2 must have chosen scissors), Player 2 wins.


op

Lastly, if Player 1 enters something other than rock, paper, or scissors, we print a message
telling them they made an invalid choice.
C

This game encapsulates many of the concepts we've learned: user input, strings, and
conditionals.. You can expand on this game, add more features, and handle more edge
cases as you continue to learn more about Python!

© Copyright RSTForum. Sharing of this material is illegal.


49
Chapter 5: Loops

5.1 The Concept of Loops


Loops in programming are a fundamental concept. They allow for a sequence of instructions
to be continually repeated until a certain condition is met. Imagine you have a task to print
numbers from 1 to 100. You could write 100 lines of code printing each number. But that's
inefficient. Instead, we can use a loop that will repeat the print command for us, changing the
number each time.

This is the essence of a loop: doing repetitive tasks efficiently and cleanly. Loops are a way

.
m
for a program to do a task a specific number of times, or until a certain condition is met. This
condition is called the loop condition.

ru
Loops have three main components: initialization (where we set the starting condition), the
condition (which, as long as it's True, keeps the loop running), and the increment (where we

Fo
change the condition so that the loop will eventually stop).

5.2 For Loops in Python


ST
The for loop in Python is used to iterate over a sequence (such as a string) or other iterable
objects. Iterating over a sequence is called traversal.
R

Here's the basic syntax of a for loop in Python:

for variable in sequence:


ht

# code to be executed
ig

5.2.1 Basic Example of a For Loop


yr

Let's consider an example where we want to print each letter of a string:


op

for letter in 'Python':


print(letter)
C

This code will output:

P
y
t
h
o
n

© Copyright RSTForum. Sharing of this material is illegal.


50
Here, 'Python' is the sequence, and 'letter' is the variable that takes the value of the item
inside the sequence for each iteration.

5.2.2 The Range Function


The range() function in Python is a unique function that allows us to generate a sequence
of numbers within the given range. It's often used with loops to repeat an action a certain
number of times.

The range() function can take up to three arguments:

● range(stop) takes one argument.

.
● range(start, stop) takes two arguments.

m
● range(start, stop, step) takes three arguments.

ru
1. start: Starting number of the sequence. If not provided, it defaults to 0.
2. stop: Generate numbers up to, but not including, this number.

Fo
3. step: Difference between each number in the sequence. If not provided, it defaults to
1.

Here's an example:
ST
print(range(10)) # This will output: range(0, 10)
R

In the example above, range(10) generates a sequence of numbers from 0 to 9. To get a


list of numbers from range(), we can convert it to a list using the list() function, like so:
ht

print(list(range(10))) # This will output: [0, 1, 2, 3, 4, 5, 6, 7, 8,


ig

9]
yr

5.2.3 For Loop with Range Function


We can use for loops in conjunction with the range() function. This is useful when we want
op

to perform an action a certain number of times. For instance, if we wanted to print numbers
from 0 to 4, we could use a for loop with range(5):
C

for i in range(5):
print(i)

The output would be:

0
1
2
3

© Copyright RSTForum. Sharing of this material is illegal.


51
4

5.2.4 Examples of For Loops

1. Counting Down

for i in range(10, 0, -1):


print(i)

.
This code counts down from 10 to 1. The range function here starts at 10, ends before 0,

m
and decrements the counter by -1 in each iteration.

2. Sum of Natural Numbers

ru
sum = 0

Fo
for i in range(1, 11): # Loop from 1 to 10
sum += i
print("Sum of first 10 natural numbers is:", sum)
ST
Here, we are calculating the sum of the first 10 natural numbers. sum += i is equivalent to
sum = sum + i, meaning each time the loop iterates, the current number i is added to sum.
R

3. Printing Every Second Number


ht

for i in range(0, 20, 2):


print(i)
ig

This code prints every second number from 0 to 20. The third parameter in range, the 'step',
yr

is set to 2, which means it will 'step' over every second number.


op

4. Printing Elements of a String in Reverse Order

word = "Python"
C

length = len(word)
for i in range(length - 1, -1, -1):
print(word[i])

This code prints the characters of the word "Python" in reverse order. It does so by iterating
over the indices of the string in reverse order, from the last index to the first.

5. Checking Divisibility

© Copyright RSTForum. Sharing of this material is illegal.


52
for i in range(1, 101):
if i % 5 == 0 and i % 7 == 0:
print(f"{i} is divisible by both 5 and 7")

This example prints all numbers between 1 and 100 that are divisible by both 5 and 7. The %
operator gives the remainder of a division. If i % 5 and i % 7 are both 0, i is divisible by both
5 and 7.

6. Calculating Factorial

.
n = 5

m
factorial = 1
for i in range(1, n + 1):
factorial *= i

ru
print(f"The factorial of {n} is {factorial}")

Fo
This code calculates the factorial of a number. A factorial of a number n is the product of all
positive integers less than or equal to n.
ST
7. Table of a Number

n = 5
R

for i in range(1, 11):


print(f"{n} * {i} = {n * i}")
ht

This prints the multiplication table for the number 5.


ig

8. Printing a Pattern
yr

for i in range(1, 6):


for j in range(i):
op

print("*", end="")
print()
C

This prints a pattern of asterisks. The end="" argument in the print function prevents it from
printing a new line at the end of each print statement.

9. Count the Number of Digits in a Number

number = 12345
count = 0
for i in str(number):
count += 1

© Copyright RSTForum. Sharing of this material is illegal.


53
print(f"The number of digits in {number} is {count}")

This code counts the number of digits in a number by converting the number into a string
and then iterating over each character (digit) in that string.

10. Calculate the Power of a Number

base = 2
exponent = 5
result = 1

.
m
for _ in range(exponent):
result *= base

ru
print(f"{base} to the power of {exponent} is {result}")

Fo
This code calculates the power of a number by multiplying the base with itself for the number
of times specified by the exponent. Here _ is a convention used for a variable that we don't
care about. In this case, we don't use the variable in the loop body.
ST
Remember, these are just a few examples of how for loops can be used in Python. The
possibilities are virtually endless, depending on the problem you're trying to solve. Keep
practicing and exploring other examples to solidify your understanding of loops.
R

5.2.5 FizzBuzz in Python


ht

The FizzBuzz problem: Write a program that prints the numbers from 1 to 100. But for
multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz".
ig

For numbers which are multiples of both three and five print "FizzBuzz". The rest of the
numbers should just be printed as they are.
yr

The FizzBuzz problem is a very common programming challenge often used in coding
interviews. It's a relatively simple problem, but it requires understanding of loops and
op

conditionals. Here's how you can solve it using a for loop in Python:

for i in range(1, 101):


C

if i % 3 == 0 and i % 5 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)

© Copyright RSTForum. Sharing of this material is illegal.


54
Explanation:

We loop over the numbers 1 through 100 using the range() function. The range function
generates a sequence of numbers, starting from the first parameter (inclusive) and ending at
the second parameter (exclusive).

For each number, we use if/elif/else statements to check certain conditions:

● if i % 3 == 0 and i % 5 == 0: The % operator computes the remainder of division.


i % 3 is the remainder of the division of i by 3. If it equals 0, i is a multiple of 3.
Similarly, i % 5 == 0 checks if i is a multiple of 5. The and operator checks if both

.
conditions are True. So, this condition checks if i is a multiple of both 3 and 5. If it is,

m
the program prints "FizzBuzz".
● elif i % 3 == 0: This condition checks if i is a multiple of 3. If it is, the program
prints "Fizz".

ru
● elif i % 5 == 0: This condition checks if i is a multiple of 5. If it is, the program
prints "Buzz".

Fo
● else: If none of the above conditions are True (that is, if i is not a multiple of 3 or
5), the program just prints the number i.
ST
The key point here is the order of the conditions. The first condition to evaluate to True will
be the one that gets executed. This is why we check for the "FizzBuzz" case first (as it's the
most specific case), and then check for "Fizz" and "Buzz".
R

5.3 The while Loop in Python


ht

The while loop in Python is used to repeatedly execute a block of statements as long as a
certain condition is true. The basic syntax of a while loop in Python is:
ig

while condition:
# statements to execute
yr

Here, condition is a boolean expression that the while loop checks before each iteration. If
op

the condition is True, the loop will execute the indented block of code. After executing the
block of code, it goes back to check the condition again. This loop continues until the
condition becomes False. When that happens, the loop terminates, and the program
C

continues with the rest of the code after the while loop.

Key Points

● Boolean Condition: The condition must be a boolean expression, i.e., it must


evaluate to either True or False.

● Loop Control Variable: Typically, the condition involves one or more variables that
change their values in the course of execution and control the number of times the
loop executes. These are known as the loop control variables.

© Copyright RSTForum. Sharing of this material is illegal.


55
● Termination: If the condition never becomes false, the while loop will continue to run
forever, creating an infinite loop. To avoid this, we must ensure that something within
the loop's code will eventually make the condition false.

Let's start with a very simple example.

Example 1: Print the numbers 1 through 5.

i = 1
while i <= 5:
print(i)

.
i += 1

m
In this example, the loop control variable i starts at 1. The condition is i <= 5, which is

ru
True at the start, so the loop begins. Inside the loop, we first print the current value of i, then
increment i by 1 (i += 1 is equivalent to i = i + 1). When i becomes 6, the condition i <=

Fo
5 becomes False, and the loop terminates.

Example 2: Reverse Count from 10 to 1.


ST
i = 10
while i > 0:
print(i)
R

i -= 1
In this example, we start from 10 and decrement i by 1 in each iteration until i is no longer
ht

greater than 0.

Example 3: A simple interactive program.


ig

print("Enter 'q' to quit.")


yr

user_input = ""
while user_input != 'q':
op

user_input = input("Enter a character: ")

In this example, the loop continues asking the user for input until the user enters 'q'.
C

While loops are very versatile and can be used for various purposes like monitoring system
status, validating user input, etc. In the next section, we'll see some real-world-like examples
of while loops.

© Copyright RSTForum. Sharing of this material is illegal.


56
5.4 The break Statement

5.4.1 Concept
The break statement in Python is used to exit or "break" out of a loop (either for or while)
prematurely, regardless of the loop's conditional expression.

while condition:
# statements to execute
if some_other_condition:
break # break out of the loop immediately

.
m
Similarly, in a for loop:

ru
for item in iterable:
# statements to execute

Fo
if some_other_condition:
break # break out of the loop immediately
ST
When the program execution reaches the break statement, it immediately stops the current
loop execution and continues executing the next line of code after the loop.
R

5.4.2 Examples
Example 1: Stopping a while loop.
ht

count = 0
while True: # This would be an infinite loop without the break
ig

statement
print(count)
yr

count += 1
if count >= 5:
op

break # When count is 5 or more, we break out of the loop

In this example, we start an infinite loop with while True:. The loop will continue indefinitely
C

unless we stop it manually. We increment count by 1 during each iteration, and when count
becomes 5, we use the break statement to exit the loop.

Example 2: Exiting a for loop prematurely.

for num in range(1, 11): # iterating over numbers from 1 to 10


if num == 5:
break # break the loop when num equals 5
print(num)

© Copyright RSTForum. Sharing of this material is illegal.


57
In this example, we are looping over a range of numbers from 1 to 10. When the number is
5, we use the break statement to exit the loop immediately. So, this program will only print
numbers from 1 to 4.

Now let's look at a complex real-world example where we can use a while loop and the
break statement together.

Example 3: A simple ATM machine program.

balance = 1000.0 # initial account balance

.
while True: # start an infinite loop

m
print("\nWelcome to the ATM!")
print("1. Show Balance")

ru
print("2. Deposit Money")
print("3. Withdraw Money")
print("4. Quit")

Fo
choice = input("Enter your choice: ")

if choice == "1":
ST
print(f"\nYour balance is: ${balance}")

elif choice == "2":


amount = float(input("Enter amount to deposit: "))
R

balance += amount
ht

elif choice == "3":


amount = float(input("Enter amount to withdraw: "))
if amount <= balance:
ig

balance -= amount
else:
yr

print("\nInsufficient balance!")
op

elif choice == "4":


print("\nThank you for using the ATM!")
break # user wants to quit, so break the loop
C

else:
print("\nInvalid choice! Please try again.")

In this example, we have simulated a very simplified ATM machine. The program presents
the user with a menu of choices in an infinite while loop. If the user enters '4', we break out
of the loop using the break statement. If the user enters an invalid choice, the loop simply
continues, showing the menu again. This is a basic example of how ATM machines operate
in the real world.

© Copyright RSTForum. Sharing of this material is illegal.


58
5.5 The continue Statement

5.5.1 Concept
The continue statement in Python is used to skip the rest of the code inside a loop (either
for or while) for the current iteration and move directly to the next iteration.

while condition:
# statements to execute
if some_other_condition:
continue # Skip the rest of this iteration and continue with

.
the next

m
# more statements

ru
Similarly, in a for loop:

Fo
for item in iterable:
# statements to execute
if some_other_condition:
ST
continue # Skip the rest of this iteration and continue with
the next
# more statements
R

When a continue statement is encountered, the program execution immediately jumps


back to the start of the loop and re-evaluates the loop's condition.
ht

5.5.2 Examples
ig

Example 1: Skipping certain iterations in a while loop.


yr

count = 0
while count < 10:
op

count += 1
if count % 2 == 0: # if count is an even number
continue # skip the print statement and move to the next
C

iteration
print(count)

In this example, the continue statement is used to skip the printing of even numbers. The
print statement is skipped each time count is an even number.

Example 2: Skipping certain iterations in a for loop.

for num in range(1, 11): # iterating over numbers from 1 to 10

© Copyright RSTForum. Sharing of this material is illegal.


59
if num % 3 == 0: # if num is divisible by 3
continue # skip the print statement and move to the next
iteration
print(num)

In this example, we are looping over a range of numbers from 1 to 10. When the number is
divisible by 3, we use the continue statement to skip the printing of that number and move
directly to the next iteration. So, this program will only print numbers that are not divisible by
3.

Example 3: A complex example involving user input.

.
m
while True: # start an infinite loop
user_input = input("Enter a number (or 'q' to quit): ")

ru
if user_input == 'q':
break # if user wants to quit, break the loop

Fo
number = int(user_input)
if number % 2 == 0: # if the number is even
continue # skip the rest and move to the next iteration
ST
print(f"{number} squared is {number**2}")

In this example, we are taking a number as input from the user in an infinite loop. If the user
enters an even number, we use the continue statement to skip the calculation and printing of
R

the square of the number, and we move directly to the next iteration. Thus, this program will
only print the squares of odd numbers.
ht

5.5.3 Applying Loops to the Rock, Paper, Scissors Game


ig

Let's take the Rock, Paper, Scissors game we developed earlier and improve it by using a
while loop. We can use the loop to keep the game running until the user decides to quit.
yr

print("Welcome to Rock, Paper, Scissors Game!")


op

while True: # game loop


# Player 1's turn
C

player1 = input("\nPlayer 1, please enter your choice


(rock/paper/scissors) or 'q' to quit: ")

# If the player wants to quit


if player1.lower() == 'q':
break

# Check for a valid input


if player1.lower() not in ['rock', 'paper', 'scissors']:
print("Invalid input. Please enter either rock, paper, or

© Copyright RSTForum. Sharing of this material is illegal.


60
scissors.")
continue

# Player 2's turn


player2 = input("Player 2, please enter your choice
(rock/paper/scissors) or 'q' to quit: ")

# If the player wants to quit


if player2.lower() == 'q':
break

.
# Check for a valid input

m
if player2.lower() not in ['rock', 'paper', 'scissors']:
print("Invalid input. Please enter either rock, paper, or

ru
scissors.")
continue

Fo
if player1 == player2:
print("It's a draw!")
elif player1 == "rock":
ST
if player2 == "scissors":
print("Player 1 wins!")
else:
R

print("Player 2 wins!")
elif player1 == "scissors":
if player2 == "paper":
ht

print("Player 1 wins!")
else:
print("Player 2 wins!")
ig

elif player1 == "paper":


if player2 == "rock":
yr

print("Player 1 wins!")
else:
op

print("Player 2 wins!")

print("\nThank you for playing. Goodbye!")


C

Explanation:

while True:

We initiate an infinite loop with 'while True'. This loop will continue until a 'break' statement is
encountered.

print("\n--- New Round! ---")

© Copyright RSTForum. Sharing of this material is illegal.


61
At the start of each round, we print a line to the console indicating the beginning of a new
round for the users.

player1 = input("\nPlayer 1, please enter your choice


(rock/paper/scissors): ")
player2 = input("Player 2, please enter your choice
(rock/paper/scissors): ")

In these two lines, we are taking the input from the two players at each round of the game.
They can enter their choice from 'rock', 'paper' or 'scissors'.

.
m
if player1 == 'q' or player2 == 'q':
break

ru
Here, we provide a way for the players to end the game by entering 'q'. If either of the

Fo
players enters 'q', the infinite loop will be broken and the game will end.

if player1 == player2:
ST
print("It's a draw!")
elif player1 == "rock":
#... remaining game logic code
R

This is the game logic as explained previously. If both players choose the same, it's a draw.
The following lines then check the various possible combinations of choices to decide and
ht

announce the winner of the round.


ig

play_again = input("Do you want to play another round? (yes/no): ")


if play_again.lower() != "yes":
yr

break
op

Finally, we give the players the option to play another round. If they enter anything other than
'yes', the game will end. We use the 'lower()' function here to ensure that the comparison is
case-insensitive.
C

If the players choose to continue, the program loops back to the beginning of the 'while' loop
and starts a new round. If they choose to stop, the 'break' statement is executed and the
loop (and the game) ends.

© Copyright RSTForum. Sharing of this material is illegal.


62
Chapter 5: Data Structures

5.1 Understanding Data Structures


A data structure is a particular way of organizing and storing data in a computer so that it
can be used efficiently. In simple terms, it's a specialized format for organizing and storing
data. Think of it like a container for data where each container has its own unique attributes
and capabilities.

Why do we need data structures? In programming, the process of managing and organizing
data is a critical component to write efficient code and solve complex problems. Certain data

.
m
structures are designed to hold particular types of data, and some are highly specialized to
specific tasks. For instance, if you need to frequently access elements by index, lists or
arrays would be beneficial. If you require unique items, a set is more appropriate. Therefore,

ru
the use of appropriate data structures can enhance the functionality, performance, and
efficiency of our software applications.

Fo
5.2 Python Lists
One of the most fundamental data structures in any language is the array. Python doesn't
ST
have a native array data structure, but it has the ‘list’ which is much more general and can
be used as a multidimensional array quite easily.
R

Python lists are one of the core data structures that the language offers. A list is used to
store an ordered collection of items, which might be of different types but usually they are all
of the same type. The items are ordered and can be accessed by their position in the list,
ht

with the first item at position 0.


ig

5.2.1 Creating Lists


Creating a list in Python is straightforward. You place the items (or "elements") of your list in
yr

square brackets [], separated by commas. Here's an example:


op

fruits = ['apple', 'banana', 'cherry', 'date']


print(fruits)
C

When you run this code, Python will print:

['apple', 'banana', 'cherry', 'date']

This is a list of four items, all of them strings. You can also make a list of numbers (integers,
floating point, etc.), or a mix of different data types.

5.2.2 Accessing Elements


The elements in a list are indexed starting from 0. This means that the first item is at position

© Copyright RSTForum. Sharing of this material is illegal.


63
0, the second item is at position 1, and so on. To access an item in a list, you use its index.
Here's how:

fruits = ['apple', 'banana', 'cherry', 'date']


print(fruits[0]) # Output: 'apple'

You can also use negative indexing to access items from the end of the list. An index of -1
refers to the last item, -2 refers to the second last item, and so on.

print(fruits[-1]) # Output: 'date'

.
m
5.2.3 Modifying Elements
Since lists are mutable, you can modify their contents. You can change an item by referring

ru
to its position in the list. Here's how to change the second item ('banana') to 'blueberry':

Fo
fruits = ['apple', 'banana', 'cherry', 'date']
fruits[1] = 'blueberry'
print(fruits) # Output: ['apple', 'blueberry', 'cherry', 'date']
ST
5.2.4 Adding Elements
To add an item to the end of the list, use the append() method:
R

fruits = ['apple', 'banana', 'cherry', 'date']


ht

fruits.append('elderberry')
print(fruits) # Output: ['apple', 'banana', 'cherry', 'date',
ig

'elderberry']
yr

You can also insert an item at a specific position with the insert() method, which takes
two arguments: the position (or "index") and the item.
op

fruits = ['apple', 'banana', 'cherry', 'date']


fruits.insert(1, 'blueberry')
C

print(fruits) # Output: ['apple', 'blueberry', 'banana', 'cherry',


'date']

5.2.5 Removing Elements


Python provides several methods to remove items from a list. The simplest one is remove(),
which removes the first occurrence of a specified item.

fruits = ['apple', 'banana', 'cherry', 'banana', 'date']


fruits.remove('banana')

© Copyright RSTForum. Sharing of this material is illegal.


64
print(fruits) # Output: ['apple', 'cherry', 'banana', 'date']

5.2.6 The pop() Method


The pop() method removes an item at a specific position and returns it. This means that you
can use the returned item in your code if you need to. Here's how you use it:

fruits = ['apple', 'banana', 'cherry', 'date']


popped_fruit = fruits.pop(1)
print(popped_fruit) # Output: 'banana'

.
m
print(fruits) # Output: ['apple', 'cherry', 'date']

In this case, the pop() method removed the item at position 1 (the second item), which is

ru
'banana', and then it returned this item. The print() function then printed 'banana'. The last
print() function call showed that 'banana' is no longer in the list.

Fo
If you call the pop() method without any argument, it removes and returns the last item.
ST
fruits = ['apple', 'banana', 'cherry', 'date']
popped_fruit = fruits.pop()
print(popped_fruit) # Output: 'date'
R

print(fruits) # Output: ['apple', 'banana', 'cherry']

5.2.7 The del Statement


ht

Python also has a del statement (not a method) that you can use to remove an item at a
specific position, or to remove a slice of items. Unlike pop(), del does not return the
ig

removed item(s).
yr

Here's how to use del to remove an item:


op

fruits = ['apple', 'banana', 'cherry', 'date']


del fruits[1]
print(fruits) # Output: ['apple', 'cherry', 'date']
C

5.2.8 Other Python List Methods


Lists are one of the most powerful and flexible data types in Python, with several built-in
methods that you can use to manipulate and interact with them. Here are some more useful
list methods:

5.2.8.1 The extend() Method


The extend() method adds all elements of a list (or any iterable) to the end of the current
list. This is similar to append(), but instead of adding a single element, extend() adds all

© Copyright RSTForum. Sharing of this material is illegal.


65
elements individually.

fruits = ['apple', 'banana', 'cherry']


more_fruits = ['date', 'elderberry', 'fig']
fruits.extend(more_fruits)
print(fruits) # Output: ['apple', 'banana', 'cherry', 'date',
'elderberry', 'fig']

5.2.8.2 The insert() Method


The insert() method can insert an item at a specific position. This is useful when you don't

.
want to add an item at the end (like append()) or at the beginning (like prepend()), but

m
somewhere in the middle.

ru
fruits = ['apple', 'banana', 'cherry']
fruits.insert(1, 'avocado')
print(fruits) # Output: ['apple', 'avocado', 'banana', 'cherry']

Fo
In this case, 'avocado' was inserted at position 1, pushing 'banana' and 'cherry' one position
to the right.
ST
5.2.8.3 The index() Method
The index() method returns the index of the first occurrence of an item.
R

fruits = ['apple', 'banana', 'cherry', 'date', 'banana']


ht

print(fruits.index('banana')) # Output: 1
ig

In this case, 'banana' occurs twice, but index() only returned the position of the first
occurrence.
yr

5.2.8.4 The count() Method


The count() method returns the number of times a specific item occurs in a list.
op

fruits = ['apple', 'banana', 'cherry', 'date', 'banana']


C

print(fruits.count('banana')) # Output: 2

In this case, 'banana' occurs twice in the list.

5.2.8.5 The sort() Method


The sort() method sorts the items in a list in ascending order. If the list contains strings, it
sorts them in lexicographical (alphabetical) order.

numbers = [6, 1, 5, 2, 4, 3]

© Copyright RSTForum. Sharing of this material is illegal.


66
numbers.sort()
print(numbers) # Output: [1, 2, 3, 4, 5, 6]

fruits = ['banana', 'apple', 'cherry', 'date']


fruits.sort()
print(fruits) # Output: ['apple', 'banana', 'cherry', 'date']

5.2.8.6 The reverse() Method


The reverse() method reverses the order of items in a list.

.
m
numbers = [1, 2, 3, 4, 5, 6]
numbers.reverse()

ru
print(numbers) # Output: [6, 5, 4, 3, 2, 1]

5.2.8.7 The copy() Method (Continued)

Fo
The copy() method returns a copy of the list. This can be useful when you want to keep the
original list intact while modifying the copied list.
ST
fruits = ['apple', 'banana', 'cherry']
fruits_copy = fruits.copy()
fruits_copy.append('date')
R

print(fruits) # Output: ['apple', 'banana', 'cherry']


print(fruits_copy) # Output: ['apple', 'banana', 'cherry', 'date']
ht

In this example, we appended 'date' to the copied list, but the original list remained
unchanged.
ig

5.2.8.8 The clear() Method


yr

The clear() method removes all items from a list.


op

fruits = ['apple', 'banana', 'cherry']


fruits.clear()
print(fruits) # Output: []
C

After using the clear() method, the 'fruits' list is now empty.

Summary
This covers the basic operations with lists. But Python lists have many more methods and
features, which we'll explore in the following sections.

Lists in Python provide a host of powerful built-in methods to make list manipulation an
efficient task. These methods can help you perform a variety of operations such as adding,
removing, searching, sorting, reversing, copying, and clearing items. Understanding how to
© Copyright RSTForum. Sharing of this material is illegal.
67
use these methods can go a long way in making your code cleaner, more efficient, and more
readable. Experimenting with different methods and scenarios will help you become more
comfortable and proficient with Python lists.

5.2.9 The in Keyword and Lists


The in keyword is a simple yet powerful tool in Python that can be used to check if a certain
value exists in a list or not. This keyword is often used in conjunction with conditionals to
allow for decision-making based on the presence or absence of a value within a list.

5.2.9.1 Basic Usage

.
m
fruits = ['apple', 'banana', 'cherry']

ru
# Check if 'apple' is in the list
if 'apple' in fruits:

Fo
print('Apple is in the list!')

In this example, Python checks to see if the string 'apple' is an element in the fruits list. If it
ST
is, then it will print 'Apple is in the list!'.

5.2.9.2 The not in Keyword


R

Similarly, Python also provides the not in keyword which checks if a certain value does not
exist in the list.
ht

fruits = ['apple', 'banana', 'cherry']


# Check if 'date' is not in the list
ig

if 'date' not in fruits:


print('Date is not in the list!')
yr

In this example, Python checks to see if the string 'date' is not an element in the fruits list. If it
op

is not, then it will print 'Date is not in the list!'.

5.2.9.3 The in Keyword with a Loop


C

The in keyword is also commonly used with loops to iterate over the elements of a list.

fruits = ['apple', 'banana', 'cherry']

# Print each fruit


for fruit in fruits:
print(fruit)

In this example, fruit is a variable that will take on each value in the fruits list, one at a time,

© Copyright RSTForum. Sharing of this material is illegal.


68
and the print(fruit) statement will be executed for each value.

Summary
The in keyword, along with its counterpart not in, are simple but versatile tools for checking
the presence or absence of values in a list. When used with loops and conditionals, these
keywords can form the basis for more complex logical structures and algorithms. Experiment
with these keywords and lists to gain more confidence in using them.

5.2.10 List Slicing


List slicing is a feature that allows us to access elements from the list in a concise manner. In
simple words, slicing is a way to extract a range of values from a list. It is a common

.
operation for lists and other sequence data types like strings and tuples.

m
5.2.10.1 Basic Slicing

ru
The syntax for slicing is list[start:stop], where start is the index at which the slice
starts, and stop is the index at which the slice ends. The element at the start index is

Fo
included, but the element at the stop index is not included in the slice.

numbers = [0, 1, 2, 3, 4, 5]
ST
# Slice from index 1 to 4
print(numbers[1:4]) # Output: [1, 2, 3]
R

5.2.10.2 Omitting Indices


ht

You can omit either the start index, or the stop index, or both in the slicing syntax.
ig

numbers = [0, 1, 2, 3, 4, 5]
yr

# Slice from start to index 3


print(numbers[:3]) # Output: [0, 1, 2]
op

# Slice from index 3 to end


print(numbers[3:]) # Output: [3, 4, 5]
C

# Slice the entire list


print(numbers[:]) # Output: [0, 1, 2, 3, 4, 5]

5.2.10.3 Negative Indices


Negative indices can be used in slicing, where -1 refers to the last element, -2 refers to the
second last element, and so on.

numbers = [0, 1, 2, 3, 4, 5]

© Copyright RSTForum. Sharing of this material is illegal.


69
# Slice from third last to the last element
print(numbers[-3:-1]) # Output: [3, 4]

5.2.10.4 Step Parameter


You can add a third parameter as a step which skips elements. The syntax is
list[start:stop:step].

numbers = [0, 1, 2, 3, 4, 5]

.
# Slice every second element

m
print(numbers[::2]) # Output: [0, 2, 4]

ru
# Slice in reverse
print(numbers[::-1]) # Output: [5, 4, 3, 2, 1, 0]

Fo
5.2.10.5 Slicing and Modifying Lists
Slicing can be used on the left side of an assignment operation to modify multiple list
ST
elements at once.

numbers = [0, 1, 2, 3, 4, 5]
R

# Replace the second and third elements


numbers[1:3] = ['two', 'three']
ht

print(numbers) # Output: [0, 'two', 'three', 3, 4, 5]


ig

Summary
List slicing in Python offers a flexible and powerful way to access and manipulate list data.
It's a fundamental skill for working with sequence data types in Python and is well worth
yr

taking the time to practice and understand thoroughly.


op

5.2.11 Python List Swapping


List swapping in Python refers to swapping the position of two elements in a list. Python
provides a very convenient way to do this that might seem a bit magical if you're coming
C

from a language like C or Java.

Let's consider a simple list:

numbers = [1, 2, 3, 4, 5]

Now, let's say we want to swap the second and fourth elements. In Python, this can be done
in a single line:

© Copyright RSTForum. Sharing of this material is illegal.


70
numbers[1], numbers[3] = numbers[3], numbers[1]

After this line, the numbers list will be [1, 4, 3, 2, 5].

Here's how it works:

The right-hand side of the equation (numbers[3], numbers[1]) forms a tuple (a kind of
immutable list) containing the values of the elements at indices 3 and 1.

The left-hand side of the equation also forms a tuple, but this time it's a tuple of variables
rather than values. Python then assigns the values from the right-hand tuple to the variables

.
in the left-hand tuple. This is known as tuple packing and unpacking, a concept we will

m
explore in detail in the next chapter.

ru
Since the assignments are all done "at the same time", you can swap the values without
needing a temporary variable to hold one of the values during the swap, which you might
have needed in other languages.

Fo
This swapping mechanism can also be used to swap the values of any two variables, not
just elements in a list.
ST
a = 5
b = 10
R

a, b = b, a # After this line, a will be 10 and b will be 5

This makes Python's list swapping a handy tool to have in your Python toolkit.
ht
ig

5.2.12 Python List Comprehensions


List comprehensions are one of Python's most beloved and unique features. The idea of
yr

comprehension is borrowed from set builder notation in mathematics. It's a way to define and
create lists in Python in a very natural or easy way, like a mathematician is used to do.
op

In mathematics, the set builder notation is an example of comprehension. It's a way to


describe sets by defining the properties that its members must satisfy. The set of all x such
C

that x > 0 is written as: {x | x > 0}. The pipe symbol (|) translates to "such that".

Python’s list comprehensions provide a natural way to describe lists, sets, and other
sequences and structures. Not only they're more readable and concise, but they can also
perform better than using loops and map() function.

Let's start with a simple example of how to use a list comprehension. Suppose we want to
create a list of the squares of the numbers from 0 to 9. Here's how we can do it with a for
loop:

© Copyright RSTForum. Sharing of this material is illegal.


71
squares = []
for x in range(10):
squares.append(x**2)
print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

And here's how we can do the same thing with a list comprehension:

squares = [x**2 for x in range(10)]


print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

.
The list comprehension is shorter, easier to read, and does exactly the same thing. Here's

m
the general form of a list comprehension:

ru
[expression for item in iterable]

Fo
The expression is calculated for each item in the iterable. The results are collected into a
new list, which is the value of the list comprehension.
ST
List comprehensions can also incorporate conditionals. For example, here's a list
comprehension that creates a list of the squares of the numbers from 0 to 9, but only for the
even numbers:
R

squares = [x**2 for x in range(10) if x % 2 == 0]


print(squares) # Output: [0, 4, 16, 36, 64]
ht

Here's the general form of a list comprehension with a conditional:


ig

[expression for item in iterable if condition]


yr

The expression is only calculated for items where the condition is true.
op

List comprehensions can be a little tricky to understand at first, but they're incredibly useful
once you get the hang of them. They can make your code more readable and efficient,
especially when you're dealing with large lists.
C

You can use both if and else in a list comprehension. This allows us to produce more
complex lists in a very compact way. Here is the syntax for it:

[expression_if_true if condition else expression_if_false for item in


iterable]

Let's take an example. Suppose we have a list of numbers and we want to create a new list
where each element is a string "even" if the number is even, and "odd" if the number is odd.

© Copyright RSTForum. Sharing of this material is illegal.


72
Here's how you can do it with a list comprehension:

numbers = [1, 2, 3, 4, 5, 6]
parity = ["even" if number % 2 == 0 else "odd" for number in numbers]
print(parity) # Output: ['odd', 'even', 'odd', 'even', 'odd', 'even']

In this list comprehension, "even" if number % 2 == 0 else "odd" is the expression


that gets calculated for each number in numbers. If number % 2 == 0 (i.e., if the number is
even), then the expression is "even". Otherwise, it's "odd".

This list comprehension does the same thing as the following for loop:

.
m
numbers = [1, 2, 3, 4, 5, 6]

ru
parity = []
for number in numbers:
if number % 2 == 0:

Fo
parity.append("even")
else:
parity.append("odd")
ST
print(parity) # Output: ['odd', 'even', 'odd', 'even', 'odd', 'even']

The list comprehension is much shorter and arguably easier to understand, once you're
familiar with the syntax.
R

Here are a few more examples of what you can do with list comprehensions:
ht

1. Creating a list of greetings for a list of names:


ig

names = ['Alice', 'Bob', 'Charlie']


greetings = [f"Hello, {name}!" for name in names]
yr

print(greetings) # Output: ['Hello, Alice!', 'Hello, Bob!', 'Hello,


Charlie!']
op

2. Calculating the price after tax for a list of prices:


C

prices = [1.5, 2.3, 4.5, 6.7]


prices_after_tax = [price * 1.1 for price in prices]
print(prices_after_tax) # Output: [1.65, 2.53, 4.95, 7.37]

3. Getting a list of all the vowels in a string:

s = "Hello, world!"
vowels = [c for c in s if c in 'aeiou']

© Copyright RSTForum. Sharing of this material is illegal.


73
print(vowels) # Output: ['e', 'o', 'o']

4. Getting a list of all the words in a string that have 5 letters or more:

s = "Hello, world! Python is awesome!"


words = [word for word in s.split() if len(word) >= 5]
print(words) # Output: ['Hello,', 'world!', 'Python', 'awesome!']

5. Creating a list of lists (a matrix):

.
m
matrix = [[i*j for i in range(5)] for j in range(5)]
print(matrix)

ru
Output:

Fo
[[0, 0, 0, 0, 0],
[0, 1, 2, 3, 4],
[0, 2, 4, 6, 8],
ST
[0, 3, 6, 9, 12],
[0, 4, 8, 12, 16]]
R

In conclusion, list comprehensions are a powerful tool that make it easy to create new lists
by processing existing lists (and other iterables). They're a big part of what makes Python
such a joy to write and read.
ht

5.2.13 Nested Lists


ig

In Python, a list can contain elements of any type, including other lists. A list within another
list is called a nested list or a multidimensional list. It's a powerful concept in Python, allowing
yr

you to model complex structures.


op

nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]


print(nested_list)
C

Output

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

The above example is a 2-dimensional list (a list of lists) that looks a bit like a table with 3
rows and 3 columns. You could imagine this representing a game board, a grid of graphical
pixels, a spreadsheet, or any number of other 2D structures.

© Copyright RSTForum. Sharing of this material is illegal.


74
5.2.13.1 Accessing Elements
Elements in a nested list are accessed using multiple indices, one for each level of nesting.

For example, to access the number 6 in nested_list above, you'd use:

print(nested_list[1][2]) # Output: 6

Here, nested_list[1] accesses the second sublist (remember, list indices start from 0),
then the [2] accesses the third element of that sublist.

.
5.2.13.2 Modifying Elements

m
Just like with regular lists, you can modify elements of a nested list:

ru
nested_list[1][2] = 600
print(nested_list) # Output: [[1, 2, 3], [4, 5, 600], [7, 8, 9]]

Fo
5.2.13.3 Looping Over Nested Lists
Looping over a nested list typically involves a nested loop. Here's an example of printing all
ST
elements of a 2D list:

for sublist in nested_list:


R

for item in sublist:


print(item, end=' ')
print() # print newline at the end of each sublist
ht

This will print:


ig

1 2 3
yr

4 5 600
7 8 9
op

Nested List Comprehensions


Just like with regular lists, you can use list comprehensions with nested lists. For example,
C

let's create a 3x3 list of zeros:

zeros = [[0 for _ in range(3)] for _ in range(3)]


print(zeros) # Output: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

In this example, range(3) is used twice, to create three-element sublists and to make three
of these sublists. The variable _ is a convention for when you don't care about the exact
values being iterated over.

© Copyright RSTForum. Sharing of this material is illegal.


75
Nested lists provide a way to work with multi-dimensional data in Python. They're used
frequently in areas like data science, machine learning, game development, and more. They
can be as simple or complex as you need them to be, which is a testament to the versatility
of Python's list data structure.

5.3 Python Dictionaries


Dictionaries are an essential part of Python programming, used extensively for data
manipulation, storage, and operations.

.
5.3.1 Dictionary Creation

m
Dictionaries in Python are a collection of key-value pairs, where each key-value pair maps
the key to its associated value. The keys in a dictionary must be unique (within one

ru
dictionary) but the values may not. Keys and values can be of any type, although keys are
typically numbers or strings.

Fo
To create a dictionary, you use curly braces {} containing key-value pairs separated by
commas ,. Each key-value pair is written as key: value.
ST
person = {"name": "John", "age": 30, "country": "USA"}
print(person) # Output: {'name': 'John', 'age': 30, 'country': 'USA'}
R

In this example, name, age, and country are keys, and John, 30, and USA are their
corresponding values.
ht

5.3.2 Accessing Dictionary Values


ig

You can access the value for a particular key by using square brackets [] containing the
key.
yr

print(person["name"]) # Output: John


op

If the key does not exist in the dictionary, Python raises a KeyError. To avoid this, you can
use the dictionary's get() method, which returns None if the key doesn't exist.
C

print(person.get("address")) # Output: None

You can also specify a default value to return if the key doesn't exist:

print(person.get("address", "Unknown")) # Output: Unknown

© Copyright RSTForum. Sharing of this material is illegal.


76
5.3.3 Modifying and Adding Dictionary Key-Value Pairs
To modify a value, use the square brackets [] with the key and assign the new value.

person["age"] = 31
print(person) # Output: {'name': 'John', 'age': 31, 'country': 'INDIA'}

Adding a new key-value pair is done the same way:

person["address"] = "123 Main St"


print(person) # Output: {'name': 'John', 'age': 31, 'country': 'INDIA',

.
'address': '123 M.G. Road'}

m
5.3.4 Deleting Key-Value Pairs

ru
To delete a key-value pair, use the del keyword with the key.

Fo
del person["address"]
print(person) # Output: {'name': 'John', 'age': 31, 'country': 'INDIA'}
ST
Be cautious when deleting key-value pairs, as Python will raise a KeyError if the key doesn't
exist. To avoid this, you can use the dictionary's pop() method, which removes the
key-value pair and returns the value. If the key doesn't exist, it returns a default value (if
R

specified) or None.
ht

address = person.pop("address", "Unknown")


print(address) # Output: Unknown
ig

5.3.5 Checking If a Key Exists


yr

You can check if a key exists in a dictionary using the in keyword.


op

if "age" in person:
print("Key exists")
else:
C

print("Key does not exist")

5.3.6 Looping Through a Dictionary


Dictionaries can be looped over using a for loop. By default, the loop variable refers to the
dictionary's keys.

for key in person:


print(key) # prints all keys

© Copyright RSTForum. Sharing of this material is illegal.


77
To loop through the values, you can use the dictionary's values() method:

for value in person.values():


print(value) # prints all values

To loop through both keys and values, you can use the dictionary's items() method:

for key, value in person.items():


print(key, value) # prints all keys and values

.
m
5.3.7 Dictionary Methods
Just like lists, dictionaries also come with built-in methods to make it easier to work with

ru
them. Below are some of the dictionary methods:

Fo
5.3.7.1 clear()
This method removes all items from the dictionary.
ST
person.clear()
print(person) # Output: {}
R

5.3.7.2 copy()
This method returns a copy of the dictionary.
ht

person_copy = person.copy()
ig

print(person_copy) # Output: {'name': 'John', 'age': 31, 'country':


'INDIA'}
yr

5.3.7.3 fromkeys(keys, value)


op

This static method returns a new dictionary with keys from the given iterable and all values
set to the provided value (defaults to None).
C

keys = ["name", "age", "country"]


default_value = "Unknown"
new_person = dict.fromkeys(keys, default_value)
print(new_person) # Output: {'name': 'Unknown', 'age': 'Unknown',
'country': 'Unknown'}

5.3.7.4 keys()
This method returns a view object containing the dictionary's keys.

© Copyright RSTForum. Sharing of this material is illegal.


78
keys = person.keys()
print(keys) # Output: dict_keys(['name', 'age', 'country'])

5.3.7.5 values()
This method returns a view object containing the dictionary's values.

values = person.values()
print(values) # Output: dict_values(['John', 31, 'INDIA'])

5.3.7.6 items()

.
m
This method returns a view object containing a tuple for each key-value pair.

ru
items = person.items()
print(items) # Output: dict_items([('name', 'John'), ('age', 31),
('country', 'USA')])

5.3.7.7 popitem()

Fo
ST
This method removes and returns the last inserted key-value pair as a tuple. If the dictionary
is empty, it raises a KeyError.

item = person.popitem()
R

print(item) # Output: ('country', 'USA')


print(person) # Output: {'name': 'John', 'age': 31}
ht

5.3.7.8 update([other])
ig

This method updates the dictionary with the key-value pairs from another dictionary or from
an iterable of key-value pairs. It overwrites the existing keys.
yr

person.update({"age": 32, "address": "123 Main St"})


op

print(person) # Output: {'name': 'John', 'age': 32, 'address': '123


Main St'}
C

There are several other dictionary methods available that you can explore.

5.3.8 Dictionary Comprehension


Just like lists, you can also use comprehensions to create dictionaries in a more readable
and concise way. Dictionary comprehensions are also a bit faster than using a for loop.
# Create a new dictionary with only pairs where the value is not "John"
person = {"name": "John", "age": 30, "country": "USA"}
new_dict = {k: v for k, v in person.items() if v != "John"}
print(new_dict) # Output: {'age': 30, 'country': 'USA'}

© Copyright RSTForum. Sharing of this material is illegal.


79
In this example, {k: v for k, v in person.items() if v != "John"} is a dictionary
comprehension. It goes through each item in the person dictionary, and if the value is not
"John", it includes it in the new dictionary. So, the key-value pairs 'age': 30 and
'country': 'USA' are included in the new dictionary, while 'name': 'John' is not.

Ex. 1: Create a dictionary with square values


A common use case for a dictionary comprehension is to generate a dictionary where the
keys are a series of numbers and the values are some function applied to those numbers.

For example, you could create a dictionary where the keys are numbers from 1 to 10, and
the values are the square of these numbers:

.
m
squares = {i: i ** 2 for i in range(1, 11)}

ru
print(squares) # Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49,
8: 64, 9: 81, 10: 100}

Fo
Ex. 2: Create a dictionary with selective keys
Suppose you have a list of words and you want to create a dictionary that stores the lengths
of the words, but only for words that are more than 3 letters long. You could accomplish this
ST
with a dictionary comprehension:

words = ["apple", "bear", "candy", "dog", "elephant", "fish", "goose",


R

"happiness", "island", "juice", "kangaroo", "lollipop", "monkey",


"notebook", "orange", "python", "queen", "rabbit", "snake", "tangerine",
"umbrella", "violin", "whale", "xylophone", "yak", "zebra"]
ht

lengths = {word: len(word) for word in words if len(word) > 3}


ig

print(lengths) # Output: {'apple': 5, 'bear': 4, 'candy': 5,


'elephant': 8, 'fish': 4, 'goose': 5, 'happiness': 10, 'island': 6,
yr

'juice': 5, 'kangaroo': 8, 'lollipop': 8, 'monkey': 6, 'notebook': 8,


'orange': 6, 'python': 6, 'queen': 5, 'rabbit': 6, 'snake': 5,
'tangerine': 9, 'umbrella': 8, 'violin': 6, 'whale': 5, 'xylophone': 9,
op

'zebra': 5}
C

In this case, the dictionary comprehension works by iterating over each word in the words
list. If the length of the word is more than 3, a new key-value pair is added to the dictionary,
with the key being the word itself and the value being the length of the word.

In this section, we've explored the core concepts and functionalities of dictionaries in Python.
We started with the basics of creating and accessing dictionary elements, followed by a
detailed look at various dictionary methods that allow us to add, remove, and manipulate
items. We've learned how to iterate over a dictionary, use conditional checks in our
dictionary operations, and leverage the flexibility of dictionaries in handling data.

We also delved into the world of dictionary comprehensions, a powerful Python feature that

© Copyright RSTForum. Sharing of this material is illegal.


80
helps us create and manipulate dictionaries in a concise and Pythonic way. By comparing it
to traditional loops, we've highlighted its efficiency and simplicity.

But remember, like any other tool, dictionaries and their methods should be used judiciously.
Always consider the nature of your problem and the structure of your data to decide if a
dictionary is the best tool for the job.

With the knowledge we've gained here, we're now equipped to deal with many real-world
tasks involving structured data. Dictionaries, with their key-value pairs, often closely
resemble the data models we see in databases and APIs, so understanding them is a
significant step forward on your Python journey.

.
m
As we move forward, we'll now shift our focus to another fundamental data structure in
Python, the Tuple. Tuples, while similar to lists, come with their own unique set of properties
and uses. Let's continue our learning journey!

ru
Fo
5.4 Python Tuples

5.4.1 Introduction
ST
A Tuple in Python is similar to a list in that it is a sequence of elements. However, the key
difference is that while lists are mutable, tuples are immutable. This means that once a tuple
is created, it cannot be modified - you can't add, modify, or delete elements from a tuple.
R

This immutability makes tuples useful in situations where you need a constant set of values
and assurance that they will not change.
ht

Tuples are defined in Python by enclosing a comma-separated sequence of elements within


parentheses (). For instance:
ig

fruits = ('apple', 'banana', 'cherry')


yr

print(fruits)
op

This will output: ('apple', 'banana', 'cherry')

5.4.2 Accessing Elements


C

Like lists, tuples are also sequences, so you can access individual elements in a tuple using
indexing. Let's see an example:

fruits = ('apple', 'banana', 'cherry')


print(fruits[1])

This will output: 'banana'

Negative indexing works in the same way as it does with lists. If you want to access the last

© Copyright RSTForum. Sharing of this material is illegal.


81
element of a tuple, you can use -1 as the index:

fruits = ('apple', 'banana', 'cherry')


print(fruits[-1])

This will output: 'cherry'

5.4.3 Tuple Unpacking


Tuple unpacking allows us to assign the values from a tuple directly into variables. Here's an
example:

.
m
fruits = ('apple', 'banana', 'cherry')
fruit1, fruit2, fruit3 = fruits

ru
print(fruit1)
print(fruit2)

Fo
print(fruit3)

This will output:


ST
apple
banana
cherry
R

5.4.4 Looping Over a Tuple


ht

We can use a for loop to iterate over the elements in a tuple. Here's an example:
ig

fruits = ('apple', 'banana', 'cherry')


for fruit in fruits:
yr

print(fruit)
op

This will output:


C

apple
banana
cherry

This is the first part of our exploration into Python tuples. We'll be diving deeper into more
advanced aspects of tuples such as tuple methods and tuple comprehension in the next
section.

5.4.5 Tuple Methods


Even though tuples are immutable, they still have a couple of methods that allow us to work

© Copyright RSTForum. Sharing of this material is illegal.


82
with them. The methods provided by tuples are:

● count(): This method returns the number of times a specific value appears in the
tuple.
● index(): This method returns the index of the first occurrence of a specified value.

Here are examples of how to use these methods:

fruits = ('apple', 'banana', 'cherry', 'apple')


print(fruits.count('apple')) # Output: 2
print(fruits.index('cherry')) # Output: 2

.
m
In this example, fruits.count('apple') returns 2 because 'apple' appears twice in the
tuple. fruits.index('cherry') returns 2 because the first occurrence of 'cherry' is at

ru
index 2.

Fo
5.4.6 Immutability of Tuples
Let's talk a bit more about the immutability of tuples. Since tuples are immutable, you might
think that they can't be modified at all. While it's true that you can't add or remove elements
ST
from a tuple, or change the existing elements, you can still modify the mutable objects
contained within the tuple.

Consider this example:


R

tuple1 = (1, 2, ['apple', 'banana'])


ht

print(tuple1) # Output: (1, 2, ['apple', 'banana'])


ig

tuple1[2][1] = 'cherry'
print(tuple1) # Output: (1, 2, ['apple', 'cherry'])
yr

In this example, even though the tuple itself is immutable, the list within the tuple is mutable
and can be modified.
op

5.4.7 Tuples vs Lists


C

So why might you choose to use a tuple instead of a list, given that lists have more features
and are more flexible?

Tuples are often used in situations where a statement or a user-defined function can safely
assume that the sequence of values will not change. For instance, the months of a year, or
the colors of a rainbow.

Tuples have the advantage of being more memory efficient than lists because they have
fewer built-in methods and their immutability allows Python to optimize resources devoted to
them.

© Copyright RSTForum. Sharing of this material is illegal.


83
This is the second part of our exploration into Python tuples. In the next part, we'll be diving
into more advanced aspects of tuples such as tuple comprehension.

5.4.8 Tuple Packing and Unpacking


Tuple packing allows us to assign multiple values to a tuple in a single statement, which is
the normal way of creating a tuple. Tuple unpacking, on the other hand, allows us to assign
the values from a tuple into a sequence of variables in a single statement.

Here's an example:

# Tuple Packing

.
m
fruit_tuple = ("apple", "banana", "cherry")

# Tuple Unpacking

ru
fruit1, fruit2, fruit3 = fruit_tuple

Fo
print(fruit1) # Output: apple
print(fruit2) # Output: banana
print(fruit3) # Output: cherry
ST
In this example, we first pack three strings into fruit_tuple. Then we unpack the values from
fruit_tuple into fruit1, fruit2, and fruit3.
R

Tuple unpacking can be useful in a variety of scenarios. For instance, we can use it to swap
the values of two variables:
ht

a = 5
ig

b = 10

# Without using a temporary variable


yr

a, b = b, a
op

print(a) # Output: 10
print(b) # Output: 5
C

In this example, we are using a tuple to swap the values of a and b without needing a
temporary variable.

5.4.9 Tuple Comprehension


Unlike lists and dictionaries, tuples do not support comprehension. If you try to create a tuple
comprehension, you will end up creating a generator instead due to the use of parentheses
().

Here's what happens when you try to create a tuple comprehension:

© Copyright RSTForum. Sharing of this material is illegal.


84
numbers = (n for n in range(5))
print(numbers) # Output: <generator object <genexpr> at 0x7f05c01e9550>
print(tuple(numbers)) # Output: (0, 1, 2, 3, 4)

In this example, numbers is not a tuple, but a generator object. You can convert this
generator into a tuple using the tuple() function.

And that wraps up our discussion on tuples in Python! We covered the creation and
manipulation of tuples, various tuple methods, the immutability of tuples, tuple packing and
unpacking, and the lack of tuple comprehension. Tuples are a fundamental data structure in
Python, and knowing how to work with them will serve you well as you continue your Python

.
journey.

m
Next, we will be exploring sets, another type of built-in data structure in Python.

ru
Fo
5.5 Python Sets

5.5.1 Introduction
ST
A set is an unordered collection of unique elements in Python. It is used to store multiple
items in a single variable. Sets are similar to lists and tuples, but unlike those data types,
sets do not maintain any specific order of the elements. Additionally, sets only contain
R

unique elements, meaning there are no duplicates allowed.

In Python, sets are defined by enclosing comma-separated elements within curly braces {}.
ht

For example:
ig

fruits = {'apple', 'banana', 'cherry'}


print(fruits)
yr

Output: {'apple', 'banana', 'cherry'}


op

5.5.2 Accessing Elements


Since sets are unordered, there is no indexing or slicing available to access individual
C

elements. Instead, we typically use sets for membership testing or performing set
operations.

5.5.3 Set Operations


Sets support a variety of operations, including union, intersection, difference, and symmetric
difference.

5.5.3.1 Union
The union of two sets contains all the unique elements from both sets. In Python, we can

© Copyright RSTForum. Sharing of this material is illegal.


85
use the union() method or the | operator to perform the union operation.

set1 = {1, 2, 3}
set2 = {2, 3, 4}
union_set = set1.union(set2)
print(union_set) # Output: {1, 2, 3, 4}

# Using the | operator


union_set = set1 | set2
print(union_set) # Output: {1, 2, 3, 4}

.
5.5.3.2 Intersection

m
The intersection of two sets contains the common elements present in both sets. We can
use the intersection() method or the & operator to perform the intersection operation.

ru
set1 = {1, 2, 3}

Fo
set2 = {2, 3, 4}
intersection_set = set1.intersection(set2)
print(intersection_set) # Output: {2, 3}
ST
# Using the & operator
intersection_set = set1 & set2
R

print(intersection_set) # Output: {2, 3}

5.5.3.3 Difference
ht

The difference between two sets contains the elements present in the first set but not in the
second set. We can use the difference() method or the - operator to perform the
ig

difference operation.
yr

set1 = {1, 2, 3}
set2 = {2, 3, 4}
op

difference_set = set1.difference(set2)
print(difference_set) # Output: {1}
C

# Using the - operator


difference_set = set1 - set2
print(difference_set) # Output: {1}

5.5.3.4 Symmetric Difference


The symmetric difference of two sets contains the elements present in either set, but not
both. We can use the symmetric_difference() method or the ^ operator to perform the
symmetric difference operation.

© Copyright RSTForum. Sharing of this material is illegal.


86
set1 = {1, 2, 3}
set2 = {2, 3, 4}
symmetric_difference_set = set1.symmetric_difference(set2)
print(symmetric_difference_set) # Output: {1, 4}

# Using the ^ operator


symmetric_difference_set = set1 ^ set2
print(symmetric_difference_set) # Output: {1, 4}

5.5.4 Set Methods

.
Sets have several built-in methods that allow us to perform various operations on sets. Here

m
are some of the commonly used set methods:

ru
5.5.4.1 add()
The add() method adds an element to the set. If the element is already present, it does not

Fo
add it again.

fruits = {'apple', 'banana'}


ST
fruits.add('cherry')
print(fruits) # Output: {'apple', 'banana', 'cherry'}

5.5.4.2 remove()
R

The remove() method removes a specific element from the set. If the element is not found,
it raises a KeyError.
ht

fruits = {'apple', 'banana', 'cherry'}


ig

fruits.remove('banana')
print(fruits) # Output: {'apple', 'cherry'}
yr

5.5.4.3 discard()
op

The discard() method removes a specific element from the set. If the element is not found,
it does not raise any error.
C

fruits = {'apple', 'banana', 'cherry'}


fruits.discard('banana')
print(fruits) # Output: {'apple', 'cherry'}

5.5.4.4 pop()
The pop() method removes an arbitrary element from the set and returns it. Since sets are
unordered, there is no defined order in which elements are popped.

© Copyright RSTForum. Sharing of this material is illegal.


87
fruits = {'apple', 'banana', 'cherry'}
removed_fruit = fruits.pop()
print(removed_fruit) # Output: 'apple'
print(fruits) # Output: {'banana', 'cherry'}

5.5.4.5 clear()
The clear() method removes all elements from the set, making it an empty set.

fruits = {'apple', 'banana', 'cherry'}


fruits.clear()

.
print(fruits) # Output: set()

m
These are just a few examples of the methods available for working with sets. You can

ru
explore more set methods in the Python documentation.

Fo
5.5.5 Set Comprehension
Similar to list comprehensions, Python also provides set comprehensions to create sets in a
ST
concise way. Set comprehensions use curly braces {} instead of square brackets []. Let's
see an example:
R

squares = {x ** 2 for x in range(5)}


print(squares) # Output: {0, 1, 4, 9, 16}
ht

In this example, we use a set comprehension to create a set of squares of numbers from 0
to 4.
ig

Set comprehensions are a powerful tool for creating sets based on iterable objects, with the
yr

added benefit of eliminating duplicate elements.

This concludes our detailed exploration of Python sets. Sets are versatile data structures
op

that offer unique features such as uniqueness and set operations. By understanding sets
and their methods, you can efficiently work with collections of unique elements in your
Python programs.
C

5.6 More Examples


Below are a few complex examples of real-world programs using lists, dictionaries, tuples,
and sets.

1. Count the frequency of words in a text

text = "It was the best of times, it was the worst of times"

© Copyright RSTForum. Sharing of this material is illegal.


88
# convert to lowercase and replace punctuation
text = text.lower().replace(",", "").replace(".", "")
# create list of words
words = text.split()

frequency = {}

for word in words:


if word not in frequency:
frequency[word] = 0
frequency[word] += 1

.
m
print(frequency)

ru
In this example, we first convert the given text into lowercase and replace the punctuation
with nothing. Then, we split the text by whitespace to get a list of words. After that, we count

Fo
the frequency of each word in the list using a dictionary.

2. Track students and their chosen courses


ST
students = {
'Alice': ['Math', 'Science'],
'Bob': ['English', 'History'],
R

'Charlie': ['Math', 'English', 'History'],


}
ht

new_course = 'Art'
ig

# Add 'Art' course to every student's course list


for student, courses in students.items():
yr

courses.append(new_course)
op

print(students)

In this example, we start with a dictionary that has student names as keys and a list of their
C

courses as values. We then iterate over the dictionary, adding a new course to each
student's list of courses.

3. Find common elements in two lists using a set

list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list2 = [5, 10, 15, 2, 20, 25]

# Convert lists to sets


set1 = set(list1)

© Copyright RSTForum. Sharing of this material is illegal.


89
set2 = set(list2)

# Find common elements


common_elements = set1 & set2

print(list(common_elements))

In this example, we start with two lists of numbers. We convert each list to a set, which
automatically removes any duplicates. Then, we find the intersection of the two sets (i.e., the
common elements) using the & operator. Finally, we convert the resulting set back to a list for
printing.

.
m
4. Calculating Average Grades

ru
grades = {
'Alice': [85, 90, 92],

Fo
'Bob': [78, 88, 91],
'Charlie': [80, 85, 88],
'David': [92, 95, 98]
ST
}

for student, grades_list in grades.items():


average_grade = sum(grades_list) / len(grades_list)
R

print(f"{student}'s average grade is {average_grade}")


ht

In this program, we have a dictionary with student names as keys and a list of their grades
as values. We calculate the average grade for each student by summing the grades and
dividing by the number of grades.
ig

5. Creating a Grocery Shopping List


yr

shopping_list = [("Apple", 2), ("Banana", 6), ("Carrot", 0.5),


op

("Donuts", 12)]
grocery_bag = {}
C

for item, quantity in shopping_list:


grocery_bag[item] = quantity

print(grocery_bag)

This script takes a list of tuples where each tuple represents an item and its quantity. It then
transforms this list into a dictionary for easier access to each item and its quantity.

6. Frequency of Characters in a String

© Copyright RSTForum. Sharing of this material is illegal.


90
text = "The quick brown fox jumps over the lazy dog"
character_frequency = {}

for char in text:


if char not in character_frequency:
character_frequency[char] = 0
character_frequency[char] += 1

print(character_frequency)

In this example, we count the frequency of each character in the text string. We use a

.
dictionary to track the counts, with each character as a key and its count as the

m
corresponding value.

ru
Fo
ST
R
ht
ig
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


91
Chapter 6: Python Functions

6.1 The Concept of Functions in Programming

In programming, functions serve as the building blocks of code. The concept of a function is
borrowed from mathematics, where a function maps input to output according to some rule.
Similarly, in programming, a function is a named sequence of statements that performs a
desired operation. This operation is specified in a function definition.

The idea of using functions or subroutines in computing dates back to the earliest

.
m
programming languages in the 1950s and 60s. The advent of procedural programming
further emphasized the use of functions, as they allowed for code reuse and abstraction,
making complex software systems more manageable and modular.

ru
Functions were created to improve the modularity of program code and to minimize

Fo
repetition. Through functions, we can write reusable pieces of code. These are
self-contained and can be plugged into different programs, making the code cleaner, more
efficient, and easier to understand.
ST
6.2 Python Functions and Their Syntax
R

In Python, functions are defined using the def keyword followed by the function name and
parentheses (). The code block within every function is indented, which starts with a colon
(:) and is followed by the function's body. Here's the general syntax:
ht

def function_name(parameters):
ig

"""docstring"""
# statements
yr

return expression
op

● def: This keyword signifies the start of the function header.


● function_name: This signifies the function's name, which is unique within its scope.
The naming follows the same rules and conventions as variables.
C

● parameters (or arguments): These are optional and are input to the function. They
are specified within the parentheses.
● :: This is used to mark the end of the function header.
● docstring: Short for documentation string, it's optional and is used to describe what
the function does.
● statements: The function body where operations are performed.
● return: This is optional. A function may or may not return a value.

Let's look at a simple Python function:

© Copyright RSTForum. Sharing of this material is illegal.


92
def greet(name):
"""This function greets the person passed in as a parameter"""
print(f"Hello, {name}!")

# Calling the function


greet("Alice") # Output: Hello, Alice!

Here, greet is the function name, name is the parameter, and the statement within the
function greets the person.

6.3 Function Parameters and Arguments

.
m
Parameters are the values that a function expects to receive when it is called, defined in the
function header. When you call a function, the values you pass in are known as arguments.

ru
In Python, there are several types of parameters:

Fo
● Positional Parameters: These are read in order from left to right.
● Keyword Parameters: These allow you to specify the parameter's value by name.
● Default Parameters: If no argument is given during the function call, these
ST
parameters use a default value.

# Example of different parameters


R

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


"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
ht

print(f"My {animal_type}'s name is {pet_name}.")


ig

describe_pet('hamster', 'Harry') # positional arguments


describe_pet(pet_name='Willie', animal_type='dog') # keyword arguments
yr

describe_pet('cat') # default argument


op

6.4 Parameters vs Arguments in Python Functions


While discussing Python functions, two terms frequently come up: parameters and
C

arguments. Though they are sometimes used interchangeably, they do not mean exactly the
same thing.

6.4.1 Parameters
Parameters are the names used when defining a function. They are placed inside the
parentheses of the function definition and represent the inputs that the function will accept
when it is called. For example:

def add_numbers(a, b):

© Copyright RSTForum. Sharing of this material is illegal.


93
"""This function adds two numbers"""
return a + b

Here, a and b are parameters of the function add_numbers. They serve as placeholders for
actual values that will be used when the function is called.

6.5.2 Arguments
Arguments, on the other hand, are the actual values that are passed to a function when it is
called. Each argument corresponds to a parameter in the function definition. For example:

.
result = add_numbers(5, 3)

m
Here, 5 and 3 are arguments that are being passed to the function add_numbers.

ru
In short, parameters are the variables in a function definition, and arguments are the values

Fo
put into those variables when the function is called.

6.5 The Return Keyword and Return Values


ST
The return keyword is used in a function to send the result back to the caller. When a
function completes its task, it can return the result to the point where the function was called.
If a function doesn't include a return statement, it returns None by default. Here's the general
R

syntax:
ht

def function_name(parameters):
# code block
return result
ig
yr

6.5.1 Simple Return Values


op

In the most basic form, a function can return a simple value. Let's consider a function that
returns the square of a number:
C

def square(n):
"""Returns the square of a number"""
return n**2

print(square(5)) # Output: 25

In the function above, the return statement returns the square of the number n. When we
call square(5), the output is 25.

© Copyright RSTForum. Sharing of this material is illegal.


94
6.5.2 Multiple Return Values

Python functions can return multiple values. This is typically done by packing the values to
be returned into a tuple, which is then unpacked by the calling code. Here is an example:

def get_info():
"""Return a tuple of information"""
name = "Alice"
age = 25
city = "New York"
return name, age, city

.
m
info = get_info()
print(info) # Output: ('Alice', 25, 'New York')

ru
This function returns three values, which are packaged into a tuple. We can also use tuple

Fo
unpacking to assign these values to separate variables:

name, age, city = get_info()


ST
print(name) # Output: Alice
print(age) # Output: 25
print(city) # Output: New York
R

6.5.3 Return Statements and Program Flow


ht

The return statement, when executed, immediately exits the function, regardless of any
remaining statements in the function. Any code written after the return statement in a
ig

function will not be executed.


yr

For instance:
op

def return_test(n):
"""Returns a string and ignores the rest of the function"""
if n > 0:
C

return "n is greater than zero"


print("This line will not be printed")

print(return_test(5)) # Output: n is greater than zero

In this function, the print statement is never executed because the function execution is
stopped once it hits the return statement.

© Copyright RSTForum. Sharing of this material is illegal.


95
6.6 Python Function Scoping: Understanding Local, Non-local
and Global
Scoping refers to the visibility of variables in the code. In Python, the scope of variables is
determined by where they are defined and is governed by four main principles: Local,
Enclosing (Non-local), Global, and Built-in scope, together known as the LEGB rule.

● Local: Names defined in the current function. If a function is currently executing, a


local variable is created.
● Enclosing: Names in the local scope of any and all enclosing functions, from inner to
outer. If a variable is not found in the local scope (inside the function), the enclosing

.
functions (or non-local scope) will be checked, starting from the innermost function

m
and extending outwards.
● Global: Names assigned at the top-level of a module file, or declared global in a

ru
function in the file. If a variable is not found in the local and enclosing scopes, Python
will check the global scope, which includes any variable defined at the module level
or declared global with the global keyword inside a function.

Fo
● Built-in: Names preassigned in the built-in names module. These are the built-in
function names in Python (like abs(), sum(), print(), etc.). If Python cannot find
the variable in the local, enclosing, or global scopes, it will check the built-in scope.
ST
Python checks these scopes in the order LEGB whenever a variable is referenced.

6.6.1 Local Scope


R

A variable defined inside a function has a local scope. It is accessible from the point at which
it is defined until the end of the function, and exists for as long as the function is executing.
ht

The variable is not accessible outside the function.


ig

def local_example():
local_var = "I'm a local variable"
yr

print(local_var)

local_example() # Output: I'm a local variable


op

print(local_var) # Raises a NameError


C

In this example, local_var is defined within local_example and only accessible within the
function.

6.6.2 Non-local (Enclosing) Scope

Non-local (or enclosing) scope covers variables defined in an enclosing function. In other
words, if a function is nested within another function, it can access variables from the outer
(or enclosing) function.

© Copyright RSTForum. Sharing of this material is illegal.


96
def outer_func():
outer_var = "I'm from outer function"

def inner_func():
print(outer_var) # It has access to outer_var

inner_func()

outer_func() # Output: I'm from outer function

Here, inner_func can access outer_var from outer_func.

.
m
6.6.3 Global Scope

ru
A variable defined outside all function definitions is a global variable and has a global scope.
It is accessible from any point in the code.

Fo
global_var = "I'm a global variable"

def global_example():
ST
print(global_var) # It can access global_var

global_example() # Output: I'm a global variable


R

print(global_var) # Output: I'm a global variable

In this example, global_var is defined globally and is accessible both inside and outside of
ht

global_example.
ig

6.6.4 The global Keyword


If you need to modify a global variable from within a function, you can use the global
yr

keyword.
op

global_var = "I'm a global variable"

def modify_global():
C

global global_var
global_var = "I have been changed!"

modify_global()
print(global_var) # Output: I have been changed!

6.6.5 The nonlocal Keyword


Similar to global, nonlocal is used in nested function to indicate that a variable belongs to
an outer, but not global, function.

© Copyright RSTForum. Sharing of this material is illegal.


97
def outer():
outer_var = "I'm in outer function"

def inner():
nonlocal outer_var
outer_var = "I'm changed in inner function"

inner()
print(outer_var) # Output: I'm changed in inner function

.
outer()

m
By understanding Python's scope rules, you can avoid many common errors related to

ru
variable assignment and access. Remember the LEGB rule and you'll know where your
variables can and cannot be used.

Fo
6.7 Documenting Python Functions
ST
Properly documenting your code is an essential part of programming. For Python functions,
this is usually done through what's known as a docstring, a type of comment used to explain
the purpose of a function and how it should be used.
R

6.7.1 What is a Docstring?


ht

A docstring is a string literal that occurs as the first statement in a module, function, class, or
method definition. It becomes the __doc__ special attribute of that object. Docstrings are
written between triple quotes """ to span multiple lines. Here's an example:
ig

def add_numbers(a, b):


yr

"""This function adds two numbers and returns the result."""


return a + b
op

In the example above, the docstring is This function adds two numbers and returns
the result. It briefly explains what the function does.
C

6.7.2 Accessing Docstrings

There are two primary ways to access the docstrings of a Python function:

● The .__doc__ attribute: This attribute is used to retrieve the docstring from a
function.

© Copyright RSTForum. Sharing of this material is illegal.


98
print(add_numbers.__doc__) # Output: This function adds two numbers and
returns the result.

● The help() function: This function is used to display the docstring along with some
other helpful information such as function signature, module name, and more.

help(add_numbers)

The output will include the function's signature, its docstring, and where it was defined.

.
6.7.3 Writing Effective Docstrings

m
Docstrings should provide a clear, brief overview of what the function does. For larger, more
complicated functions, they might also explain the function's arguments, return values, and

ru
any exceptions that it might raise. The PEP 257
(https://www.python.org/dev/peps/pep-0257/) guide provides a good guide on how to write

Fo
effective docstrings.

Here's an example of a more comprehensive docstring:


ST
def add_numbers(a, b):
"""
Add two numbers and return the result.
R

Parameters:
ht

a (int or float): The first number to add


b (int or float): The second number to add
ig

Returns:
int or float: The sum of the two numbers
yr

"""
return a + b
op

This docstring not only explains what the function does but also describes its parameters,
their expected types, and the return value.
C

By writing effective docstrings, you can make your code much easier to understand and use,
both for others and for your future self.

6.8 *args, **kwargs and Parameter Ordering in Python


Functions

© Copyright RSTForum. Sharing of this material is illegal.


99
Understanding *args and **kwargs is crucial for writing flexible Python functions. These
special symbols are used in the function definition to allow the function to accept
variable-length arguments.

6.8.1 The *args Argument


The *args argument allows you to pass a non-keyworded, variable-length argument list to
your function. The function will receive the arguments as a tuple. Here's an example:

def sum_numbers(*args):
"""This function sums any number of input arguments."""

.
return sum(args)

m
print(sum_numbers(1, 2, 3, 4)) # Output: 10
print(sum_numbers(10, 20)) # Output: 30

ru
In this function, *args can accept any number of arguments, and the function will return their

Fo
sum.

6.8.2 The **kwargs Argument


ST
The **kwargs argument allows you to pass a keyworded, variable-length argument
dictionary to your function. The function will receive the arguments as a dictionary. Here's an
R

example:
ht

def print_student_info(**kwargs):
"""This function prints student information in key-value pairs."""
for key, value in kwargs.items():
ig

print(f"{key}: {value}")
yr

print_student_info(name="Alice", age=20, major="Computer Science")


op

In this example, the function accepts any number of keyword arguments and prints them out
in key-value pairs.
C

6.8.3 Using *args and **kwargs Together


You can use both *args and **kwargs in the same function to accept any number of
positional and keyword arguments:

def combined_example(*args, **kwargs):


"""This function sums the positional arguments and prints the
keyword arguments."""
print(f"The sum of positional arguments is {sum(args)}")
for key, value in kwargs.items():

© Copyright RSTForum. Sharing of this material is illegal.


100
print(f"{key}: {value}")

combined_example(1, 2, 3, name="Alice", age=20)

In this function, *args is used to sum the positional arguments, and **kwargs is used to print
the keyword arguments.

6.8.4 Parameter Ordering


When defining a function, parameters need to follow a specific order:

.
1. Standard positional parameters

m
2. *args
3. Keyword parameters

ru
4. **kwargs

Here's an example:

Fo
def ordered_arguments(a, b, *args, c=10, d=20, **kwargs):
print(a, b, args, c, d, kwargs)
ST
ordered_arguments(1, 2, 3, 4, 5, c=30, name="Alice", age=20)
R

In this example, 1 and 2 are assigned to the positional parameters a and b. 3, 4, and 5 are
grouped together into args. The keyword parameter c is given a new value of 30, d uses its
default value of 20, and the remaining keyword arguments are grouped together into
ht

kwargs.
ig

Understanding and using *args and **kwargs can make your functions more flexible and
reusable. They allow your functions to work with a variable number of arguments, making
yr

your code more Pythonic.

6.9 Argument Unpacking and Dictionary Unpacking in Python


op

Functions
C

Just as *args and **kwargs allow for variable numbers of arguments in function definitions,
the same operators can be used in function calls to unpack arguments from sequences and
dictionaries. This is known as argument unpacking.

6.9.1 Argument Unpacking with *


In Python, you can use the * operator to unpack a sequence (like a list or a tuple) into
positional arguments for a function call.

def add_three_numbers(a, b, c):

© Copyright RSTForum. Sharing of this material is illegal.


101
return a + b + c

numbers = [1, 2, 3]
print(add_three_numbers(*numbers)) # Output: 6

In the example above, the list numbers is unpacked into the three arguments for the
add_three_numbers function using the * operator.

6.9.2 Dictionary Unpacking with **


Similarly, the ** operator can be used to unpack a dictionary into keyword arguments for a

.
function call.

m
def print_student_info(name, age):

ru
print(f"Name: {name}, Age: {age}")

Fo
student_info = {"name": "Alice", "age": 20}
print_student_info(**student_info) # Output: Name: Alice, Age: 20
ST
In this example, the dictionary student_info is unpacked into the keyword arguments for
the print_student_info function using the ** operator.

6.9.3 Mixed Unpacking with * and **


R

Both * and ** can be used in a single function call to unpack both a sequence and a
dictionary.
ht

def student_info(name, age, major):


ig

print(f"Name: {name}, Age: {age}, Major: {major}")


yr

info_sequence = ["Alice", 20]


info_dict = {"major": "Computer Science"}
op

student_info(*info_sequence, **info_dict) # Output: Name: Alice, Age:


20, Major: Computer Science
C

In this example, info_sequence is unpacked into the positional arguments and info_dict
is unpacked into the keyword argument for the student_info function.

This feature of argument unpacking in Python makes your function calls flexible and clean,
especially when working with sequences and dictionaries of data.

© Copyright RSTForum. Sharing of this material is illegal.


102
6.10 Lambda Functions in Python
Lambda functions are one of Python's most powerful tools. They provide a way to create
small, anonymous functions, which are functions without a name. These are throw-away
functions, i.e., they are just needed where they have been created. Lambda functions are
syntactically restricted to a single expression.

6.10.1 Understanding Lambda Functions


A lambda function in Python is defined using the lambda keyword, followed by a list of
arguments, a colon, and then an expression. The lambda function can have any number of
arguments but only one expression, which is evaluated and returned.

.
m
Here is the syntax for a lambda function:

ru
lambda arguments: expression

Fo
Here's an example of a simple lambda function that adds two numbers:

add = lambda a, b: a + b
ST
print(add(5, 3)) # Output: 8

In this example, a and b are the arguments, and a + b is the expression. The function adds
R

the arguments and returns the result.

6.10.2 Why Use Lambda Functions?


ht

Lambda functions are used when you need a function for a short period of time. This is
commonly used when you want to pass a function as an argument to higher-order functions,
ig

that is, functions that take other functions as their arguments.


yr

Lambda functions make your code concise and can be extremely useful in a variety of
situations. However, they are limited in their complexity and shouldn't be used for more
op

complicated programming logic.

6.10.3 Lambda Functions with filter(), map(), and reduce()


C

Lambda functions are often used with built-in functions like filter(), map(), and reduce().

● filter(function, sequence): This function offers an elegant way to filter out all
the elements of a sequence. The function function needs to return a Boolean value.

numbers = [1, 2, 3, 4, 5, 6]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4, 6]

© Copyright RSTForum. Sharing of this material is illegal.


103
In this example, the lambda function filters out the even numbers from the list.

● map(function, sequence): This function applies the function to all the elements of
the sequence. It returns a new list with the elements changed by the function.

numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # Output: [1, 4, 9, 16, 25]

In this example, the lambda function squares each number in the list.

.
● reduce(function, sequence): This function continually applies the function to the

m
sequence and returns a single value. Note that reduce() is in the functools module.

ru
from functools import reduce

Fo
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # Output: 120
ST
In this example, the lambda function calculates the product of all numbers in the list.

Lambda functions are a powerful feature of Python that allow you to create quick, short-lived
R

functions for a variety of tasks. While they can be incredibly useful, it's important to
remember that they are limited in complexity and should be used sparingly to ensure your
ht

code remains readable and maintainable.

6.10.4 More Examples


ig
yr

1. Adding two numbers:


op

add = lambda a, b: a + b
print(add(5, 3)) # Output: 8
C

2. Multiplying two numbers:

multiply = lambda a, b: a * b
print(multiply(5, 3)) # Output: 15

3. Checking if a number is even:

is_even = lambda x: x % 2 == 0
print(is_even(4)) # Output: True

© Copyright RSTForum. Sharing of this material is illegal.


104
4. Finding the square of a number:

square = lambda x: x ** 2
print(square(4)) # Output: 16

5. Converting a string to uppercase:

to_uppercase = lambda s: s.upper()


print(to_uppercase("hello")) # Output: HELLO

.
m
6. Sorting a list of tuples by the second element:

ru
pairs = [(1, 'one'), (3, 'three'), (2, 'two')]
pairs.sort(key=lambda pair: pair[1])

Fo
print(pairs) # Output: [(1, 'one'), (3, 'three'), (2, 'two')]

7. Filtering out odd numbers from a list:


ST
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # Output: [2, 4, 6]
R

8. Finding the product of all numbers in a list:


ht

from functools import reduce


ig

numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
yr

print(product) # Output: 120


op

9. Finding the maximum of a list of numbers:

find_max = lambda x, y: x if x > y else y


C

numbers = [1, 2, 3, 4, 5]
max_number = reduce(find_max, numbers)
print(max_number) # Output: 5

10. Creating a dictionary of square numbers:

squares = {x: (lambda x: x**2)(x) for x in range(1, 6)}


print(squares) # Output: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

© Copyright RSTForum. Sharing of this material is illegal.


105
6.11 Built-in Functions in Python
Python comes with a set of built-in functions that are always available. These functions can
make your code concise and efficient. Here's a list of some of the commonly used built-in
functions:

1. abs(x): Returns the absolute value of a number.

print(abs(-5)) # Output: 5

2. all(iterable): Returns True if all elements of the iterable are true (or if the iterable

.
is empty).

m
print(all([True, False, True])) # Output: False

ru
3. any(iterable): Returns True if any element of the iterable is true. If the iterable is

Fo
empty, return False.

print(any([True, False, True])) # Output: True


ST
4. ascii(object): As repr() (will learn more about it in the Object-Orientation
chapters), return a string containing a printable representation of an object, but
R

escape the non-ASCII characters in the string using \x, \u or \U escapes.


ht

print(ascii("Hello Münchën")) # Output: 'Hello M\xfcnch\xe9n'

5. bin(x): Convert an integer number to a binary string.


ig
yr

print(bin(10)) # Output: '0b1010'


op

6. bool([x]): Convert a value to a Boolean.

print(bin(10)) # Output: '0b1010'


C

7. chr(i): Return the string representing a character whose Unicode code point is the
integer i.

print(chr(97)) # Output: 'a'

8. dict(): Create a new dictionary.

© Copyright RSTForum. Sharing of this material is illegal.


106
print(dict(a=1, b=2)) # Output: {'a': 1, 'b': 2}

9. divmod(a, b): Take two numbers as arguments and return a pair of numbers (a
tuple) consisting of their quotient and remainder when using integer division.

print(divmod(9, 2)) # Output: (4, 1)

10. enumerate(iterable, start=0): Return an enumerate object.

for i, v in enumerate(['a', 'b', 'c'], 1):

.
m
print(i, v) # Output: 1 a, 2 b, 3 c

ru
11. filter(function, iterable): Construct an iterator from elements of iterable for
which function returns true.

Fo
numbers = [1, 2, 3, 4, 5]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens)) # Output: [2, 4]
ST
12. float([x]): Convert a string or a number to floating point.
R

print(float(5)) # Output: 5.0


ht

13. hex(x): Convert an integer number to a lowercase hexadecimal string prefixed with
“0x”.
ig

print(hex(255)) # Output: '0xff'


yr

14. input([prompt]): Read a line from input, convert it to a string (stripping a trailing
op

newline), and return that.

name = input("Enter your name: ") # User enters 'Alice'


C

print(name) # Output: 'Alice'

15. int([x]): Convert a number or string to an integer, or return 0 if no arguments are


given.

print(int(2.5)) # Output: 2

16. len(s): Return the length of an object. The argument may be a sequence or a
collection.

© Copyright RSTForum. Sharing of this material is illegal.


107
print(len("Hello")) # Output: 5

17. list(iterable): Create a list.

print(list('hello')) # Output: ['h', 'e', 'l', 'l', 'o']

18. max(iterable): Return the largest item in an iterable or the largest of two or more
arguments.

.
m
print(max([1, 2, 3])) # Output: 3

ru
19. min(iterable): Return the smallest item in an iterable or the smallest of two or
more arguments.

Fo
print(min([1, 2, 3])) # Output: 1

20. pow(x, y): Return x to the power y.


ST
print(pow(2, 3)) # Output: 8
R

21. reversed(seq): Return a reverse iterator.


ht

print(list(reversed([1, 2, 3]))) # Output: [3, 2, 1]


ig

22. round(number[, ndigits]): Round a number to a given precision in decimal digits.


yr

print(round(5.76543, 2)) # Output: 5.77


op

23. sorted(iterable): Return a new sorted list from the items in iterable.
C

print(sorted([5, 2, 3, 1, 4])) # Output: [1, 2, 3, 4, 5]

24. str(object): Convert a value to a string.

print(str(123)) # Output: '123'

25. sum(iterable): Sums start and the items of an iterable from left to right and returns
the total.

© Copyright RSTForum. Sharing of this material is illegal.


108
print(sum([1, 2, 3, 4, 5])) # Output: 15

26. zip(*iterables): Makes an iterator that aggregates elements from each of the
iterables. Returns an iterator of tuples, where the i-th tuple contains the i-th element
from each of the argument sequences or iterables.

numbers = [1, 2, 3]
letters = ['a', 'b', 'c']
print(list(zip(numbers, letters))) # Output: [(1, 'a'), (2, 'b'), (3,
'c')]

.
m
27. type(object): Returns the type of the object.

ru
print(type(123)) # Output: <class 'int'>

Fo
28. set([iterable]): Returns a new set object, optionally with elements taken from
iterable.
ST
print(set([1, 2, 2, 3, 3, 3])) # Output: {1, 2, 3}

29. ord(c): Given a string representing one Unicode character, return an integer
R

representing the Unicode code point of that character.

print(ord('a')) # Output: 97
ht

30. id(object): Return the “identity” of an object. This is an integer which is guaranteed
ig

to be unique and constant for this object during its lifetime.


yr

a = 'Hello'
print(id(a)) # Output: Some id value, like 139860847423824
op

These functions cover a wide range of tasks, allowing you to write more efficient and
readable code. They are versatile and can be used in many different contexts. Remember,
C

Python's built-in functions are your friend - they are there to make your life easier, so you do
not have to reinvent the wheel every time.

© Copyright RSTForum. Sharing of this material is illegal.


109
6.12 Sample practice programs

6.12.1 Contact Management System


A program that allows the user to manage their contacts. They can add new contacts, view
existing contacts, search for contacts by name, update contact information, and delete
contacts.

# Contact Management System

contacts = []

.
m
def add_contact():
name = input("Enter the name of the contact: ")

ru
phone = input("Enter the phone number of the contact: ")
email = input("Enter the email address of the contact: ")
contact = {

Fo
'name': name,
'phone': phone,
'email': email
ST
}
contacts.append(contact)
print("Contact added successfully.")
R

def view_contacts():
if not contacts:
ht

print("No contacts found.")


else:
print("Contacts:")
ig

for contact in contacts:


print(f"Name: {contact['name']}")
yr

print(f"Phone: {contact['phone']}")
print(f"Email: {contact['email']}")
op

print("-------------------------")

def search_contacts():
C

name = input("Enter the name of the contact to search: ")


found_contacts = []
for contact in contacts:
if contact['name'].lower() == name.lower():
found_contacts.append(contact)

if not found_contacts:
print("No matching contacts found.")
else:
print("Matching contacts:")

© Copyright RSTForum. Sharing of this material is illegal.


110
for contact in found_contacts:
print(f"Name: {contact['name']}")
print(f"Phone: {contact['phone']}")
print(f"Email: {contact['email']}")
print("-------------------------")

def update_contact():
name = input("Enter the name of the contact to update: ")
for contact in contacts:
if contact['name'].lower() == name.lower():
phone = input("Enter the updated phone number: ")

.
email = input("Enter the updated email address: ")

m
contact['phone'] = phone
contact['email'] = email

ru
print("Contact updated successfully.")
return

Fo
print("Contact not found.")

def delete_contact():
ST
name = input("Enter the name of the contact to delete: ")
for contact in contacts:
if contact['name'].lower() == name.lower():
R

contacts.remove(contact)
print("Contact deleted successfully.")
return
ht

print("Contact not found.")


ig

# Main menu loop


while True:
yr

print("Contact Management System")


print("1. Add Contact")
op

print("2. View Contacts")


print("3. Search Contacts")
print("4. Update Contact")
C

print("5. Delete Contact")


print("6. Exit")

choice = input("Enter your choice: ")

if choice == '1':
add_contact()
elif choice == '2':
view_contacts()
elif choice == '3':

© Copyright RSTForum. Sharing of this material is illegal.


111
search_contacts()
elif choice == '4':
update_contact()
elif choice == '5':
delete_contact()
elif choice == '6':
print("Thank you for using the Contact Management System.
Goodbye!")
break
else:
print("Invalid choice. Please try again.")

.
m
ru
6.12.2 To-Do List Manager

Fo
A program that helps the user manage their tasks. The user can add new tasks, mark tasks
as completed, view the list of tasks, and remove completed tasks.
ST
# To-Do List Manager

tasks = []
R

def add_task():
task = input("Enter a new task: ")
tasks.append(task)
ht

print("Task added successfully.")


ig

def view_tasks():
if not tasks:
yr

print("No tasks found.")


else:
print("Tasks:")
op

for index, task in enumerate(tasks, start=1):


print(f"{index}. {task}")
print("-------------------------")
C

def mark_completed():
view_tasks()
task_number = int(input("Enter the task number to mark as completed:
"))
if 1 <= task_number <= len(tasks):
task = tasks[task_number - 1]
print(f"Task '{task}' marked as completed.")
tasks.remove(task)

© Copyright RSTForum. Sharing of this material is illegal.


112
else:
print("Invalid task number.")

def remove_completed():
completed_tasks = [task for task in tasks if
task.endswith("(Completed)")]
if not completed_tasks:
print("No completed tasks found.")
else:
print("Completed Tasks:")
for index, task in enumerate(completed_tasks, start=1):

.
print(f"{index}. {task}")

m
remove_option = input("Do you want to remove all completed

ru
tasks? (yes/no): ")
if remove_option.lower() == "yes":
tasks[:] = [task for task in tasks if not

Fo
task.endswith("(Completed)")]
print("Completed tasks removed successfully.")
elif remove_option.lower() == "no":
ST
print("No completed tasks were removed.")
else:
print("Invalid option.")
R

# Main menu loop


while True:
ht

print("To-Do List Manager")


print("1. Add Task")
print("2. View Tasks")
ig

print("3. Mark Task as Completed")


print("4. Remove Completed Tasks")
yr

print("5. Exit")
op

choice = input("Enter your choice: ")

if choice == '1':
C

add_task()
elif choice == '2':
view_tasks()
elif choice == '3':
mark_completed()
elif choice == '4':
remove_completed()
elif choice == '5':
print("Thank you for using the To-Do List Manager. Goodbye!")
break

© Copyright RSTForum. Sharing of this material is illegal.


113
else:
print("Invalid choice. Please try again.")

6.12.3 Inventory Management System


A program that assists in managing inventory for a small business. The program allows the
user to add new products, update the quantity and price of existing products, view the
inventory, and generate reports on low stock items.

.
# Inventory Management System

m
inventory = {}

ru
def add_product():
product_id = input("Enter the product ID: ")

Fo
if product_id in inventory:
print("Product already exists in the inventory.")
return
ST
name = input("Enter the product name: ")
quantity = int(input("Enter the product quantity: "))
price = float(input("Enter the product price: "))
R

product = {
'name': name,
ht

'quantity': quantity,
'price': price
ig

}
inventory[product_id] = product
yr

print("Product added successfully.")

def update_product():
op

product_id = input("Enter the product ID to update: ")


if product_id not in inventory:
print("Product not found.")
C

return

print("Enter the new product details:")


name = input("Enter the product name: ")
quantity = int(input("Enter the product quantity: "))
price = float(input("Enter the product price: "))

product = {
'name': name,

© Copyright RSTForum. Sharing of this material is illegal.


114
'quantity': quantity,
'price': price
}
inventory[product_id] = product
print("Product updated successfully.")

def view_inventory():
if not inventory:
print("Inventory is empty.")
else:
print("Inventory:")

.
for product_id, product in inventory.items():

m
print(f"Product ID: {product_id}")
print(f"Name: {product['name']}")

ru
print(f"Quantity: {product['quantity']}")
print(f"Price: {product['price']}")
print("-------------------------")

def generate_report():
if not inventory:
Fo
ST
print("Inventory is empty.")
else:
print("Inventory Report:")
R

for product_id, product in inventory.items():


print(f"Product ID: {product_id}")
print(f"Name: {product['name']}")
ht

print(f"Quantity: {product['quantity']}")
print(f"Price: {product['price']}")
print(f"Total Value: {product['quantity'] *
ig

product['price']}")
print("-------------------------")
yr

# Main menu loop


op

while True:
print("Inventory Management System")
print("1. Add Product")
C

print("2. Update Product")


print("3. View Inventory")
print("4. Generate Report")
print("5. Exit")

choice = input("Enter your choice: ")

if choice == '1':
add_product()
elif choice == '2':

© Copyright RSTForum. Sharing of this material is illegal.


115
update_product()
elif choice == '3':
view_inventory()
elif choice == '4':
generate_report()
elif choice == '5':
print("Thank you for using the Inventory Management System.
Goodbye!")
break
else:
print("Invalid choice. Please try again.")

.
m
ru
6.12.4 Student Grade Calculator
A program that calculates and stores the grades of a class. The program allows the user to

Fo
enter the names and scores of students, calculate their average grades, display the highest
and lowest grades, and sort the student list based on grades.
ST
# Student Grade Calculator

students = []
R

def add_student():
name = input("Enter the student's name: ")
scores = []
ht

for i in range(3):
score = float(input(f"Enter score {i+1}: "))
ig

scores.append(score)
student = {
yr

'name': name,
'scores': scores
}
op

students.append(student)
print("Student added successfully.")
C

def calculate_average(scores):
total = sum(scores)
return total / len(scores)

def calculate_highest_lowest():
highest_score = float('-inf')
lowest_score = float('inf')
highest_student = ''
lowest_student = ''

© Copyright RSTForum. Sharing of this material is illegal.


116
for student in students:
name = student['name']
scores = student['scores']
average = calculate_average(scores)
if average > highest_score:
highest_score = average
highest_student = name
if average < lowest_score:
lowest_score = average
lowest_student = name
return highest_student, highest_score, lowest_student, lowest_score

.
m
def view_students():
if not students:

ru
print("No students found.")
else:
print("Students:")

Fo
for student in students:
name = student['name']
scores = student['scores']
ST
average = calculate_average(scores)
print(f"Name: {name}")
print(f"Scores: {scores}")
R

print(f"Average: {average}")
print("-------------------------")
ht

def sort_students():
sorted_students = sorted(students, key=lambda x:
calculate_average(x['scores']), reverse=True)
ig

print("Sorted Students (by average score):")


for student in sorted_students:
yr

name = student['name']
scores = student['scores']
op

average = calculate_average(scores)
print(f"Name: {name}")
print(f"Scores: {scores}")
C

print(f"Average: {average}")
print("-------------------------")

# Main menu loop


while True:
print("Student Grade Calculator")
print("1. Add Student")
print("2. View Students")
print("3. Calculate Highest and Lowest Average")
print("4. Sort Students by Average")

© Copyright RSTForum. Sharing of this material is illegal.


117
print("5. Exit")

choice = input("Enter your choice: ")

if choice == '1':
add_student()
elif choice == '2':
view_students()
elif choice == '3':
highest_student, highest_score, lowest_student, lowest_score =
calculate_highest_lowest()

.
print(f"Highest Average: {highest_student} - {highest_score}")

m
print(f"Lowest Average: {lowest_student} - {lowest_score}")
elif choice == '4':

ru
sort_students()
elif choice == '5':
print("Thank you for using the Student Grade Calculator.

Fo
Goodbye!")
break
else:
ST
print("Invalid choice. Please try again.")
R

6.12.5 Word Frequency Analyzer


A program that analyzes the frequency of words in a given text. The user is able to enter a
ht

paragraph, and the program should output a dictionary containing each unique word and its
frequency in the text.
ig

# Word Frequency Analyzer


yr

text = input("Enter a paragraph: ")


op

# Clean the text by removing punctuation and converting to lowercase


cleaned_text = ''.join(c.lower() if c.isalpha() or c.isspace() else ''
for c in text)
C

# Split the text into words


words = cleaned_text.split()

# Create a dictionary to store word frequencies


word_freq = {}

# Count the frequency of each word


for word in words:

© Copyright RSTForum. Sharing of this material is illegal.


118
if word in word_freq:
word_freq[word] += 1
else:
word_freq[word] = 1

# Display the word frequencies


print("Word Frequencies:")
for word, freq in word_freq.items():
print(f"{word}: {freq}")

# Sort the word frequencies in descending order

.
sorted_word_freq = sorted(word_freq.items(), key=lambda x: x[1],

m
reverse=True)

ru
# Display the top 5 most frequent words
print("Top 5 Most Frequent Words:")
for word, freq in sorted_word_freq[:5]:

Fo
print(f"{word}: {freq}")
ST
R
ht
ig
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


119
Chapter 7: Debugging

7.1 Understanding Debugging


Debugging is the process of finding and resolving issues or "bugs" within computer
programs. It is an integral part of software development, often requiring sophisticated tools
and techniques. Bugs in a program can manifest in many forms, such as incorrect
calculations, unintended actions, or unexpected crashes.

In Python, as with any programming language, debugging is a critical skill. Understanding


how to effectively debug Python code allows you to better understand your code, make it

.
m
more robust and reliable, and improve your productivity as a programmer.

A good debugger helps to identify the root cause of an issue by allowing you to inspect the

ru
state of the program at various stages of its execution. This can involve examining the
values of variables, the flow of control, and the call stack.

Fo
7.2 Python Exceptions
In Python, errors detected during execution are called "exceptions". They are not
ST
unconditionally fatal, but by default, they cause the program to terminate. Exceptions can be
handled in Python code using try and except blocks. When the code in the try block
encounters an error, control is passed to the corresponding except block, where you can
R

handle the error or output a more user-friendly error message.

Here are some of the most common exceptions in Python:


ht

● SyntaxError: Raised when the parser encounters a syntax error.


ig

print("Hello World) # missing closing quote


yr
op

● NameError: Raised when a local or global name is not found.

print(undefined_variable) # variable not defined


C

● ZeroDivisionError: Raised when the second argument of a division or modulo


operation is zero.

print(1/0) # division by zero

● IndexError: Raised when a sequence subscript is out of range.

© Copyright RSTForum. Sharing of this material is illegal.


120
my_list = [1, 2, 3]
print(my_list[3]) # index out of range

● KeyError: Raised when a dictionary key is not found.

my_dict = {'a': 1, 'b': 2}


print(my_dict['c']) # key not found in dictionary

.
● AttributeError: Raised when an attribute reference or assignment fails.

m
x = 10

ru
x.append(6) # 'int' object has no attribute 'append'

Fo
● TypeError: Raised when an operation or function is applied to an object of
inappropriate type.
ST
'2' + 2 # unsupported operand types for +
R

● ValueError: Raised when a built-in operation or function receives an argument that


has the right type but an inappropriate value.
ht

int('hello') # invalid literal for int() with base 10


ig

● FileNotFoundError: Raised when trying to open a file that does not exist.
yr

with open('non_existent_file.txt') as f:
op

print(f.read())
C

● ImportError: Raised when the imported module is not found.

import non_existent_module # No module named 'non_existent_module'

● OverflowError: Raised when the result of an arithmetic operation is too large to be


expressed by a Python integer.

import math

© Copyright RSTForum. Sharing of this material is illegal.


121
print(math.exp(1000)) # range exceeded for float

● RuntimeError: Raised when an error is detected that doesn’t fall in any of the other
categories.

raise RuntimeError("This is a runtime error")

● IndentationError: Raised when there is incorrect indentation.

.
m
def func():
print("Hello World") # expected an indented block

ru
Fo
● StopIteration: Raised by built-in function next() and an iterator‘s __next__()
method to signal that there are no further items produced by the iterator.
ST
my_list = iter([1, 2, 3])
print(next(my_list))
print(next(my_list))
print(next(my_list))
R

print(next(my_list)) # StopIteration
ht

● UnboundLocalError: Raised when a reference is made to a local variable in a


function or method, but no value has been bound to that variable.
ig
yr

def func():
print(x)
x = 10
op

func() # local variable 'x' referenced before assignment


C

These are just a few examples of exceptions that can be raised in Python
(https://docs.python.org/3/library/exceptions.html). When these occur, Python provides a
traceback, which can be used to determine where the error occurred and what function calls
led up to the error.

By understanding these exceptions and learning how to handle them properly, you can write
more robust Python programs and become a more effective programmer.

© Copyright RSTForum. Sharing of this material is illegal.


122
Note:
As you continue your journey with Python, you may encounter exceptions such as StopIteration
and FileNotFoundError which we have not yet experienced in our discussions or examples. Don't
worry, these are more advanced topics that you will naturally come across as you delve deeper into
file handling, iterators, generators, and more.

What's important at this stage is to understand that these exceptions exist and knowing how to
handle them can lead to more robust code. They provide important clues when something goes
wrong in your program. Reading and understanding the traceback of these exceptions can help you
locate the source of the problem.

Remember, encountering errors and exceptions is a normal part of the programming process,

.
regardless of your skill level. Even seasoned programmers deal with bugs in their code. The key is

m
understanding how to effectively debug these issues, and the first step in that process is
understanding the exceptions that Python might throw at you.

ru
As you progress further in your Python programming journey, be sure to revisit this chapter and
others as a handy reference.

Fo
7.3 Handling Exceptions in Python: try/except
ST
The Python language provides a simple yet powerful way of handling exceptions using the
try and except keywords.

When the code inside the try block encounters an error, control is passed to the
R

corresponding except block, where you can handle the error or output a more user-friendly
error message.
ht

Here are some examples:


ig

Example 1:
yr

try:
result = 10 / 0
op

except ZeroDivisionError:
print("You can't divide by zero!")
C

In this example, the code tries to divide a number by zero, which raises a
ZeroDivisionError. The except block catches this error and prints a friendly message
instead of letting the program crash.

Example 2:

try:
numbers = [1, 2, 3]
print(numbers[5])

© Copyright RSTForum. Sharing of this material is illegal.


123
except IndexError:
print("That index is not in the list!")

In this example, the code tries to access an index that doesn't exist in the list, raising an
IndexError. The except block catches this error and prints an informative message.

Example 3:

try:
with open('non_existent_file.txt') as f:

.
print(f.read())

m
except FileNotFoundError:
print("That file was not found!")

ru
In this case, the code attempts to open a file that doesn't exist, raising a
FileNotFoundError. The except block catches this error and informs the user.

Fo
7.3.1 More Advanced Exception Handling: try/except/else/finally
ST
For more sophisticated exception handling, Python provides the
try/except/else/finally construct. Here's what each block means:

● try: The code block that might raise an exception.


R

● except: The code block that handles the exception.


● else: If there is this block, it will be executed if the try block doesn't raise any
exceptions.
ht

● finally: This block is always executed no matter what, whether an exception was
raised or not, even if an uncaught exception or a return/break/continue statement
ig

was encountered in the try or except blocks.


yr

Here are examples illustrating these:

Example 1:
op

try:
C

result = 10 / 2
except ZeroDivisionError:
print("You can't divide by zero!")
else:
print("The division succeeded!")
finally:
print("End of program.")

In this example, no exception is raised, so the else block is executed, and then the finally
block is executed.

© Copyright RSTForum. Sharing of this material is illegal.


124
Example 2:

try:
numbers = [1, 2, 3]
print(numbers[5])
except IndexError:
print("That index is not in the list!")
else:
print("Index found in list!")
finally:

.
print("End of program.")

m
In this example, an IndexError is raised, so the except block is executed, and then the finally

ru
block is executed.

Fo
Example 3:

try:
ST
with open('non_existent_file.txt') as f:
print(f.read())
except FileNotFoundError:
print("That file was not found!")
R

else:
print("File found and read successfully!")
finally:
ht

print("End of program.")
ig

In this case, a FileNotFoundError is raised, so the except block is executed, and then the
finally block is executed.
yr

The try/except/else/finally construct provides you with a flexible tool to handle


op

exceptions in Python,

7.4 Raising Exceptions: The raise keyword


C

While Python provides a number of built-in exceptions that can handle most common error
scenarios, there may be times when you need to generate exceptions based on your
application-specific conditions. This is where the raise keyword comes into play.

The raise keyword allows you to trigger exceptions in your code manually, enabling you to
react to potential issues that are specific to your application's requirements. This is a
powerful tool for ensuring that your programs behave as expected under all conditions.

© Copyright RSTForum. Sharing of this material is illegal.


125
7.4.1 Using raise to trigger built-in exceptions

First, let's look at how we can use the raise keyword to trigger built-in exceptions.

For example, imagine you're building a calculator app and you want to prevent users from
dividing by zero. You could use the raise keyword to throw a ZeroDivisionError
exception when the denominator is zero, as shown in this function:

def divide(num1, num2):


if num2 == 0:
raise ZeroDivisionError("You can't divide by zero!")

.
m
else:
return num1 / num2

ru
In this example, when you call divide(10, 0), the function will raise a
ZeroDivisionError with the message "You can't divide by zero!"

7.4.2 Creating custom exceptions


Fo
There may be times when Python's built-in exceptions don't quite fit the error you're trying to
ST
handle. In these cases, you can define your own custom exception types.

To define a custom exception, you can create a new class that inherits from the built-in
R

Exception class or one of its subclasses. For example:

class ValueTooHighError(Exception):
ht

pass
ig

class ValueTooLowError(Exception):
def __init__(self, message, value):
yr

self.message = message
self.value = value
op

In this code, we've defined two new exception types: ValueTooHighError and
ValueTooLowError. The ValueTooLowError exception includes a custom constructor
C

(__init__) that accepts additional arguments (message and value), which are then stored
as instance variables.

Now, you can use these custom exceptions in your code using the raise keyword:

def test_value(x):
if x > 100:
raise ValueTooHighError("Value is too high.")
if x < 5:
raise ValueTooLowError("Value is too low.", x)

© Copyright RSTForum. Sharing of this material is illegal.


126
try:
test_value(200)
except ValueTooHighError as e:
print(e)
except ValueTooLowError as e:
print(f"{e.message} The value is: {e.value}")

In this example, the test_value function raises a ValueTooHighError if the argument is


greater than 100, and a ValueTooLowError if the argument is less than 5. We then use a
try/except block to catch and handle these exceptions.

.
m
In summary, the raise keyword is a powerful tool for handling errors and enforcing
constraints in your Python programs. By using it effectively, you can make your programs

ru
more robust and easier to debug.

Fo
Note:
In the previous examples, you saw how we can create custom exceptions by defining new classes
that inherit from the built-in Exception class. However, if you're not yet familiar with the concept of
ST
classes and object-oriented programming, don't worry. The understanding of these examples is not
crucial at this point.

We will delve into the topic of classes, objects, and object-oriented programming in Python in the
R

upcoming chapters. For now, it's enough to understand that a class is a blueprint for creating
objects (specific data structures), and that we can create our own types of exceptions by making
new classes that inherit from the built-in Exception class.
ht

When we get to the chapter on classes, we will revisit this topic and these examples will make
much more sense. For now, just understand that Python allows us to create our own exceptions
that we can raise in our programs using the raise keyword, which can be useful for handling error
ig

conditions specific to our applications. The details of how this is done will become clearer as you
progress in your understanding of Python.
yr

7.5 Debugging with PDB, the Python Debugger


op

Sometimes reading error messages or print statements isn't enough to understand what's
going wrong with your code. In such cases, the Python Debugger, or PDB, can be an
invaluable tool. PDB allows you to interactively step through your code, line by line,
C

inspecting variable values and program flow.

PDB is a part of Python's standard library and doesn't require any additional installation. It
provides various commands to help in debugging like setting breakpoints, stepping through
the code, inspecting variables, and changing variable values.

7.5.1 Starting a debugging session


To begin a debugging session, we'll need to import pdb and call its set_trace() function at
the point where we want to start the debugging. This function call serves as a breakpoint.

© Copyright RSTForum. Sharing of this material is illegal.


127
Here's an example:

import pdb

def add_to_list_in_dict(thedict, listname, element):


if listname not in thedict:
thedict[listname] = []
pdb.set_trace() # Start debugging here
thedict[listname].append(element)

.
mydict = {}

m
add_to_list_in_dict(mydict, "mylist", "myelement")

ru
In this example, we add a call to pdb.set_trace() where we want to start the debugging.
When Python executes this line, it'll start a pdb debugging session.

Fo
7.5.2 PDB commands
Once the pdb prompt is displayed, you can use a variety of commands to navigate through
ST
your code. Here are some of the most commonly used pdb commands:

● n(ext): Execute the next line and stop again.


● s(tep): Execute the current line and stop at the first possible occasion.
R

● c(ontinue): Continue execution and only stop when a breakpoint is encountered.


● l(ist): Display 11 lines around the current line or continue the previous listing.
● h(elp): Without argument, print the list of available commands. With a command as
ht

argument, print help about that command.


● q(uit): Quit from the debugger. The program being executed is aborted.
ig

● p(rint): Evaluate the expression in the current context and print its value.
yr

Here is how these commands can be used in practice:


op

> /path/to/your/script.py(7)add_to_list_in_dict()
-> thedict[listname].append(element)
(Pdb) p thedict
C

{'mylist': []}
(Pdb) n
> /path/to/your/script.py(6)add_to_list_in_dict()
-> pdb.set_trace()
(Pdb) p thedict
{'mylist': ['myelement']}
(Pdb) c

In this example:

© Copyright RSTForum. Sharing of this material is illegal.


128
● The first p thedict command prints the value of thedict before the line
thedict[listname].append(element) has been executed.
● The n command moves to the next line of execution.
● The second p thedict command prints the value of thedict after the line
thedict[listname].append(element) has been executed.
● Finally, the c command ends the debugging session and the program continues to
run to completion.

7.5.3 Post-mortem debugging


Sometimes your program crashes and you don't know why. In this case, pdb has a nice
function you can use, post_mortem(). It starts a post-mortem debugging session. Here's an

.
m
example:

ru
import pdb

def buggy_func(x):

Fo
return 1.0 / x

try:
ST
buggy_func(0)
except ZeroDivisionError:
pdb.post_mortem()
R

In this example, calling buggy_func(0) causes a ZeroDivisionError. The pdb


post-mortem function allows us to start a debugging session at the point of the exception.
ht

In summary, PDB is a powerful tool for Python debugging. By allowing you to step through
your code interactively and inspect variables at any point, PDB provides a deeper
ig

understanding of your code's execution flow and helps you pinpoint and fix bugs more
efficiently.
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


129
Chapter 8: Object-Oriented Programming (OOP) in
Python
Welcome to Chapter 8, where we'll dive deep into the realm of object-oriented programming
(OOP) in Python. Python, being a multi-paradigm language, supports both procedural and
object-oriented programming styles. While we have been using aspects of OOP
unconsciously, it's time to study this powerful paradigm in a formal and systematic way.

Object-oriented programming is a programming paradigm that provides a means of


structuring programs so that properties and behaviors are bundled into individual objects. If
you have come across terms such as "class", "object", "inheritance", or "encapsulation", and

.
m
found them a bit overwhelming, worry not! By the end of this chapter, you'll have a solid
understanding of these concepts and you'll be comfortable using them in your Python
programming journey.

ru
To ensure a thorough understanding of object-oriented programming in Python, we will cover

Fo
the following topics in this chapter:

● Introduction to Object-Oriented Programming (8.1)


● Classes and Objects in Python (8.2)
ST
● Inheritance and Polymorphism (8.3)
● Encapsulation and Abstraction (8.4)
● Special (Dunder) Methods (8.5)
R

● Working with Class and Static Methods (8.6)


● Composition and Aggregation (8.7)
● Python's Built-In OOP Features (8.8)
ht

● Working with Modules and Packages (8.9)


● Practical OOP: Design Patterns (8.10)
ig

● Summary and Real-world Examples of OOP in Python (8.11)

Each section will build upon the last, starting with the basics and gradually delving into more
yr

advanced topics. By the end of this chapter, you'll be well-equipped to utilize the power of
object-oriented programming in Python for your coding projects.
op

Let's start with an introduction to the concept of object-oriented programming, understand its
historical context, significance, and how it compares with the procedural style of
C

programming. Let's begin our OOP journey with section 8.1.

8.1 Introduction to Object-Oriented Programming

8.1.1 Procedural vs. Object-Oriented Programming


Before we dive into the realm of object-oriented programming (OOP), it's helpful to contrast it
with the procedural style of programming, which you might already be familiar with.

© Copyright RSTForum. Sharing of this material is illegal.


130
Procedural programming is a programming paradigm in which the program structure is made
up of procedures, also known as functions or routines, which are a series of computational
steps to be carried out. Any given procedure might be called at any point during a program's
execution, including by other procedures or itself. Python, C, and Perl are languages that
allow procedural programming.

On the other hand, object-oriented programming is a paradigm based on the concept of


"objects", which can contain data, in the form of fields (often known as attributes), and code,
in the form of procedures (often known as methods). A distinguishing feature of objects is
that an object's procedures can access and often modify the data fields of the object they are
associated with. Languages such as Python, Java, and C++ support object-oriented
programming.

.
m
8.1.2 The Concept of Classes and Objects

ru
A class is a blueprint for creating objects (a particular data structure), providing initial
values for state (member variables or attributes), and implementations of behavior
(member functions or methods). The user-defined objects are created using the class

Fo
structure. This is similar to the way a building blueprint describes how to construct a building,
and the buildings themselves are the objects.
ST
An object is an encapsulation of variables and functions into a single entity. Objects get their
variables and functions from classes. Classes are essentially a template to create your
objects.
R

Here's a basic example:


ht

class MyClass:
variable = "This is a class variable"
ig

def function(self):
print("This is a message inside the class.")
yr

my_object = MyClass()
op

In the example above, MyClass is a class with a class variable variable and a method
function. We create an object my_object using the MyClass definition. We can then
C

access the class variable and method using the object.

8.1.3 Benefits and Applications of OOP


Object-oriented programming comes with substantial benefits, including:

● Modularity for easier troubleshooting: When a problem occurs in OOP, you know
exactly where to look. That's because, in OOP, data type is tied to the data itself.
● Reuse of code through inheritance: Suppose that in addition to your Car object,
one colleague needs a RaceCar object, and another needs a Limousine object.

© Copyright RSTForum. Sharing of this material is illegal.


131
Everyone builds off from your Car object and simply modifies their copies to include
the features they need. This ability to build off of other object's data types is a
fundamental characteristic of OOP and it is called inheritance.
● Flexibility through polymorphism: This refers to the concept of using a single
interface to represent different underlying forms (data types).
● Effective problem solving: A large problem is divided into smaller sets by creating
objects. The data structures are designed around objects and not procedures or
functions.

As a result of these advantages, OOP is used in a wide range of areas including web and
desktop applications, databases, AI, game development, and many more.

.
m
Object-oriented programming is a major paradigm, and it forms the basis for many modern
programming languages. Understanding OOP will give you an essential skill for today's
programming environment.

ru
8.2 Classes and Objects in Python

8.2.1 Understanding Classes and Objects


Fo
ST
A class is a code template for creating objects. Objects have member variables and have
behavior associated with them. In Python, a class is created by the keyword class.

An object is created using the constructor of the class. This object will then be called the
R

instance of the class. You can create as many objects for a class as you need.
ht

class MyClass:
x = 5
ig

p1 = MyClass()
print(p1.x) # output: 5
yr

In the example above, MyClass is a class with a member variable x. p1 is an object of


op

MyClass.

8.2.2 Defining a Class in Python


C

Defining a class in Python is simple and straightforward. You use the keyword class to define
a class. Here's a simple class definition:

class MyClass:
x = 5

In this example, we've created a class MyClass that has one attribute x.

© Copyright RSTForum. Sharing of this material is illegal.


132
8.2.3 Creating an Instance of a Class
An instance of a class, also known as an object, is created like a function call of the class.

p1 = MyClass()

Here, p1 is an instance (or object) of MyClass.

8.2.4 Adding Methods to a Class


Methods are functions that are associated with a class. You can define methods within your
class:

.
m
class MyClass:

ru
x = 5

def hello(self):

Fo
print("Hello, I am a method of this class!")

p1 = MyClass()
ST
p1.hello() # output: Hello, I am a method of this class!

In this example, hello is a method of MyClass. Note that all methods must take at least one
R

parameter, self, which refers to the object being created or manipulated.

8.2.5 The __init__ Method and Object Initialization


ht

The __init__ method is a special method that gets called when a new object is created
from a class. It allows the class to initialize attributes of the class.
ig

class MyClass:
yr

def __init__(self):
self.x = 5
op

p1 = MyClass()
print(p1.x) # output: 5
C

In this example, __init__ method is initializing x for the object being created. The self
keyword represents the instance of the class and is automatically passed as the first
parameter when a class's method is called.

8.2.6 Instance Variables and Class Variables


Instance variables are owned by instances of the class. This means that for each object or
instance of a class, the instance variables are different.

© Copyright RSTForum. Sharing of this material is illegal.


133
On the other hand, class variables are shared by all instances of a class. They are not tied to
any one instance of a class.

class MyClass:
class_var = "I am a class variable!"

def __init__(self, x):


self.instance_var = x

p1 = MyClass("I belong to p1")


p2 = MyClass("I belong to p2")

.
m
print(p1.class_var) # output: I am a class variable!
print(p2.class_var) # output: I am a class variable!

ru
print(p1.instance_var) # output: I belong to p1
print(p2.instance_var) # output: I belong to p2

Fo
In this example, class_var is a class variable shared by all instances, while instance_var
is specific to each instance.
ST
Classes and objects are a fundamental concept in Python's object-oriented programming.
They provide structure and reusable code and are used in almost all Python applications.
R

8.2.7 Real-World Example


We'll create a BankAccount class and Customer class to simulate some basic banking
ht

operations.

Here's an overview of the program:


ig

# BankAccount Class Definition


yr

class BankAccount:
# Class variable - applicable to all instances
op

interest_rate = 0.05

def __init__(self, account_number, balance=0):


C

# Instance variables - unique for each instance


self.account_number = account_number
self.balance = balance

# Instance method to deposit money


def deposit(self, amount):
self.balance += amount
return self.balance

# Instance method to withdraw money

© Copyright RSTForum. Sharing of this material is illegal.


134
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
else:
print("Insufficient balance!")
return self.balance

# Instance method to calculate interest


def calculate_interest(self):
return self.balance * self.interest_rate

.
# Customer Class Definition

m
class Customer:
def __init__(self, name, bank_account):

ru
self.name = name
self.bank_account = bank_account

Fo
# Instance method to deposit money
def deposit_money(self, amount):
self.bank_account.deposit(amount)
ST
print(f"{amount} deposited into account
{self.bank_account.account_number}")
R

# Instance method to withdraw money


def withdraw_money(self, amount):
self.bank_account.withdraw(amount)
ht

print(f"{amount} withdrawn from account


{self.bank_account.account_number}")
ig

# Instance method to display account balance and calculated interest


def display_account_info(self):
yr

print(f"Customer: {self.name}, Account Number:


{self.bank_account.account_number}, Balance:
op

{self.bank_account.balance}, Interest:
{self.bank_account.calculate_interest()}")
C

# Creating a bank account object


account = BankAccount('123456789', 5000)

# Creating a customer object


customer = Customer('John Doe', account)

# The customer makes some transactions


customer.deposit_money(1000)
customer.withdraw_money(500)
customer.display_account_info()

© Copyright RSTForum. Sharing of this material is illegal.


135
This program illustrates the following concepts:

● Class and object definition: BankAccount and Customer are classes, account and
customer are objects.
● Use of the __init__ method to initialize object attributes.
● Instance variables (self.account_number and self.balance) and class variables
(interest_rate)
● Instance methods (deposit, withdraw, calculate_interest)
● Object interaction: Customer objects interact with BankAccount objects,
demonstrating the power of object-oriented programming.

.
m
You can run this program in your Python environment, try different operations, and see the
output.

ru
8.3 Inheritance and Polymorphism

Fo
8.3.1 Concept of Inheritance, Subclasses, and Superclasses
Inheritance is a key principle of object-oriented programming that allows one class to inherit
ST
the properties and methods of another class. This leads to code reusability and a
hierarchical structure between classes. The class from which properties and methods are
inherited is called the superclass or parent class, and the class that inherits these properties
and methods is called the subclass or child class.
R

For example, consider a Bird class and a Penguin class. All birds have certain
characteristics, like wings and the ability to fly. However, a penguin is a special kind of bird
ht

that cannot fly. This kind of relationship can be represented through inheritance: Bird would
be the superclass, and Penguin would be the subclass.
ig

8.3.2 Implementing Inheritance in Python


yr

Python allows inheritance through a simple syntax. When defining a subclass, you include
the superclass in parentheses in the class definition:
op

class Bird:
def can_fly(self):
C

return True

class Penguin(Bird):
def can_fly(self):
return False

Here, Penguin is a subclass of Bird and has overridden the can_fly method from the Bird
class.

© Copyright RSTForum. Sharing of this material is illegal.


136
8.3.3 Method Overriding (Polymorphism in OOP)
Polymorphism is another key concept in OOP that allows a subclass to provide a different
implementation of a method that is already defined in its superclass. This is achieved by
overriding methods.

In the example above, the Penguin class overrides the can_fly method from the Bird
class. When called on a Penguin instance, it will return False instead of True.

8.3.4 The super() Function


The super() function in Python is used to call a method from a superclass in a subclass.

.
This can be useful when the subclass method wants to extend rather than entirely replace

m
the superclass method.

ru
class Bird:
def __init__(self):
self.can_fly = True

class Penguin(Bird):
def __init__(self):
Fo
ST
super().__init__() # calls the __init__ method of Bird
self.can_fly = False
R

In this example, Penguin calls the __init__ method of Bird using super() before setting
can_fly to False.
ht

8.3.5 Multiple Inheritance


Python also supports multiple inheritance, where a subclass can inherit from multiple
ig

superclasses:
yr

class Bird:
can_fly = True
op

class Swimmer:
can_swim = True
C

class Penguin(Bird, Swimmer):


can_fly = False

Here, Penguin is a subclass of both Bird and Swimmer. It inherits properties from both
classes but overrides the can_fly property from Bird.

Inheritance and polymorphism are powerful tools for creating reusable, organized, and
logical code structures in object-oriented programming.

© Copyright RSTForum. Sharing of this material is illegal.


137
8.3.6 Real-World Example
Let's consider a school management system where we have different types of users like
Student, Teacher, and Administrator. We will use inheritance and polymorphism concepts to
show how this can be modeled in an object-oriented way in Python.

# Class Definition for User (Base Class)


class User:
def __init__(self, name, email):
self.name = name
self.email = email

.
m
def display_user_details(self):
print(f'Name: {self.name}, Email: {self.email}')

ru
# Class Definition for Student (Inherited from User)
class Student(User):

Fo
def __init__(self, name, email, student_id):
super().__init__(name, email) # Calls the init method of base
class
ST
self.student_id = student_id

def display_user_details(self): # Method Overriding


super().display_user_details() # Calls the method from the base
R

class
print(f'Student ID: {self.student_id}')
ht

# Class Definition for Teacher (Inherited from User)


class Teacher(User):
ig

def __init__(self, name, email, subject):


super().__init__(name, email)
yr

self.subject = subject

def display_user_details(self): # Method Overriding


op

super().display_user_details()
print(f'Subject: {self.subject}')
C

# Class Definition for Administrator (Inherited from User)


class Administrator(User):
def __init__(self, name, email, department):
super().__init__(name, email)
self.department = department

def display_user_details(self): # Method Overriding


super().display_user_details()
print(f'Department: {self.department}')

© Copyright RSTForum. Sharing of this material is illegal.


138
# Creating objects for each class
student = Student('John Doe', '[email protected]', 'S101')
teacher = Teacher('Jane Smith', '[email protected]', 'Mathematics')
admin = Administrator('James Johnson', '[email protected]',
'Admissions')

# Each object calls the method


student.display_user_details()
teacher.display_user_details()

.
admin.display_user_details()

m
In this program, Student, Teacher, and Administrator are all subclasses of User, and

ru
they each override the display_user_details method to include their unique details.

Fo
In addition, they each use super() to call the User (superclass) version of
display_user_details before adding their unique details. This illustrates how subclasses
can inherit from a superclass, override methods, and use super() to call superclass
methods.
ST
8.4 Special (Dunder) Methods
R

Special methods in Python are sometimes called "dunder" methods (a portmanteau of


"double underscore"). They have special names that start and end with double underscores
(e.g., __init__, __str__, __repr__). These methods are used to emulate certain
ht

behaviors or implement certain functionalities in classes.


ig

8.4.1 Understanding Special Methods


Special methods allow us to use Python's syntax features within our own custom objects.
yr

For example:
op

● __init__(self): As we have seen in previous examples, this method is used for


initializing an object. It is the constructor method in Python.
● __str__(self): This method should return a string, and is used when we use the
C

str() function on our object or when we try to print our object. It's meant to provide a
"user-friendly" output describing the object.
● __repr__(self): This is similar to __str__, but should provide more detailed
output. It's meant to be unambiguous and used for debugging and development. If
__str__ is not defined, Python uses __repr__ as a fallback.

8.4.2 Overloading Operators in Python


In addition to these, Python also provides a series of special methods to overload operators,
that is, to define what an operator (like +, -, *, /, ==, etc.) should do when used with instances
of your class.

© Copyright RSTForum. Sharing of this material is illegal.


139
For instance:
__add__(self, other): This method allows us to use the + operator on our objects.
Here's an example of these special methods in action:

class ComplexNumber:
def __init__(self, real=0, imag=0):
self.real = real
self.imag = imag

def __str__(self):

.
return f"{self.real} + {self.imag}j"

m
def __repr__(self):

ru
return f"ComplexNumber({self.real}, {self.imag})"

def __add__(self, other):

Fo
if isinstance(other, ComplexNumber):
return ComplexNumber(self.real + other.real, self.imag +
other.imag)
ST
else:
raise TypeError("Can only add another ComplexNumber")
R

c1 = ComplexNumber(2, 3)
c2 = ComplexNumber(1, 1)
ht

print(c1) # calls __str__: "2 + 3j"


print(repr(c1)) # calls __repr__: "ComplexNumber(2, 3)"
c3 = c1 + c2 # calls __add__: ComplexNumber(3, 4)
ig

In this example, we create a ComplexNumber class that represents a complex number, and
yr

define the __str__, __repr__, and __add__ methods to provide string representation and
addition functionality.
op

8.4.3 Real-World Example


C

Let's consider a real-world example of a Library Management System. We'll define a Book
class to manage book entities. We will also use special methods to define some behavior for
our Book class:

class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
self.is_issued = False # Whether the book is issued to a

© Copyright RSTForum. Sharing of this material is illegal.


140
borrower or not

def __str__(self):
return f"'{self.title}' by {self.author}"

def __len__(self):
return self.pages

def __add__(self, other):


if isinstance(other, Book):
return self.pages + other.pages

.
else:

m
raise TypeError("Can only add another Book instance")

ru
def issue(self):
if not self.is_issued:
self.is_issued = True

Fo
else:
raise ValueError(f"'{self.title}' is already issued to a
borrower")
ST
def return_book(self):
if self.is_issued:
R

self.is_issued = False
else:
raise ValueError(f"'{self.title}' is not issued")
ht

book1 = Book("1984", "George Orwell", 328)


book2 = Book("To Kill a Mockingbird", "Harper Lee", 281)
ig

# The __str__ method provides a user-friendly string representation of


yr

the book
print(book1) # '1984' by George Orwell
op

# The __len__ method provides the length (number of pages) of the book
print(len(book1)) # 328
C

# The __add__ method allows adding two book objects which returns the
total pages
print(book1 + book2) # 609

# Issue a book
book1.issue()

# Try to issue it again (will raise an error because the book is already
issued)

© Copyright RSTForum. Sharing of this material is illegal.


141
try:
book1.issue()
except ValueError as e:
print(e) # '1984' is already issued to a borrower

# Return the book


book1.return_book()

In this system, each Book object represents a book in a library. The issue and return_book
methods represent a book being issued to a borrower or returned to the library, respectively.
We also define the __str__, __len__, and __add__ special methods to allow for intuitive

.
m
interaction with our Book objects.

ru
8.6 Working with Class and Static Methods

Fo
In Python, methods inside a class are by default instance methods, meaning that they are
tied to the instance of the class and can access instance-specific attributes and methods.
However, there are two additional types of methods: class methods and static methods.
These methods are not bound to an instance, but instead to the class or none at all.
ST
8.6.1 Understanding @classmethod
The @classmethod decorator can be applied to a method within a class to make it a class
R

method. A class method is bound to the class and not the instance. This means it can't
access or modify instance-specific attributes, but it can access or modify class attributes.
ht

A class method's first parameter is not self (the instance), but cls (the class).
ig

class MyClass:
yr

class_attribute = 10

@classmethod
op

def modify_class_attribute(cls, new_value):


cls.class_attribute = new_value
C

MyClass.modify_class_attribute(20)
print(MyClass.class_attribute) # Output: 20

In this example, modify_class_attribute is a class method that can modify the class
attribute class_attribute.

8.6.2 Understanding @staticmethod


The @staticmethod decorator can be applied to a method within a class to make it a static
method. A static method is not bound to either the class or the instance. It can't modify or

© Copyright RSTForum. Sharing of this material is illegal.


142
access instance-specific or class-specific attributes. It's just like a normal function, but it lives
inside the class namespace. It's typically used for utility functions that don't need to access
any data from instances or the class.

class MyClass:
@staticmethod
def my_utility_method(a, b):
return a * b

result = MyClass.my_utility_method(5, 6)
print(result) # Output: 30

.
m
In this example, my_utility_method is a static method that doesn't access any instance or
class data.

ru
8.6.3 Differences and use-cases for class and static methods

Fo
● Use instance methods for most general use-cases, as they can access and modify
instance data.
ST
● Use class methods when you want to provide a method that's tied to the class, but
not any particular instance. This is often useful for factory methods, which create an
instance of a class, because the method can't be tied to any particular instance if it's
being used to create one.
R

● Use static methods as utility functions that don't depend on any class or instance
data.
ht

These three types of methods provide a great deal of flexibility and control over how you
design your classes in Python. By understanding when to use each, you can write cleaner,
ig

more efficient, and more intuitive code.


yr

8.6.4 Real-World Example


Let's build upon the library example from before. We'll add more functionality to our Book
op

class, and also introduce a Library class, which will keep track of the books it contains. This
Library class will make use of instance methods, class methods, and static methods.
C

class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
self.is_issued = False

def __str__(self):
return f"'{self.title}' by {self.author}"

© Copyright RSTForum. Sharing of this material is illegal.


143
def __len__(self):
return self.pages

def __add__(self, other):


if isinstance(other, Book):
return self.pages + other.pages
else:
raise TypeError("Can only add another Book instance")

def issue(self):

.
if not self.is_issued:

m
self.is_issued = True
else:

ru
raise ValueError(f"'{self.title}' is already issued to a
borrower")

Fo
def return_book(self):
if self.is_issued:
self.is_issued = False
ST
else:
raise ValueError(f"'{self.title}' is not issued")
R

class Library:
def __init__(self):
ht

self.books = []

def add_book(self, book):


ig

if isinstance(book, Book):
self.books.append(book)
yr

else:
raise TypeError("Can only add a Book instance")
op

def issue_book(self, book):


if book in self.books and not book.is_issued:
C

book.issue()
else:
raise ValueError("Book not available for issuing")

@classmethod
def with_books(cls, books):
library = cls()
for book in books:
library.add_book(book)
return library

© Copyright RSTForum. Sharing of this material is illegal.


144
@staticmethod
def is_book_object(book):
return isinstance(book, Book)

def total_pages_in_library(self):
return sum(len(book) for book in self.books)

# Create some books


book1 = Book("1984", "George Orwell", 328)

.
book2 = Book("To Kill a Mockingbird", "Harper Lee", 281)

m
# Create a library with books

ru
library = Library.with_books([book1, book2])

# Issue a book

Fo
library.issue_book(book1)

# Check if an object is a book using the static method


ST
print(Library.is_book_object(book1)) # True
print(Library.is_book_object("1984")) # False
R

# Check the total pages in the library


print(library.total_pages_in_library()) # 609
ht

This example builds a simple Library Management System where we can add books to the
library, issue books, and also calculate the total number of pages in the library. It uses
ig

instance methods, class methods, and static methods in a way that makes sense for their
purpose and functionality. The class method with_books is used as a factory method to
create a new library with a list of books. The static method is_book_object is used as a
yr

utility function to check if a given object is a book.


op

8.6.4.1 isinstance() function


The isinstance() function in Python is a built-in function that checks if the specified
object is of the specified type, or if the object is an instance of a subclass of the specified
C

type.

In the form isinstance(object, classinfo), the function returns True if the object
argument is an instance of the classinfo argument, or of a (direct, indirect, or virtual)
subclass thereof. If object is not an object of the given type, the function returns False.

If classinfo is a tuple of type objects (or recursively, other such tuples), return True if
object is an instance of any of the types. If classinfo is not a type or tuple of types and such
tuples, a TypeError exception is raised.

© Copyright RSTForum. Sharing of this material is illegal.


145
Here is a basic example of isinstance() in action:

class Fruit:
pass

class Apple(Fruit):
pass

a = Apple()

print(isinstance(a, Apple)) # Returns: True

.
print(isinstance(a, Fruit)) # Returns: True because Apple is a subclass

m
of Fruit
print(isinstance(a, str)) # Returns: False

ru
In the context of our Library Management System, we used isinstance() to check if an

Fo
object was an instance of the Book class before adding it to the library or issuing it. This is a
way of using Python's dynamic typing to our advantage, while still making sure that we're
working with the kind of objects we expect.
ST
8.7 Python's Built-In OOP Features
Python provides several built-in functions to work with objects and classes. These functions
R

make it easier to inspect and manipulate objects in your program. In this section, we'll cover
the following functions:
ht

● isinstance
● issubclass
ig

● hasattr
● getattr
yr

● setattr
● delattr
op

8.8.1 The isinstance function


The isinstance function is used to check if an object is an instance of a class or a subclass
C

thereof. Its syntax is as follows:

isinstance(object, classinfo)

Here, object is the object that you want to check, and classinfo is a class, a type, or a tuple
of classes and types.

The isinstance function returns True if the object is an instance of the class or one of its
subclasses, and False otherwise.

© Copyright RSTForum. Sharing of this material is illegal.


146
Let's see isinstance in action:

class Fruit:
pass

class Apple(Fruit):
pass

apple = Apple()

print(isinstance(apple, Apple)) # True

.
print(isinstance(apple, Fruit)) # True

m
print(isinstance(apple, object)) # True

ru
As you can see, isinstance can help us confirm the class of an object, including its
inheritance hierarchy.

Fo
8.7.2 The issubclass function
The issubclass function is used to check if a class is a subclass of another class. Its syntax
ST
is as follows:

issubclass(class, classinfo)
R

Here, class is the class that you want to check, and classinfo is a class, a type, or a
tuple of classes and types.
ht

The issubclass function returns True if class is a subclass of classinfo, and False
ig

otherwise.
yr

Let's see issubclass in action:


op

class Fruit:
pass
C

class Apple(Fruit):
pass

print(issubclass(Apple, Fruit)) # True


print(issubclass(Fruit, Apple)) # False
print(issubclass(Apple, object)) # True

As you can see, issubclass can help us confirm the inheritance relationship between two
classes.

© Copyright RSTForum. Sharing of this material is illegal.


147
8.7.3 The hasattr, getattr, setattr, and delattr functions
The hasattr, getattr, setattr, and delattr functions are used to work with the
attributes of an object.

The hasattr function checks if an object has a given attribute, getattr gets the value of a
given attribute, setattr sets the value of a given attribute, and delattr deletes a given
attribute.

Let's see these functions in action:

.
class Fruit:

m
def __init__(self, color):
self.color = color

ru
apple = Fruit('red')

Fo
# hasattr
print(hasattr(apple, 'color')) # True
print(hasattr(apple, 'taste')) # False
ST
# getattr
print(getattr(apple, 'color')) # 'red'
# print(getattr(apple, 'taste')) # Raises AttributeError
R

# setattr
setattr(apple, 'color', 'green')
ht

print(apple.color) # 'green'
ig

setattr(apple, 'taste', 'sweet')


print(apple.taste) # 'sweet'
yr

# delattr
delattr(apple, 'taste')
op

# print(apple.taste) # Raises AttributeError


C

8.7.4 Real-World Example


Here's a real-world program that makes use of isinstance, issubclass, hasattr,
getattr, setattr, and delattr. We'll simulate a simple school system.

class Person:
def __init__(self, name, age):
self.name = name

© Copyright RSTForum. Sharing of this material is illegal.


148
self.age = age

class Teacher(Person):
def __init__(self, name, age, subject):
super().__init__(name, age)
self.subject = subject

class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self.grade = grade

.
m
def person_details(person):
print(f"Name: {person.name}")

ru
print(f"Age: {person.age}")

# Check if the person object has attribute subject or grade

Fo
if hasattr(person, 'subject'):
print(f"Subject: {getattr(person, 'subject')}")
elif hasattr(person, 'grade'):
ST
print(f"Grade: {getattr(person, 'grade')}")

# Let's change person's age and print updated details


R

setattr(person, 'age', getattr(person, 'age') + 1)


print(f"Updated Age: {person.age}")
ht

# Create instances
teacher = Teacher("John Doe", 40, "Mathematics")
student = Student("Jane Doe", 15, "10th")
ig

# Check instance and class relationship


yr

print(isinstance(teacher, Teacher)) # True


print(isinstance(student, Student)) # True
op

print(issubclass(Teacher, Person)) # True


print(issubclass(Student, Person)) # True
C

# Display details
person_details(teacher)
print("----------------")
person_details(student)

# Remove attribute 'subject' from teacher


delattr(teacher, 'subject')
print(hasattr(teacher, 'subject')) # False

In this script:

© Copyright RSTForum. Sharing of this material is illegal.


149
● We've defined classes Person, Teacher, and Student. Teacher and Student
classes inherit from the Person class.
● We've defined a function person_details that accepts a person object and uses
hasattr, getattr, and setattr to display and manipulate person's details.
● We've created teacher and student instances and used isinstance and
issubclass to check their relationships.
● We've used delattr to delete the subject attribute from the teacher object.

.
m
ru
Fo
ST
R
ht
ig
yr
op
C

© Copyright RSTForum. Sharing of this material is illegal.


150

You might also like