Python 1
Python 1
Python 1
Bemnet Girma
Fun-damentals of
PYTHON
PROGRAMMING
Gateway for the Joy of Programming
Fun-damentals of
PYTHON
PROGRAMMING
Gateway for the Joy of Programming
Contacts
bemnet.dev@gmail.com
https://www.linkedin.com/in/bemnetdev/
The author and the publisher have made every effort to contact
copyright holders for material used in this book. Any person or
organisation that may have been overlooked should contact the
author and they will be glad to rectify in future editions any errors or
omissions brought to their attention.
INTRODUCTION X
03. VARIABLES 12
05. OPERATORS 36
07. FUNCTION 65
08. STRING 95
Computer programming used to solve problems. However It is still taught as boring theory and most
beginners fails to learn then they hate it. Here, I tried to fluid the boring theory. This is my humble
attempt to help the world, by pushing you to love programming.
Why Python?
Python is an easy-to-learn programming language that has some really useful features for a beginner.
The code is quite easy to read when compared to other programming languages, and you can solve and
make almost anything with it.
Have Fun!
Think programming as a way to create some fun games or playing puzzles with your friends. Learning
to program is a wonderful mental exercise and the results can be very rewarding. But most of all,
whatever you do, have fun!
●● ●●
●●●●●●●
●●●●●●●
●●●●●
●●●
●
Bemnet
No content here - this page is intentionally blank.
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER ONE
Get Started
Objectives
What is programming?
What is programming language?
How computers understand a programming language?
How to write and run a code?
Computers are dumb. Computers are only smart because we program them to be.
What is Programming?
Programming is the process of preparing an instructional program for a device to do some task
without making mistakes.
There are two types of languages for communication between a computer and a programmer
(human).
1. Machine language: which is a binary code (series of 0s and 1s) and computers understood it and
it is difficult for humans to understand.
2. Programming language: which is a source code and humans understood it and computers could
not.
A programming language is a formal language, which includes a set of instructions that helps a
programmer to communicate or interact with a computer.
Page 1
Programming Language is classified into two categories, based on the level (Degree) of abstraction
and gap between source code and machine code.
1. Source code is any collection of code, written using a human-readable programming language,
usually as plain text.
2. Machine code is a computer program written in machine language instructions that can be
executed directly by a computer's control unit.
High level programming languages are those which are programmer friendly. Humans can easily
understand it which helps in easy maintaining and debugging of the code.
Low level programming languages are those which are machine friendly. Humans can’t understand
such languages. In other words, low level languages are not human readable.
What is Compiler?
A compiler is a computer program that translates source code written in one programming language
(the source language) into another language (the target language) to create an executable program.
What is Interpreter?
An interpreter is a computer program that directly executes instructions written in a programming
language, without requiring them previously to have been compiled into a machine language
program.
Compiler Vs Interpreter
All the programming languages are converted to machine understandable language for execution.
The conversion is taken care of by compilers and interpreters.
A compiler takes the source code and converts it into machine executable code at once. The
processor takes the executable and executes it. The languages which use a compiler are called
compiled languages. Compiled languages are faster and more efficient comparatively.
Page 2
Examples – Java, C++
An interpreter is one which runs the code line by line and executes instruction by instruction. The
languages which use interpreters are called Interpreted languages. Such languages are slower in
terms of execution and less efficient.
Suppose you want to watch an Italian movie, but you don't understand the Italian language.
However, you can understand English. You have two options to watch the movie. The first way is to
watch an English dubbed version of the movie, if available. The second way is to watch the Italian
movie with English subtitles. In the second way, the subtitles are displayed scene by scene
separately, whereas in the first way, all the scenes are converted to English. We can compare the
first scenario with a compiler and the second one with an interpreter.
What is IDE?
IDE (Integrated Development Environment) is a place (graphic interface) to write, run, and debug
(check errors) code and also convert your source code to machine code.
Page 3
How to run (execute) a code?
You can’t simply type rubbish in an IDE, convert it to machine code and expect the computer to
understand it. Each programming language has its own set of rules (Grammar) you must follow
within an IDE called Syntax.
What is Syntax?
Syntax is set of rules you must follow to run your program correctly. Syntax for each programming
language is unique.
Example:
Mens clothes are cheap.
Men’s clothes are cheap
Key Takeaways
Page 4
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER TWO
Hello Python
Objectives
What is Python?
Why we study Python?
What are the key features of Python?
What are applications of Python?
How to install jupyter notebook?
To better communicate with a computer you should have to learn a programming language, Even
though you have translators like compiler and interpreter. But which programming language? The
answer would be simple, used for different / multiple purposes, i.e. Python.
What is Python?
Python is simple, general purpose, dynamic, object oriented, interpreted as well as compiled, high-
level programming language.
In details Python is
Page 6
Why the name Python?
There was a TV show by the name Monty Python’s Flying Circus which was a very much popular
fun show in the 1970’s. While creating Python, Guido also used to read this show’s published scripts.
Guido needed a short and a different name for this language, hence he named it “Python”.
Python Versions
PS. Python 3 won’t provide backward compatibility to Python2 i.e. there is no guarantee that
Python2 programs will run in Python3.
Features of Python
Simple - Python syntax is very easy. Developing and understanding python is very easy than
others. The below comparison illustrated how simple python language is when compared to
other languages.
# include <stdio.h>
int main()
{
printf("Hello World")
return 0
}
print("Hello World")
Open Source - We can download freely and customize the code as well
Platform independent - Python programs are not dependent on any specific operating
systems. We can run on all operating systems happily.
Portable - If a program gives the same result on any platform then it is a portable program.
Python used to give the same result on any platform.
Huge library - Python has a big library to fulfil the requirements.
Database connectivity - Python provides interfaces to connect with all major databases like,
oracle, MySQL.
Page 7
Lesson Two : Applications of Python
Python is a programming language that does it all, from web applications to video-games, Data
Science, Machine Learning, real-time applications to embedded applications, and so much more. In
this lesson, we’ll take a deeper dive into a broader list of applications of Python out in the wild.
1. Web Development
I hope you are familiar with what web development is. Python is used to develop fully functional
website using web development frameworks like Flask and Django. Using Python for web
development also offers several other benefits, such as security, easy scalability, and convenience in
the development process.
2. Game Development
Just like web development, Python comes equipped with an arsenal of tools and libraries for 2D, 3D
and video game development like PyGame.
5. Image Processing
Due to the ever-increasing use of Machine Learning, the role of image (pre)processing tools has also
skyrocketed. To fulfill this demand, Python offers a host of libraries that are useful for multiple
applications like face recognition & image detection. Some of the popular image processing Python
libraries include OpenCV and Python Imaging Library(PIL).
6. Text Processing
Text Processing is among the most common uses of Python. Text Processing allows you to handle
enormous volumes of text while giving you the flexibility to structure it as you wish. Do you ever
think how facebook detects hate speech posts and comments? Well, that has done with Python’s text
processing capabilities.
Page 8
7. Audio and Video Applications
When it comes to working with audio and video files, python is fully equipped with tools and
libraries to accomplish your task. Tasks such as basic signal processing, creative audio manipulation,
audio recognition, and more can be easily handled by libraries like Pyo, pyAudioAnalysis, Dejavu,
and many other libraries like it.
As for the video part, Python offers several libraries, such as Scikit-video, OpenCV, and SciPy, that
can help you manipulate and prepare videos for use in other applications. Popular audio & video
streaming applications like Spotify, Netflix, and YouTube are written in Python.
The Python ecosystem offers several libraries that can help you tackle your Data Science problems
head-on. We have Matplotlib and Seaborn as the most widely used data visualization tools.
Conclusion
Python is an extremely robust and versatile programming language that is rapidly gaining popularity
among developers from various sectors. Its ability to be deployed into virtually any domain is
remarkable, thanks to its vast ecosystem of diverse libraries.
Page 9
Lesson Three : Python Installation
Python IDEs are software applications that provide tools and features to facilitate coding in Python.
They offer features like code writing, execution, debugging, making the development process more
efficient.
Jupyter Notebook
Jupyter Notebook is an open source web application that you can use to create and share live code. It
is a popular IDE for data science and machine learning tasks.
print("Hello World")
Page 10
Finally you will get an output ‘Hello World’ on next line to your code Else you made a
mistake, so recheck it once again.
1 print("Hello World")
Hello World
Key Takeaways
Python is a high-level programming language known for its simplicity and readability.
We study Python because it is widely used, has a large community support, and offers
numerous applications in various domains.
Python was created by Guido van Rossum, and it was first released in 1991.
Key features of Python include its easy-to-learn syntax, open source, extensive standard
library, portable and platform independent.
Python has a wide range of applications, including web & App development, data analysis,
machine learning, scientific computing, automation, and scripting, among others.
Jupyter Notebook is a popular IDE for data science and machine learning tasks.
Page 11
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER THREE
Variables
Objectives
What is a variable?
What are the properties of a variable?
How can we create and use variables in Python?
What is keyword?
What operations can be performed on variables?
What is Variable?
Variable is the name which we give to the memory location which holds some data. With a variable we can
store the data, access the data and also manipulate the data.
To summarize, a variable is a
Name
Refers to a value
Hold some data
Name of a memory location
Let us consider librarians, how could they storeand access ton of books? They just make catalogue of
books based on their genre with their reference location. That is how variables also works.
Page 12
Properties of a Variable
1. Type:
Each data have a type whether it is number word or something and each variable should belong to one of the
data types. This is called the data type of the variable.
2. Scope:
In any programming language, scope refers to the place or limit or boundaries or the part of the program
within which the variable is accessible.
3. Value:
Each and every variable in a program holds value of some type which can be accessed or modified during the
due flow of the program.
4. Location:
As already stated, the data is stored in memory location. The variable is the name which we give to that
location. Each memory location has some address associated with it.
5. Lifetime:
The lifetime of a variable refers to the time period for which the memory location associated with the variable
stores the data.
name_of_the_variable = value
1 age = 21
Page 13
How can I look for my variables?
To see your variable use print() function
print(name_of_the_variable)
1 print(age)
21
PS. Don’t worry we will discuss more about function later in Function Chapter.
1 print("I am John")
I am John
My age is 21
Page 14
EXERCISE 3.1
Create a variable "date" and store today's date then print it?
Today's date is 6
What if we want to submit value of a variable outside our code like questionnaire?
Note: We can print meaningful text messages along with variables for better understanding.
EXERCISE 3.2
Create a variable "bd" and take input birth date from user then print it?
Your birthdate is 6
Page 15
.
1 17 = age
1 _age = 23
2 print(_age)
23
1 1dollar = 76
Page 16
3. cannot use any special symbol
1 $dollar = 74
1 My Age = 24
PS. Case sensitive means you can’t use lowercase letters in place of uppercase and vice versa.
1 age = 21
2 print(Age)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 2
1 age = 21
----> 2 print(Age)
6. cannot be a keyword.
Page 17
Lesson Two : Keywords
What is keyword?
Keywords are special reserved words, that have specific meanings and purposes.
All 33 keywords in python contain only alphabet symbols. All of them are in lower case except True, False,
and None.
1 import keyword
2 keyword.kwlist
['False',
'None',
'True',
'and',
'as',
'assert',
'async',
'await',
'break',
'class',
'continue',
'def',
'del',
'elif',
'else',
'except',
'finally',
'for',
'from',
'global',
'if',
'import',
'in',
'is',
'lambda',
'nonlocal',
'not',
'or',
'pass',
'raise',
'return',
'try',
'while',
'with',
'yield']
PS. You cannot use these keywords as a variable, else will result in error.
Page 18
Ex. 3.12 ( Creating a variable with keyword name )
1 class = 4
24 9 4327
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[17], line 1
----> 1 Sid, age, grade = 4327, 24
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[18], line 1
----> 1 Sid, age = 4327, 24, 9
Page 19
Single Value for multiple Variables
We can assign a single value to multiple variables simultaneously.
10 10 10
you can get Memory location of a variable using the syntax below:
id(variable_name)
PS. For sake of simplicity, from now onward MA means Memory Address of a variable.
1 dollar = 69
2 print("1$ = ",dollar)
3 print("MA of dollar:",id(dollar))
1$ = 69
MA of dollar: 140719801867176
2. Reassigning
you can update / reassign value of a variable using the syntax below:
variable_name = new_value
Page 20
Ex. 3.18 ( Updating the value of variable )
1 dollar = 69
2 print("In 2019, $1 =",dollar)
3 print("MA of dollar in 2019:",id(dollar))
4 dollar = 72
5 print("In 2020, $1 = ",dollar)
6 print("MA of dollar in 2020:",id(dollar))
In 2019, $1 = 69
MA of dollar in 2019: 140719801867176
In 2020, $1 = 72
MA of dollar in 2020: 140719801867272
3. Deleting
del variable_name
1 book = 5
2 del book
3 print(book)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[22], line 3
1 book = 5
2 del book
----> 3 print(book)
Page 21
EXERCISE 3.3
Create a variable "ap" and accept "apple price" from user, then print user’s apple price
“ap” and its memory location, then next reassign apple price to 34, again print apple
price and its memory location, finally delete variable "ap"?
Key Takeaways
Variable is the name which we give to the memory location which holds some data.
Type, Scope, Value, Location and Lifetime are properties of a variable.
print() is a function that can print the specified message to your computer screen.
input() is a function that can accept values from a user (you).
Keywords are special reserved words, that have specific meanings and purposes.
Checking memory location, reassigning and deleting are operations you can perform on variables.
Page 22
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER FOUR
Data Types
Objectives
All programming languages aim is to create some data then do some actions / operations on the data, i.e.
processing data. The data can be categorized into different types. Categorizing the data is important in order
to perform the operations on it. That classification, which states the type of data stored in the variable is called
data type.
Generally based on their creations data types can be classified into two types:
1. User defined data types: Data types which are created by programmer (you), example is class, module,
array etc.
2. Built-in data types: Data types which are already available in python.
Page 23
None
Bool / booleans
Numeric types
Int
Float
Complex
Sequences / Collections
list
tuple
set
dict
str
variable_name = None
type(variable_name)
1 box = None
2 print("The Box is",box)
3 print(type(box))
Page 24
What if we want to store facts (True / False) values?
1 a = True
2 b = False
3 print("Gravity = 9.81",a)
4 print("1 + 2 = 5 is",b)
5 print(type(a))
6 print(type(b))
EXERCISE 4.1
Create a variable "gf" and print any general fact and its data type?
1 Sid = 16784
2 print("My student id is",Sid)
3 print(type(Sid))
My student id is 16784
<class 'int'>
Page 25
EXERCISE 4.2
Create a variable "s" and store number of subjects you are taking on this semester then
print it and its data type?
1 grade = 9.74
2 print("My grade is",grade)
3 print(type(grade))
My grade is 9.74
<class 'float'>
EXERCISE 4.3
Create a variable "T" and store current temperature then print it and its data type?
1 a = 3 + 6j
2 b = 2 - 5.5j
3 c = 2.4 + 7j
4 print(a, b, c)
5 print(type(a))
Page 26
(3+6j) (2-5.5j) (2.4+7j)
<class 'complex'>
Sequences in python are objects that can store a group of values. The below data types are called sequences.
String
List
Tuple
Set
Dictionary
1 name = 'John'
2 print("My name is",name)
3 print(type(name))
My name is John
<class 'str'>
Page 27
What if there is both apostrophe and double quote in a string?
EXERCISE 4.4
Create a variable "n", "s", "q" and store your name, your favorite song and your
favorite quote respectively. then print it?
What if we want to describe our code with title, author, date and moreover about our code?
What is comment?
Comment is a programmer-readable explanation or annotation in the source code.
Hello World
Page 28
EXERCISE 4.5
Write any python code that you have learned before then describe your code by
✓ Coder name
✓ Date
✓ Place
name_of_list = [element,...]
EXERCISE 4.6
Create a list of your favorite subjects then print it and its data type?
Page 29
3. Tuple data type
We can create tuple data structure by using parenthesis (). A tuple can store different data types. tuple is
immutable.
name_of_tuple = (element,...)
EXERCISE 4.7
Create a tuple of days in a week then print it and its data type?
name_of_set = {element,...}
Create a set of your favorite books then print it and its data type?
What if we want to pair of related elements ( for example pair of Athlete’s name with their rank )?
name_of_dictionary = {key:value,...}
EXERCISE 4.9
Create a football player and jersey pair of dictionary then print it and its data type?
Based on requirements, developers/programmers can convert from one data type into another data type
explicitly, this is called type conversion. Python provides the following inbuilt functions to convert from one
type to another type.
1. Convert to oat
Ex 4.14 ( Convert to float data type )
1 i = 65
2 itf = float(i) #Integer to float
3 print(itf)
4 print(type(itf))
65.0
<class 'float'>
2. Convert to integer
Ex 4.15 ( Convert float to integer data type )
1 f = 65.89
2 fti = int(f) #float to Int
3 print(fti)
4 print(type(fti))
65
<class 'int'>
1 st = '123'
2 sti = int(st, 10) #Str(No.) to Int
3 print(sti)
4 print(type(sti))
123
<class 'int'>
Page 32
65
<class 'int'>
3. Convert to complex
Ex 4.18 ( Convert Real No. to complex data type )
(6+0j)
<class 'complex'>
4. Convert to string
Ex 4.19 ( Convert integer to string data type )
1 i = 65
2 itst = str(i) #Int to Str
3 print(itst)
4 print(type(itst))
Page 33
65
<class 'str'>
A
<class 'str'>
5. Convert to list
Ex 4.21 ( Convert Tuple to List data type )
6. Convert to tuple
Ex 4.23 ( Convert List to Tuple data type )
Page 34
Ex 4.24 ( Convert Set to Tuple data type )
7. Convert to set
Ex 4.25 ( Convert to Set data type )
Key Takeaways
Page 35
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER FIVE
Operators
Objectives
What is an operator?
Which operators you can use in Python?
What is Assignment Operator?
What are Arithmetic Operators?
What is Compound Operator?
What are Relational Operators?
What is Identity Operator?
Computer is a device that can accept input data from a user and process the given data to produce a desired
output. Nevertheless processing data means doing some sort of calculations on the given inputs to give output
back to the user. Programming is more than storing data in a variable, operators allow us to do exciting things
with the data.
What is an operator?
An operator is a symbol which is applied on some operands (usually variables), to perform certain action or
operation. For example,
Page 36
In the above example, first we assigned values to two variables ‘a’ and ‘b’ and then we added both the
variables and stored the result in variable ‘c’.
Note: The symbols + and = are called operators and the variables a,b,c on which operation is being performed
are called operands.
For example, in ‘-5’ the operator ‘-’ is used to make the (single) operand ‘5’ a negative value.
2. Binary Operator – If the operator acts on two operands then it’s called a binary operator.
For example, ‘+’ operators need two variables (operands) to perform addition operation.
3. Ternary Operator – If the operator acts on three operands then it’s called a ternary operator.
PS. Don’t panic, We will see more in detail on upcoming chapters (if … else Statement).
What if we want to make a positive number negative? Yes we can, How? Let us see…
1 a = 10
2 print(a)
3 print(-a)
10
-10
Earlier, When we discuss about creating a variable we have used ‘=’ let us recall
age = 21
What is ‘=’ ?
Syntax :
new_variable = old_variable
PS. Memory Address of both new (copied) and old variables is unique.
1 v = 10
2 c = v
3 print("Old variable is", v)
4 print("Copied variable is", c)
5 print("Memory Address of Old variable:", id(v))
6 print("Memory Address of Copy variable", id(c))
Old variable is 10
Copied variable is 10
Memory Address of Old variable: 137772376572432
Memory Address of Copy variable 137772376572432
Page 38
EXERCISE 5.1
Create a string variable "name" and store your name then copy it to a "new" variable,
after that print both variables and their memory location?
What if we want to add two numbers? Yes we can, How? Let us see…
Note:
Division operator / always performs floating point arithmetic, so it returns float value.
Floor division (//) can perform both floating point and integral as well,
If values are int type, then result is int type.
If at least one value is float type, then the result is of float type.
1 a = 20
2 b = 12
3 print(a + b) #Addition
4 print(a - b) #Subtraction
5 print(a / b) #Division
6 print(a // b) #Quotient
7 print(a % b) #Remainder
8 print(a * b) #Multiplication
9 print(a ** b) #Square
10 print(a - b + 3 * 4 / 3) #BODMAS
32
8
1.6666666666666667
1
8
240
4096000000000000
12.0
Page 39
EXERCISE 5.2
Create two integer variables "a" and "b" accept values from a user then calculate their
average?
What if we want perform complex calculations like logarithm, trigonometric, exponential etc…?
math() Function
2.302585092994046
1.0
0.8939966636005579
1.5707963267948966
1.0
8.0
7.38905609893065
4.0
120
5
4
2.718281828459045
3.141592653589793
Page 40
EXERCISE 5.3
Calculate
■ ln(e)
■ cos(90°)
■ 10 the power of 5
What if we want to increase value of a variable? Yes we can, How? Let us see
1 balance = 12345
2 print("Balance before deposit:",balance)
3 deposit = 2655
4 balance = balance + deposit
5 print("Balance after deposit:",balance)
Why we write a variable twice? We can write it only once, How? Let us see…
Page 41
balance = balance + deposit is same as balance += deposit
That means add "balance" and "deposit" then store the result in variable "balance".
1 balance = 12345
2 print("Balance before deposit:",balance)
3 deposit = 2655
4 balance += deposit
5 print("Balance after deposit:",balance)
1 a, b = 2, 3
2 a+=b #Addition Assignment
3 print(a)
4 a-=b #Subtraction Assignment
5 print(a)
6 a*=b #Multiplication Assignment
7 print(a)
8 a//=b #Quotient Assignment
9 print(a)
10 a%=b #Remainder Assignment
11 print(a)
12 a**=b #Square Assignment
13 print(a)
5
2
6
2
2
8
EXERCISE 5.4
Create two integer variables "avg" and "b" accept from user then calculate their average
using compound operators?
Page 42
What if we want to compare two numbers or variables?
These are used to compare two values for some relation and return booleans (True or False) depending the
relation.
1 print(1 == 2) #Equal
2 print(1 != 2) #Not Equal
3 print(1 > 2) #Less Than
4 print(1 < 2) #Greater Than
5 print(1 <= 2) #Less Than Or Equal
6 print(1 >= 2) #Greater Than Or Equal
False
True
False
True
True
False
EXERCISE 5.5
Create two variables "my_age" and "friend_age" accept from user then compare them?
Page 43
Lesson Six : Identity Operators
Recall that : The memory location of the object can be seen using id() function.
1. is:
2. is not:
A is not B returns True, if both A and B are not pointing to the same object.
A is not B returns False, if both A and B are pointing to the same object.
1 a, b, c = 25, 25, 30
2 print(a is b)
3 print(a is c)
4 print(id(a))
5 print(id(b))
6 print(id(c))
True
False
140719801865768
140719801865768
140719801865928
EXERCISE 5.6
Page 44
Note: Identity operators are not comparing values of objects. They compare memory address of objects. If we
want to compare value of objects, we should use relational operator ‘==’.
1 a = []
2 b = []
3 c = a
4 print(id(a))
5 print(id(b))
6 print(id(c))
7 print(a == b)
8 print(a is b)
9 print(a is c)
10 print(a == c)
2091128894208
2091128891264
2091128894208
True
False
True
True
Key Takeaways
Page 45
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER SIX
Conditional Statement
Objectives
Decision Making in programming is similar to decision making in real life. In programming, a certain block
of code needs to be executed when some condition is fulfilled.
Conditional /decision making/ Statements are statements executed based on the condition.
Python Interpreter execute sequentially when there is no condition around the statements. If you put some
condition for a block of statements, the execution flow may change based on the result evaluated by the
condition.
Page 46
There are four types of conditional statements in python. They are as follows:
1. if statement
2. if else statement
3. Nested if statement
4. if elif else statement
The if statement is used to test a specific condition. If the condition is true, if-block statement will be
executed.
The condition of if statement can be any valid logical expression which can be either evaluated to True or
False.
In Python, indentation is used to separate the if-block statement from other block. If two statements are at the
same indentation level, then they are the part of the same block.
Generally, four spaces are given to indent the statements which are a typical amount of indentation.
Page 47
What is Indentation?
Indentation is the spaces at the beginning of a code line to indicate a block of code.
Note: if statement contains an expression/condition. As per the syntax colon (:) is mandatory otherwise it
throws syntax error.
Condition gives the result as a bool type, either True or False. If the condition result is True, then if block
statements will be executed. If the condition result is False, then next line of code execute.
Suppose you want hire employees for your company and your main condition is employee’s age should be
above 18 because hiring under age is prohibited. let us develop a code to filter job applicants.
Ex 6.1 ( if statement )
EXERCISE 6.1
Create a variable "age" and take input from user then check vote eligibility (age > 18)?
What if you want to reject applicants who could not fulfill the age condition?
Page 48
Lesson Three : if else statement
If the condition result is True, then if block statements will be executed. If the condition result is False, then
else block statements will be executed.
Page 49
EXERCISE 6.2
Create a variable "username" and its value is your name then create log in conditional
statement based on username?
john
Welcome to facebook.
Here is a problem, What if a 90 years old man applied for the job, will you accept him? Hell No
In python, there are three types of logical operators. They are and, or, not. These operators are used to
construct compound conditions, combinations of more than one simple condition. Each simple condition
gives a boolean value which is evaluated, to return final boolean value.
Note: In logical operators, False indicates 0(zero) and True indicates non-zero value. Logical operators on
boolean types
and : If both the arguments are True then only the result is True
or : If at least one argument is True then the result is True
not : complement of the boolean value
Page 50
Ex 6.4 ( Logical operators on boolean types )
1 a, b = True, False
2
3 print(a and b) # and
4 print(a or b) # or
5 print(not a) # not
False
True
False
EXERCISE 6.3
Create two variable and "nationality" and "cgpa" and store values is your name and
nationality, then create scholarship conditional statement based on nationality and
cgpa?
Indian
8.7
Page 51
What if you have more additional condition like ( Applicant should have GPA above than 9 else he/she will
be in waiting list ) ?
Nested if statement is an if statement inside another if statement. Here, a user can decide among multiple
options based on multiple conditions.
Page 52
Ex 6.6 ( Nested if statement )
EXERCISE 6.4
Create two variable "username" and "password" and store values is your name and
password, then create log in conditional statement based on username and password?
Welcome to facebook.
Now, you couldn’t get a person who have GPA more than 9, and the job vacancy is urgent, so you need to
reduce GPA criteria to lower range.
The conditions are evaluated in the written order. If one condition becomes True then the set of statements
associated with that particular condition are executed and the execution comes out without checking other
conditions.
Page 53
Syntax for if elif else statement:
if (condition):
if block statement
elif:
elif block statement
else:
else block statement
next line of code
Page 54
EXERCISE 6.5
Create a variable "score" and take input from user, then classify them based on their
score?
Classification:
"A" – 90 to 100
"B" – 80 to 90
"C" – 70 to 80
"D" – 60 to 70
"F" – below 60
What if a and b are equal numbers. For example: (1, 1, 2) or (1, 2, 2) or (2, 1, 2) (2, 2, 2)
Page 56
Ex 6.12 ( Full Nested if statement )
Variable Swapping
Using third variable
Using Assignment operator
Using * and / operators
Using ^ ( XOR ) operator
1 a, b = 1, 2
2
3 print("Before Swap a=",a,"b=",b)
4 temp = a
5 a = b
6 b = temp
7 print("After Swap a=",a,"b=",b)
Before Swap a= 1 b= 2
After Swap a= 2 b= 1
Page 57
Ex 6.14 ( Using Assignment operator )
1 a, b = 1, 2
2
3 print("Before Swap a=",a,"b=",b)
4 a, b = b, a
5 print("After Swap a=",a,"b=",b)
Before Swap a= 1 b= 2
After Swap a= 2 b= 1
1 a, b = 1, 2
2
3 print("Before Swap a=",a,"b=",b)
4 a = a + b
5 b = a - b
6 print("After Swap a=",a,"b=",b)
Before Swap a= 1 b= 2
After Swap a= 3 b= 1
1 a, b = 1, 2
2
3 print("Before Swap a=",a,"b=",b)
4 a = a * b
5 b = a / b
6 a = a / b
7 print("After Swap a=",a,"b=",b)
Before Swap a= 1 b= 2
After Swap a= 2.0 b= 1.0
Page 58
Case Study : Bus Stop Problem
There are bus stops in a road each bus stop have its own number. Bus station (initial) number is 0. Each bus
stop number is double of previous bus stop number. Current bus stop number is 16,
What is the bus stop number before the current bus stop?
What is the bus stop number next to the current bus stop?
We can also do the previous Bus Stop Problem using another operator called Bitwise Operators. Let us
see…
Page 59
There are six bitwise operators, those are
Bitwise AND
Bitwise OR
Bitwise NOT
Bitwise XOR
Bitwise right shift
Bitwise left shift
1 a = 1
2 b = 2
3
4 print("Before Swap a=",a,"b=",b)
5 a = a ^ b
6 b = a ^ b
7 a = a ^ b
8 print("After Swap a=",a,"b=",b)
Before Swap a= 1 b= 2
After Swap a= 2 b= 1
Page 60
What if you want to search a keyword in a text?
1. in operator: The in operators returns True if element is found in the collection of sequences. returns False
if not found.
2. not in operator: The not in operator returns True if the element is not found in the collection of sequence.
returns False in found.
1 text = "Welcome"
2
3 print("Well" in text)
4 print("wel" in text)
5 print("Wel" in text)
6 print("come" not in text)
False
False
True
False
What if you want to check a person whether he/she is belong to class 10A or not?
False
True
What if a user just want to evaluate some calculation without using variables?
Page 61
Lesson Nine : eval() Function
This is an in-built function available in python, which takes the strings as an input. The strings which we pass
to it should, generally, be expressions. The eval() function takes the expression in the form of string and
evaluates it and returns the result.
1 eval('10 + 10')
20
EXERCISE 6.6
Create two integer variables "a" and "b" take input from a user, then calculate their
average by using eval() function?
Enter expression: 20 - 12 + 3 * 4 / 3
12.0
1 a = 5
2 eval('-a ')
-5
Page 62
Ex 6.25 ( eval() function /Relational Operator/ )
False
16
1 s = "John"
2 eval('"Jo" in s')
True
1 eval('1 is 2')
0.0
Page 63
EXERCISE 6.7
Calculate
■ ln(e)
■ cos(90°)
■ 10 the power of 5
Key Takeaways
Page 64
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER SEVEN
Function
Objectives
Let us understand this with an example. When you go to school in every morning, the things you do are
Page 65
Think of this sequence of steps to do morning to go to school. Now when your mom wakes you up for school,
she doesn’t need to explain all these steps each time to you. Whenever your mom says, “Get ready for
school”, it’s like making a function call. “Going to school‟ is an abstraction for all the above steps involved.
While writing coding logic, instead of writing like a plain text, it’s good to keep those coding statements in
one separate block, because whenever required then we can call these. If a group of statements is repeatedly
required, then it is not recommended to write these statements each and every time separately.
So, it’s good to define these statements in a separate block. After defining a function we can call directly if
required. This block of statements is called a function. Let us understand more by doing practically.
What is a Function?
Example: print() is predefined function in python which prints output on the desktop.
Types of functions
There are many categories based on which we can categorize the functions.
The functions which come installed along with python software are called predefined or built-in functions. We
have covered some inbuilt functions in examples of earlier chapters. Some of them are id(), type(),
input(), print() etc.
Page 66
User-defined functions
The functions which are defined by the developer as per the requirement are called as user defined functions.
In this chapter we shall concentrate on these kind of functions which are used defined.
Defining function
Calling function
1. Defining a function
def keyword – Every function in python should start with the keyword ‘def’. In other words, python
can understand the code as part of a function if it contains the ‘def’ keyword only.
PS. ‘def’ means define a function.
Name of the function – Every function should be given a name, which can later be used to call it.
Parenthesis – After the name ‘()’ parentheses are required
Parameters – The parameters, if any, should be included within the parenthesis.
Colon symbol ‘:’ should be mandatorilyplaced immediately after closing the parentheses.
Body of function – All the code that does some operation should go in the body of the function. The
body of the function should have indentation of one level with respect to the line containing the ‘def’
keyword.
Return value /statement/– Return statement should be in the body of the function. It’s not mandatory
to have a return statement.
1 # defining a function
2 def add():
3 a, b = 1, 2
4 c = a + b
5 return c
Note: After defining a function we can call the function using its name. While calling a function, we need to
pass the parameters if it has any.
Page 67
2. Calling a function
In the above example we defined a function with the name ‘add’ to add two nos. But when we execute the
above code, it will not display any output, because the function is not called. Hence, function calling is also
important along with function definition.
Note: When a function is called once then it will execute once, if called twice then it will be executed twice
and so on.
1 # calling function
2 add()
While calling the function, we have to call with the same name of the function which we used while defining
it, otherwise we will get an error.
1 # defining a function
2 def add():
3 a, b = 1, 2
4 c = a + b
5 return c
6
7 # calling function
8 two()
-------------------------------------------------------
--------------------
NameError Traceback
(most recent call last)
<ipython-input-8-e7cdd6ebe0b2> in <cell line: 2>()
1 # calling function
----> 2 two()
Page 68
EXERCISE 7.1
EXERCISE 7.2
1 # defining a function
2 def cal():
3 a, b = 3, 2
4 c = a + b
5 d = a - b
6 return c, d
7
8 # calling function
9 cal()
(5, 1)
Page 69
EXERCISE 7.3
Based on the parameters, functions can be categorized into two types. They are:
1 # defining a function
2 def display():
3 print("Welcome to facebook.")
4
5 # calling function
6 display()
Welcome to facebook.
What is Argument?
An argument is a variable (which contains data) or a parameter which is sent to the function as input.
Page 70
Before getting into argument types, let’s get familiar with words formal and actual arguments.
1. Formal arguments
When a function is defined it (may) has (have) some parameters within the parentheses. These parameters,
which receive the values sent from the function call, are called formal arguments.
2. Actual arguments
The parameters which we use in the function call or the parameters which we use to send the values/data
during the function calling are called actual arguments.
1 # defining a function
2 def add(a,b):
3 c = a+b
4 print(c)
5
6 # calling a function
7 add(7, 3)
10
EXERCISE 7.4
Types of Arguments
In python, depending on the way or format we send the arguments to the function, the arguments can be
classified into five types:
1. Positional arguments
2. Keyword arguments
3. Default arguments
4. Variable length arguments
5. keyword variable length argument
Page 71
1. Positional Arguments
If there are three arguments (formal arguments) in the function definition, then you need to send three
arguments(actual arguments) while calling the function. The actual arguments will be received by the formal
arguments in the same order as in the function calling.
1 # defining a function
2 def sub(a,b):
3 c = a - b
4 print(c)
5
6 # calling a function
7 sub(5, 2)
Let’s understand this through an example. In the above example the actual arguments 5, 2 will be received in
the same order sent i.e. 5 will go into variable ‘a’, and 2 will go into variable ‘b’.
The number of arguments and position of arguments should be matched, otherwise we will get errors as
shown below.
1 # defining a function
2 def sub(a, b):
3 c = a - b
4 print(c)
5
6 # calling function
7 sub(10, 20, 30)
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[8], line 7
4 print(c)
6 # calling function
----> 7 sub(10, 20, 30)
If we send the arguments as 2, 5 then 2 will go into ‘a’ and 5 will go into ‘b’ then we will get different
result(output).
Page 72
Ex 7.9 ( Positional arguments )
1 # defining a function
2 def sub(a, b):
3 c = a - b
4 print(c)
5
6 # calling function
7 sub(2, 5)
-3
2. Keyword Arguments
In the function call, if we send the values using keys then they are called keyword arguments. Here, keys are
nothing but the names of the variables. In a way, we can say that keyword arguments are arguments that
recognize the parameters by the name of the parameters.
1 # defining a function
2 def sub(a, b):
3 c = a - b
4 print(c)
5
6 # calling a function
7 sub(b=2, a=5)
At the time of calling this function, we must pass two values and we can write which value is for what by
using name of the parameter.
Syntax:
function_name(keyword = actual_argument)
PS. a and b are called as keywords in the above scenario. Here we can change the order of arguments.
EXERCISE 7.5
Create a function to print student id and student name using keyword arguments?
Page 73
Can we use both positional and keyword arguments? Yes of course…
We can use both positional and keyword arguments simultaneously. But first we must take positional
arguments and then keyword arguments, otherwise we will get syntax error.
1 # defining a function
2 def sub(a, b):
3 c = a - b
4 print(c)
5
6 # calling a function
7 sub(5, b=2)
1 # defining a function
2 def sub(a, b):
3 c = a - b
4 print(c)
5
6 # calling a function
7 sub(a=5, 2)
EXERCISE 7.6
Create a function to print phone brand and phone price using positional keyword
arguments?
If you don’t pass exact number of parameters you will get a Type error.
Page 74
Ex 7.13 ( Positional arguments TypeError )
1 # defining a function
2 def sub(a, b):
3 c = a - b
4 print(c)
5
6 # calling function
7 sub(a=5)
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[13], line 7
4 print(c)
6 # calling function
----> 7 sub(a=5)
4. Default Arguments
In the function definition, while declaring parameters, we can assign some value to the parameters, which are
called default values. Such default values will be considered when the function call does not send any data to
the parameter.
Let’s take earlier function as an example. There, the function sub() has parameters as a and b. To resolve
TypeError, we can set the default value of b as 0, then default values will be overridden with passed value.
1 # defining a function
2 def sub(a, b=0):
3 c = a - b
4 print(c)
5
6 # calling a function
7 sub(a=5, b=2)
8
9 # calling a function
10 sub(a=5)
3
5
Note: If we are not passing any value, then only default value will be considered. While defining a function,
after default arguments we should not take non-default arguments.
Page 75
Ex 7.15 ( Default arguments Error )
1 # defining a function
2 def add(a=3, b):
3 print(a + b)
4
5 # calling a function
6 add(a=5, b=2)
7
8 # calling a function
9 add(a=9)
EXERCISE 7.7
Create a function to print football player name and no. of goals he scored using default
arguments?
Sometimes, the programmer (you) does not know how many values need to pass to function. In that case, the
programmer cannot decide how many arguments to be given in the function definition. Therefore, we use
variable length arguments to accept n number of arguments.
The variable length argument is an argument that can accept any number of values.
The variable length argument is written with a ‘*’ (one star) before variable in function definition.
x is formal argument, *y is variable length argument. Now we can pass any number of values to this *y.
1 # defining a function
2 def detail(name, *others):
3 print(name, others)
4
5 # calling a function
6 detail("John")
7
8 # calling a function
9 detail("John", 20)
10
11 # calling a function
12 detail("John", 20, 3.7)
John ()
John (20,)
John (20, 3.7)
EXERCISE 7.8
Create a function to print player name and other details of him using variable length
arguments?
Just as variable length arguments, there are keyword variable length arguments which are n key value pairs.
**x represents as keyword variable argument. Internally it represents like a dictionary. A dictionary stores the
data in the form of key value pairs.
Page 77
Ex 7.17 ( keyword variable length argument )
1 # defining a function
2 def detail(**others):
3 print(others)
4
5 # calling a function
6 detail(name='John', age=20, gpa=3.7)
Function as a variable
PS. We can also assign return value to a variable.
variable_name = function_name()
1 # defining a function
2 def add(a, b):
3 return a + b
4
5 # calling a function
6 x = add(1, 2)
7
8 print("Sum of two numbers is :",x)
EXERCISE 7.9
Create a function to calculate average of two numbers and assign return value to a
variable?
Page 78
Function calling another function
It is also possible in python that a function can call another function.
def function_two():
// body of function two
function_one() # This is optional
return value
function_two()
1 # defining a function
2 def add(a,b):
3 return(a+b)
4
5 # defining a function
6 def average(a,b):
7 sum = add(a,b)
8 avg = sum / 2
9 print("Average =",avg)
10
11 # calling a function
12 average(7,3)
Average = 5.0
EXERCISE 7.10
Create a function to calculate tan(45°) using two other functions sine and cosine return
values by using eval() function?
Page 79
Nested Function
We can define one function inside another function. If we defined the inner function, then we need to call that
inner function in the outer function.
def function_two():
// body of function two
return of function two
function_two()
return of function one
function_one()
1 # defining a function 1
2 def average(a, b):
3 # defining a function 2
4 def add():
5 return a + b
6
7 # calling a function 1
8 sum = add()
9
10 avg = sum / 2
11 print("Average =",avg)
12
13 # calling a function 2
14 average(7, 3)
Average = 5.0
Page 80
EXERCISE 7.11
Create a function to calculate tan(45°) using two other nested functions sine and cosine
eval() functions?
Function as a parameter
PS. We can pass function as a parameter to another function.
1 # defining a function 1
2 def add(a, b):
3 return a + b
4
5 # defining a function 2
6 def average(sum):
7 avg = sum / 2
8 print("Average =",avg)
9
10 # calling a function 2
11 average(add(7, 3))
Average = 5.0
EXERCISE 7.12
Create a function to calculate tan(45°) by passing sin & cos functions as parameter
eval() functions?
Page 81
Let’s consider a function which calculates the factorial of a number. It can be written as a recursive functions
as explained below.
3! = 3 x 2 x 1
factorial(3) = 3 x factorial(2)
factorial(2) = 3 x 2 x factorial(1)
factorial(1) = 3 x 2 x 1 x factorial(0)
factorial(n) = n x factorial(n-1)
1 # defining a function
2 def factorial(n):
3 if n == 0:
4 result = 1
5 else:
6 result = n * factorial(n-1)
7 return result
8
9 # calling a function
10 x = factorial(4)
11
12 print("Factorial of 4 is :",x)
Factorial of 4 is : 24
PS. We will see Factorial without recursive function later in control Flow /Loops/ Chapter
EXERCISE 7.13
Page 82
Lesson Four : Types of Variables
As we discussed in variables chapter about properties of variables, The variables based on their scope can be
classified in to two types:
Local variables
Global variables
1. Local Variables
The variables which are declared inside of the function are called as local variables. Their scope is limited to
the function i.e. we can access local variables within the function only.
1 # defining a function
2 def add():
3 a, b = 5, 2
4 print(a + b)
5
6 # calling a function
7 add()
If we are trying to access local variables outside of the function, then we will get an error.
1 # defining a function
2 def add():
3 a, b = 5, 2
4 print(a + b)
5
6 # defining a function
7 def sub():
8 print(a - b)
9
10 # calling a function
11 sub()
Page 83
-------------------------------------------------------
--------------------
NameError Traceback
(most recent call last)
Cell In[33], line 11
8 print(a - b)
10 # calling a function
---> 11 sub()
2. Global Variables
The variables which are declared outside of the function are called global variables. Global variables can be
accessed in all functions.
1 a, b = 5, 2
2
3 # defining a function
4 def add():
5 print(a + b)
6
7 # defining a function
8 def sub():
9 print(a - b)
10
11 # calling a functions
12 add()
13 sub()
7
3
What if both local and global variables have the same name?
Page 84
Ex 7.26 ( same global and local variables name )
1 a, b = 5, 2
2
3 # defining a function
4 def add():
5 a = 9
6 print(a + b)
7
8 # defining a function
9 def sub():
10 print(a - b)
11
12 # calling a function
13 add()
14 sub()
11
3
If we want our function to refer to global variable rather than the local variable, we can use global keyword
before the variable in the function as shown in the example below.
1 a, b = 5, 2
2
3 # defining a function
4 def add():
5 global a
6 a = 9
7 print(a + b)
8
9 # defining a function
10 def sub():
11 print(a - b)
12
13 # calling a functions
14 add()
15 sub()
11
7
PS. The keyword "global" can be used for the following two purposes:
If we use the global keyword inside the function, then the function is able to read only global variables.
Page 85
PROBLEM: This would make the local variable no more available.
globals() is a built in function which returns a table of current global variables in the form of a dictionary.
Using this function, we can refer to the global variable as:
Syntax:
global()["variable_name"]
1 a, b = 5, 2
2
3 # defining a function
4 def add():
5 a = 9
6 print(a + b)
7 print(globals()['a'] + b)
8
9 # calling a function
10 add()
11
7
The name of the function is the mandatory item in the function definition as discussed earlier. But, in python,
we have a keyword called ‘lambda’ with which we can define a simple function in a single line without
actually naming it. Such functions are called lambda functions.
1 s = lambda a: a * a
2 x = s(4)
3 print(x)
16
Page 86
Ex 7.30 ( Lambda Function )
1 # defining a function
2 s = lambda a, b : a * b
3
4 # calling a function
5 x = s(4, 5)
6
7 print(x)
20
A lambda function can take any number of arguments but should have only one expression.
It takes the parameters and does some operation on them and returns the result, just the same as normal
functions.
The biggest advantage of lambda functions is that a very concise code can be written which improves
the readability of the code.
This can be used for only simple functions but not for complex functions.
The lambda function, mostly, can be used in combination with other functions such as map(), reduce(),
filter() etc. which we are going to discuss now.
EXERCISE 7.14
1. lter() Function
This function is used to filter values from a sequence of values.
The filter function will filter the elements in the sequence based on the condition in the function. Let’s
understand it through the example.
Page 87
Ex 7.31 ( filter() function )
1 a = [1, 2, 3, 4]
2 g = filter(lambda x : x > 2, a)
3 x = list(g)
4 print(x)
[3, 4]
In the above example, filter applies the lambda function on all the elements in the ‘a’ and returns the elements
which satisfy the lambda function.
EXERCISE 7.15
2. map() Function
This function is used to map a particular function onto the sequence of elements. After applying, this returns a
new set of values.
1 a = [1, 2, 3, 4]
2 g = map(lambda x : x+2, a)
3 x = list(g)
4 print(x)
[3, 4, 5, 6]
EXERCISE 7.16
Create a list variable and store price of foods then print all foods price after 25%
discount using map() function?
Page 88
3. reduce() Function
This function reduces the sequence of elements into a single element by applying a specific condition or logic.
To use the reduce function we need to import the functools module.
10
EXERCISE 7.17
Create a list variable and store your mid semester Exam results of each subject then
find its average using reduce() function?
What is Decorator?
A decorator is a special function which adds some extra functionality to an existing function.
Suppose you want to add some extra functionality of adding the two numbers only if they are positive. If
any number is negative, then take it as 0 during adding. For adding this extra functionality let us create a
decorator.
Syntax:
def inner_function(x, y):
if x < 0:
x = 0
if y < 0:
y = 0
return func(x, y)
return inner_function
We have created our decorator and now let’s use it with our add function from
add = decor(add)
With the above statement, we are passing the add function as parameter to the decorator function, which is
returning inner_function.
After this, whenever we call add, the execution goes to inner_function in the decorator.
add(-10, 20)
In inner_function, we are doing the extra logic for checking whether the arguments are positive or not. If not
positive we are assigning them with zero. And we are passing the processed values to the original add
function which was sent to the decorator.
Page 90
Ex 7.34 ( Decorator Function )
1 # defining a function
2 def decor(func):
3
4 # defining inner function
5 def inner_function(x, y):
6 if x < 0:
7 x = 0
8 if y < 0:
9 y = 0
10 return func(x, y)
11
12 return inner_function
13
14 # defining add function
15 def add(a, b):
16 res = a + b
17 return res
18
19 # calling a function
20 add = decor(add)
21
22 print(add(20, 30))
23 print(add(-10, 5))
50
5
EXERCISE 7.18
Create a decorator to divide two numbers but if a number is divided by zero, print
“Invalid”?
@ symbol in python
In the above example, in order to use the decorator, we have used the ‘add = decor(add)’ line. Rather than
using this we can just use the ‘@decor’ symbol on top of the function for which we want to add this extra
functionality. The decorator once created can also be used for other functions as well.
Page 91
Ex 7.35 ( Subtract Function using decorator )
1 # defining a function
2 def decor(func):
3
4 # defining a function
5 def inner_function(x, y):
6 if x < 0:
7 x = 0
8 if y < 0:
9 y = 0
10 return func(x, y)
11
12 return inner_function
13
14 @decor
15 # defining a function
16 def sub(a, b):
17 res = a - b
18 return res
19
20 # calling a function
21 print(sub(30, 20))
22 print(sub(10, -5))
10
10
EXERCISE 7.19
Create a decorator to divide two numbers but the numerator is always greater than
denominator?
If we want to retrieve elements from a generator, we can use the next function on the iterator returned by the
generator. This is the other way of getting the elements from the generator.
Page 92
Advantages of using generators
Memory Efficiency: Generators save memory by generating values on-the-fly instead of storing them
all at once.
Lazy Evaluation: Values are computed only as needed, improving efficiency for expensive operations.
Iteration Support: Generators are iterable, making it easy to loop over generated values.
Simplified Code: Generators help break complex code into smaller, more manageable pieces.
Infinite Sequences: Generators handle large or infinite sequences that can't fit in memory.
Ex 7.36 ( Generators )
1 # defining a function
2 def my_gen():
3 n = 1
4 print(n)
5 yield n
6
7 n += 1
8 print(n)
9 yield n
10
11 n += 1
12 print(n)
13 yield n
14
15 # calling a function
16 a = my_gen()
17
18 print(type(a))
19 next(a)
20 next(a)
21 next(a)
<class 'generator'>
1
2
3
3
yield is a keyword used in the context of generators. Generators are special functions that can be paused and
resumed during their execution. When a function contains the yield keyword, it becomes a generator
function.
Think of a generator function as a recipe for creating a sequence of values. Instead of generating all the values
at once and storing them in memory, the generator function generates one value at a time and "yields" it back
to the caller. The generator function remembers its state, so when it's called again, it continues from where it
left off.
Page 93
Now, let's talk about the next() function. The next() function is used to manually iterate over the values
produced by a generator. When you call next() on a generator object, it resumes the execution of the
generator function and returns the next value produced by the yield statement.
EXERCISE 7.20
Create a generator to print top 3 athletes who finish Olympic marathon 2019?
Key Takeaways
A function is a group of statements or a block of code to perform a certain task.
If a group of statements is repeatedly required, then it is not recommended to write a function.
There are two types of functions: Pre-defined (built-in) and User-defined.
An argument is a variable (which contains data) or a parameter which is sent to the function as input.
Nested function is a function that is defined inside another function.
A function is called recursive when it is called by itself.
Variables can be classified into two types based on their scope: Local variables and Global variables.
Lambda function is a short anonymous function that can be defined inline without a name.
Decorator is a special function which adds some extra functionality to an existing function.
Generators are just like functions which give us a sequence of values one as an iterable.
Page 94
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER EIGHT
String
Objectives
What is a string?
How can you access a string?
What is indexing?
What is slicing?
What operations can you perform on a string?
We already learn the first Hello World program in python. In that program we just print a group of characters
by using print() function. Those groups of characters are called as a string.
What is a string?
A group of characters enclosed within single or double or triple quotes is called as string. We can say string is
a sequential collection of characters.
Page 95
Syntaxs :
string_name = 'String' #single quotes
string_name = "String" #double quotes
string_name = '''String''' #triple single quotes
string_name = """String""" #triple double quotes
Note: Generally, to create a string mostly used syntax is double quotes syntax.
If you want to create multiple lines of string, then triple single or triple double quotes are the best to use.
1 s = ""
2 print("This is empty string ",s)
By using indexing
By using slicing operator
By using loops ( PS. we will discuss in later Control Flow Chapter )
Page 96
What is Indexing?
Indexing means a position of string’s characters where it stores. We need to use square brackets [ ] to access
the string index. String indexing result is string type. String indices should be integer otherwise we will get an
error. We can access the index within the index range otherwise we will get an error.
Positive indexing: The position of string characters can be a positive index from left to right direction
(we can say forward direction). In this way, the starting position is 0 (zero).
Negative indexing: The position of string characters can be negative indexes from right to left direction
(we can say backward direction). In this way, the starting position is -1 (minus one).
Diagram representation
Note: If we are trying to access characters of a string with out of range index, then we will get error as
IndexError.
M
J
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[8], line 2
1 name = "Michael Jackson"
----> 2 print(name[1.3])
-------------------------------------------------------
--------------------
IndexError Traceback
(most recent call last)
Cell In[9], line 2
1 name = "Michael Jackson"
----> 2 print(name[100])
EXERCISE 8.1
Create a string variable "name" and store your name then print only vowel letters from
your name?
What is Slicing?
A substring of a string is called a slice. A slice can represent a part of string from string or a piece of string.
String slicing result is string type. We need to use square brackets [ ] in slicing.
In slicing we will not get any Index out of range exception. In slicing indices should be integer or None
otherwise we will get errors.
Syntax:
string_name[start : stop : step]
step: Represents the increment the position of the index while accessing (default is 1)
Note: If you are not specifying the begin index, then it will consider the beginning of the string. If you are not
specifying the end index, then it will consider the end of the string. The default value for step is 1.
Page 98
Ex 8.6 ( String Slicing )
1 text = "together"
2 print(text [:])
3 print(text[:2])
4 print(text[2:5])
5 print(text[5:])
6 print(text[::3])
7 print(text[1:8:6])
together
to
get
her
tee
or
EXERCISE 8.2
Create a string variable "quote" and store your favorite quote then print each words
from the quote?
String having immutable nature. Once we create a string variable then we cannot change or modify it.
1 name = "Michael"
2 name[0] = "P"
3 print(name)
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[11], line 2
1 name = "Michael"
----> 2 name[0] = "P"
3 print(name)
1. Concatination ( + )
The + operator works like concatenation or joins the strings. While using + operator on string, It is
compulsory that both variables should be string type, otherwise we will get an error.
Syntax:
s1 + s2
1 fn = "Michael "
2 ln = "Jackson"
3 print(fn + ln)
Michael Jackson
1 fn = "Michael"
2 num = 4
3 print(fn + num)
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[13], line 3
1 fn = "Michael"
2 num = 4
----> 3 print(fn + num)
EXERCISE 8.3
Create four string variables "UPPER", "lower", "Symbols", "digits" and store uppercase
letters, lowercase letters, special symbols and digits(0-9) respectively then create a
password which contains all of them?
Page 100
What if we want to duplicate a string?
2. Multiplication ( * )
This is used for string repetition. While using * operator on string, It is compulsory that one variable should
be string and other arguments should be int type.
Syntax:
s * number
1 fn = "Michael "
2 rn = 4
3 print(fn * rn)
1 fn = "Michael"
2 rn = "4"
3 print(fn * rn)
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[15], line 3
1 fn = "Michael"
2 rn = "4"
----> 3 print(fn * rn)
1. len() method
We can find the length of string by using len() function. By using the len() function we can find groups of
characters present in a string. The len() function returns int as result.
Syntax:
len(s)
Page 101
Ex 8.12 ( len() Function )
1 fn = "Michael"
2 print("Length of string:",len(fn))
Length of string: 7
EXERCISE 8.4
Create a string variable "quote" and store your favorite quote then find length of the
quote?
2. Membership operators
We can check, if a string or character is a member/substring of string or not by using below operators:
in
not in
in operator returns True, if the string or character found in the main string.
Ex 8.13 ( in operator )
1 fn = "Michael"
2 print('M' in fn)
3 print('m' in fn)
4 print('Mic' in fn)
5 print('lm' in fn)
True
False
True
False
not in operator returns the opposite result of in operator. not in operator returns True, if the string or
character is not found in the main string.
1 S = "pair"
2 print('air' not in S)
3 print('chair' not in S)
Page 102
False
True
EXERCISE 8.5
Create a string variable "name" and store a string “Yonatan” then remove all vowel
letters from the string?
3. Relational Operators
We can use the relational operators like >, >=, <, <=, ==, != to compare two strings. While comparing it
returns boolean values, either True or False. Comparison will be done based on alphabetical order or
dictionary order.
1 un = "michael"
2 i = str(input("Enter user name:"))
3
4 if i == un:
5 print("Hello", i)
6 print("Welcome to facebook.")
7 else:
8 print("Invalid user name!")
A space is also considered as a character inside a string. Sometimes unnecessary spaces in a string will
lead to wrong results.
1 un = "michael"
2 i = str(input("Enter user name:"))
3
4 if i == un:
5 print("Hello", i)
6 print("Welcome to facebook.")
7 else:
8 print("Invalid user name!")
Page 103
Enter user name:mic hael
Invalid user name!
4. strip()
Predefined methods to remove spaces in Python
Note: These methods won’t remove the spaces which are in the middle of the string.
Syntax:
s.strip()
to get her
EXERCISE 8.6
Searching Methods
We can find a substring in two directions like forward and backward direction. We can use the following 4
methods:
find()
index()
rfind()
rindex()
Page 104
5. nd() method
This method returns an index of the first occurrence of the given substring.
If it is not available, then we will get -1 (minus one) value. By default find() method can search the total string
of the object.
Syntax:
string_name.find(substring)
Syntax:
string_name.find(substring, begin, end)
EXERCISE 8.7
Create a string variable "quote" and store your favorite quote then find letter "x" in
the quote?
6. index() method
index() method is exactly the same as find() method except that if the specified substring is not available then
we will get ValueError. So, we can handle this error in application level.
Syntax:
string_name.index(substring)
Page 105
Ex 8.19 ( finding substring by using index method )
1 s = "Together"
2 print(s.index("get"))
1 s = "Together"
2 print(s.index("to"))
-------------------------------------------------------
--------------------
ValueError Traceback
(most recent call last)
Cell In[25], line 2
1 s = "Together"
----> 2 print(s.index("to"))
EXERCISE 8.8
Create a string variable "quote" and store your favorite quote then find index of letter
"a" in the quote?
7. count() method
By using count() method we can find the number of occurrences of substring present in the string
Syntax:
string_name.count(substring)
1 fn = "Michael Jackson"
2 print(fn.count("a"))
3 print(fn.count("j"))
Page 106
2
0
EXERCISE 8.9
Create a string variable "name" and store your name then find no. of vowel letters in
your name?
8. replace() method
We can replace old string with new string by using replace() method. As we know string is immutable, so
replace() method never performs changes on the existing string object. The replace() method creates a new
string object, we can check this by using id() method.
Syntax:
string_name.replace(old string, new string)
A big NO. String is immutable. Once we create a string object, we cannot change or modify the existing string
object. This behavior is called immutability.
If you are trying to change or modify the existing string object, then with those changes a new string object
will be created. So, replace() method will create a new string object with the modifications.
Page 107
EXERCISE 8.10
Create a string variable "email" and store your gmail then convert it into yahoo mail?
9. split() method
We can split the given string according to the specified separator by using split() method. The default
separator is space. split() method returns list.
Syntax:
new_string = string_name.split(separator)
EXERCISE 8.11
Create a string variable "name" and store your full name then split it?
Syntax:
string_name = separator.join(A)
1 split_s = ['to','get','her']
2 s = '-'.join(split_s)
3 print(split_s)
4 print(s)
EXERCISE 8.12
Create a list variable "name" and store your first name, your middle name and surname
then join it?
Page 109
Ex 8.26 ( Changing cases )
1 fn = 'MicHaEl jACksON'
2 print(fn.upper())
3 print(fn.lower())
4 print(fn.swapcase())
5 print(fn.title())
6 print(fn.capitalize())
MICHAEL JACKSON
michael jackson
mIChAeL JacKSon
Michael Jackson
Michael jackson
Password Validation
Ex 8.27 ( Password Validation )
EXERCISE 8.13
Minimum 5 characters
Maximum 10 characters
Only lowercase letters
Underscore and dot is allowed
Whitespace, symbol are not allowed
Page 110
1 # write your answer code here
2
In other programming languages char data type represents the character type, but in python there is no
specific data type to represent characters. We can fulfill this requirement by taking a single character in single
quotes. A single character also represents as string type in python.
1 gender1 = "M"
2 gender2 = "F"
3 print(gender1)
4 print(gender2)
5 print(type(gender1))
6 print(type(gender2))
M
F
<class 'str'>
<class 'str'>
Key Takeaways
Page 111
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER NINE
Objectives
While we write a program, we store a lots of data, then those data become cluttered. Finally it will be much
difficult to retrieve, access and use them. Therefore we need to arrange, organize and manage those data by
grouping /categorizing/ then store in a single variable. In programming, this process is called as Data
Structure.
PS. Data Structure is a particular way of organizing data in a computer so that it can be used effectively.
What is List?
A list is a data structure which can store a group of elements or objects in a single variable.
Page 112
Properties of List
Lists can store the same type as well as different types of elements. Hence, it is heterogeneous.
Lists have dynamic nature which means we don’t need to mention the size (number of elements) of the
list while declaring. The size will increase dynamically.
Insertion order is preserved. The order, in which the elements are added into a list, is the order in
which output is displayed.
List can store duplicates elements.
In lists index plays the main role. Using index we perform almost all the operations on the elements in
it.
List objects are mutable which means we can modify or change the content of the list even after the
creation
We can create a list by using square brackets ‘[]’. The elements in the list should be comma separated.
Syntax :
list_name = [elements]
1 l = []
2 print(l)
3 print(type(l))
[]
<class 'list'>
You can create a list by using list() function. Generally, we use this function for creating lists from other data
types like set, tuple etc…
Syntax :
list_name = list(elements)
PS. We already discussed earlier in Data Type Chapter Lesson 4 - Data Type Conversion.
Page 113
Ex 9.2 ( Creating a list using list() function )
1 l = list()
2 print(l)
3 print(type(l))
[]
<class 'list'>
Suppose you want to create a list of multiples of 3 between 5 and 40. How could you do it? Let us see..
The range() function creates a sequence of numbers, starting from 0 by default, and increments by 1 (by
default), and stops before a specified number.
Syntax :
list_name = list(range(start, stop, step))
[6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39]
<class 'list'>
You want to go super market and buy, what will you do first. You will think what you want to buy then
make a list of items.
Let us consider you want to buy the following items ( bag, pen, cap and another pen).
You can observe from the output that the order is preserved and also duplicate items are allowed.
Page 114
PS. List can also contain mixed data type (strings, integers, boolean, None) elements.
While you list down items, you index goods from 0 to last item no. based on their priority (urgency).
By using indexing
By using slicing operator
By using loops ( PS. we will discuss in later Control Flow Chapter )
Syntax :
list_name[index_number]
Accessing the elements by index means, accessing by their position numbers in the list. Index starts from 0
onwards. List supports both positive and negative indexes. Positive index represents from left to right
direction and negative index represents from right to left direction
Note: If we are trying to access beyond the range of list index, then we will get IndexError.
-------------------------------------------------------
--------------------
IndexError Traceback
(most recent call last)
Cell In[6], line 2
1 ml = ['bag', 'pen', 'cap', 'pen']
----> 2 print(ml[10])
EXERCISE 9.1
Create a list of your email, name, gender and age, then print your name?
What if you want to look for goods listed from number 1 to 3 or listed on even numbers?
Slicing is the way of extracting a sublist (selected elements of a list) from the main list.
Syntax :
list_name[start : stop : step]
start represents the index from where we slice should start, default value is 0.
stop represents the end index where slice should end.
Page 116
Ex 9.7 ( List Slicing )
EXERCISE 9.2
Create a list of your email, name, gender and age, then print your name and age?
Syntax :
list_name[i] = new element
3. index() method
The index() method returns the position at the first occurrence of the specified item (value).
Syntax :
list_name.index(element)
Page 117
Ex 9.9 ( index() method )
cap index 2
pen index 1
4. enumerate() method
The enumerate() method returns pair of value and index position of all items in a list.
Syntax :
list(enumerate(list_name)
PS. In python, a method and a function are one and the same. There is not much difference between them. It
will be clearly explained later in OOPS chapter. For now just remember function and method are the same.
EXERCISE 9.3
Create a list of your email, name, gender and age, then update your email and print
index of all elements in the list?
Ohhh... you forgot to write “oil” on your list, don’t worry you can add to the list. How? Let us see..
Page 118
Lesson Three : Insertion of List Elements
1. append() method
Using this method we can add elements to the list. The elements will be added at the end of the list.
Syntax :
list_name.append(new_element)
Here is the problem, “oil” is listed at end of the list, but you are starving now and you want to cook food
as soon as you reach to your home. So “oil” should be listed first. How? Let us see...
2. insert() method
The insert() method add the elements to the list at the specified index (position). It takes two arguments as
input: one is the index and the other is the element.
Syntax :
list_name.insert(i, new_element)
If the specified index is greater than max index, then element will be inserted at last position.
If the specified index is smaller than min index, then element will be inserted at first position.
EXERCISE 9.4
Create a list of your email, name, gender and age, then append your password and insert
your username to the list at index 1?
Here is another issue, your father also want to buy goods but he is too busy so he asks you to buy him
items. Therefore, you have to merge your list with his list? How? Let us see…
3. extend() method
Using this method the items in one list can be added to the other.
Syntax :
new_list.extend(old_list)
Suppose your mother also order you to pick her goods from store then you want to merge all lists: my_list,
mom_list and dad_list, Let us see…
Page 120
Ex 9.14 ( extend() method )
But, Why you extend the list twice, Since Number of lines in a program is important for code efficiency /
execution time /, Why don’t we complete it within a single line? Let us see…
4. Concatenation operator ( + )
“+” operator concatenates two list objects to join them and returns a single list.
PS. For this, both the operands should be list type, else we will get TypeError.
Syntax :
list_3 = list_1 + list_2
1 a = [1, 2, 3]
2 b = 'pen'
3
4 c = a + b
5 print(c)
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
Cell In[17], line 3
1 a = [1, 2, 3]
2 b = 'pen'
----> 3 c = a + b
4 print(c)
EXERCISE 9.5
Create a list of your email, name, gender and age, then create another list which
contains your birth date, month, year and extend/add it to former list?
Hell no… on your way your sister called you then told you that he found your pen so you want to remove
one pen from your list. How? Let us see…
There are many ways of deleting & clearing elements from a list. Let’s try to understand each of them.
1. remove() method
This method used to remove specific item from a list.
Syntax :
list_name.remove(element)
Page 122
Ex 9.17 ( remove() method )
If the item exists multiple times, then only the first occurrence will be removed.
If the specified item not present in list, then we will get ValueError.
Before removing elements it’s a good approach to check if the element exists or not to avoid errors.
2. pop() method
This method takes an index of removable element.
If no index is given, then the last item is removed and returned by default.
If the provided index is not in the range, then IndexError is thrown.
Syntax :
list_name.pop(i)
Page 123
Ex 9.19 ( pop() method )
While you are purchasing in supermarket you are running out of money so what will you do? You should
remove item based on its priority so last item should be removed. How? Let us see…
-------------------------------------------------------
--------------------
IndexError Traceback
(most recent call last)
<ipython-input-2-858b5e8b67d2> in <cell line: 2>()
1 my_list = ['bag', 'pen', 'cap', 'pen']
----> 2 my_list.pop(10)
Page 124
Difference between remove() and pop()
3. del statement
The del statement can be used to delete an element at a given index. Also, it can be used to remove slices from
a list.
Syntax :
del list_name[start : stop : step]
Page 125
Ex 9.24 ( del statement / all )
4. clear() method
clear() method removes all the elements from a list.
Syntax :
list_name.clear()
5. *= method
This method removes all the elements by selecting all elements of a list then truncate them from the list.
Syntax :
list_name *= 0
Ex 9.26 ( *= method )
Page 126
EXERCISE 9.6
Create a list of your email, name, gender and age, then if the email is not gmail delete
it, if the gender is male delete all elements from the list?
What if your list contains large number of items. It is difficult to find and manage your items. So you need
to sort them based on alphabetical order (A to Z). How? Let us see…
1. sort() method
In a list by default insertion order is preserved. If we want to sort the elements of the list according to default
natural sorting order then we should go for sort() method.
Syntax :
list_name.sort()
Page 127
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
<ipython-input-9-dffd5406ba98> in <cell line: 2>()
1 n = [4, 5, 1, 'bag', 2, 'pen']
----> 2 n.sort()
3 print(n)
2. reverse() method
This method reverses the order of list elements.
Syntax :
list_name.reverse()
EXERCISE 9.7
Create a list of name of grade 10 students then sort them from A to Z and Z to A?
Earlier we use extend() function to merge two lists? But Now we want to categorize elements of a list.
Here elements of a list are treated as a list themselves.
What if you want to group items based on their type ( Electronics, Stationary, Food )?
3. Nested Lists
A list within another list is called a nested list. It is possible to take a list as an element in another list.
Page 128
Syntax :
list_name=[[elements..], [..]..]
EXERCISE 9.8
Create a list of name of grade 10 students then classify them as Section 10A and Section
10B students?
Suppose, you have twin and your twin also want to buy exactly the same items that you want to buy, but in
different supermarket so how would you copy your item list to her?
The new name is called an alias name. Both names will refer to the same memory location.
If we do any modifications on the data, then it will be updated at the memory location.
Since both the actual and alias name refer to the same location, any modifications done on an existing
object will be reflected in the new one also.
Syntax :
list_1 = list_2
PS. list_1 is new list (alias name) and list_2 is original list (actual name).
Page 129
Ex 9.31 ( List Aliasing )
What if your twin want to buy book instead of bag because she already have one? so what will you do?
Here is the problem. your twin want to buy book but you want to buy a bag. Solve this? Let’s see…
PS. In List Aliasing, memory address of my_list and twin_list was the same. What if we have different memory
address for each list?
Earlier, we use extend() method to merge two lists, Now we can use to copy a list. How? Let us see..
The lists can be copied into a new list by using the extend() function. This appends each element of the
original list to the end of the new list.
Syntax :
list_1 = [] list_1.extend(list_2)
Syntax :
list_1 = [] list_1 += list_2
Page 131
Ex 9.34 ( Cloning using extend() method )
What if you want to copy specific elements of a list? Suppose your twin want to buy only book and cap.
you can create another new twin list, but why don’t we clone your list since it contains all items ( except
“book” ) that your twin want to buy? How could you do it? Let us see…
Earlier, we use slice ( : ) operator to slice then access elements of a list, Now we can use to copy a list.
How? Let us see…
Syntax :
list_1 = list_2[start:stop:step]
Page 132
my list: ['bag', 'pen', 'cap', 'pen']
twin list: ['book', 'cap']
Memory Address of my list: 134125664854016
Memory Address of twin list: 134125664902080
Earlier, we use list() method to create a list, Now we use to copy a list. How? Let us see…
Syntax :
list_1 = list(list_2)
Syntax :
list_1 = list_2.copy()
Page 133
Ex 9.37 ( Cloning by using copy() method )
A shallow copy means constructing a new collection list and then populating it with references to the
elements of list found in the original.
Syntax :
import copy
list_1 = copy.copy(list_2)
1 import copy
2 my_list = ['bag', 'pen', 'cap', 'pen']
3 twin_list = copy.copy(my_list)
4
5 twin_list[0] = 'book'
6 print('my list:', my_list)
7 print('twin list:', twin_list)
8 print('Memory Address of my list:', id(my_list))
9 print('Memory Address of twin list:', id(twin_list))
EXERCISE 9.9
Create a list of name of grade 10 students then add extra student ‘John’ then copy the
list?
Page 134
1 # write your answer code here
2
PS. Shallow copy doesn't create a copy of nested elements of list, instead it just copies the reference of nested
list. This means, a copy process does not recurse or create copies of nested elements of a list.
Here is the problem, even though we use the above six cloning methods (including method of Shallow
Copy) to copy nested list, we couldn’t modify an element independently. Let us check it…
1 import copy
2 my_list = [['oat', 'egg'],['bag', 'pen']]
3 twin_list = copy.copy(my_list)
4
5 twin_list[1][0] = 'book'
6 print('my list:', my_list)
7 print('twin list:', twin_list)
8 print('Memory Address of my list:', id(my_list))
9 print('Memory Address of twin list:', id(twin_list))
Therefore, we need to use method of deep copy for cloning nested list.
Syntax :
import copy
list_1 = copy.deepcopy(list_2)
1 import copy
2 my_list = [['oat','egg'],['bag','pen']]
3 twin_list = copy.deepcopy(my_list)
4
5 twin_list[1][0] = 'book'
6 print('my list:', my_list)
7 print('twin list:', twin_list)
8 print('Memory Address of my list:', id(my_list))
9 print('Memory Address of twin list:', id(twin_list))
Page 135
my list: [['oat', 'egg'], ['bag', 'pen']]
twin list: [['oat', 'egg'], ['book', 'pen']]
Memory Address of my list: 134125663881920
Memory Address of twin list: 134125664520384
EXERCISE 9.11
Create a nested list of name of grade Section 10A and Section 10B students then add
extra student ‘John’ then copy the list?
1. len() method
len() function returns the number ( length ) of elements in a list.
Syntax :
len(list_name)
Page 136
Ex 9.41 ( len() function )
my list length: 4
twin list length: 2
What if you want to know how many pens you listed to buy?
2. count() method
This method returns the number of occurrences of specific item in the list.
Syntax :
list_name.count(element)
Pen occurs: 2
Pen occurs: 0
3. max()
max() function returns the largest element of a list.
Syntax :
max(list_name)
Page 137
Ex 9.43 ( max() method )
1 n = [7, 6, 9, 2, 3]
2 my_list = ['bag', 'pen', 'cap', 'pen']
3 twin_list = [['oat', 'egg'], ['bag', 'pen']]
4
5 print("max of numbers list:",max(n))
6 print("max of my list:",max(my_list))
7 print("max of twin list:",max(twin_list))
4. min()
min() function returns the smallest element of a list.
Syntax :
min(list_name)
1 n = [7, 6, 9, 2, 3]
2 my_list = ['bag', 'pen', 'cap', 'pen']
3 twin_list = [['oat', 'egg'], ['bag', 'pen']]
4
5 print("min of numbers list:",max(n))
6 print("min of my list:",max(my_list))
7 print("min of twin list:",max(twin_list))
5. random.choice() method
Sometimes, while working with dictionaries, we can have a situation in which we need to find a random pair
from dictionary. This type of problem can come in games such as lotteries etc. Let’s discuss certain ways in
which this task can be performed.
Syntax:
import random
random.choice(list_name)
Page 138
Ex 9.45 ( random(choice()) method )
1 import random
2 players = {'Messi', 'Ronaldo', 'Salah'}
3
4 print("The Winner is " ,end="")
5 print(random.choice(list(players)))
EXERCISE 9.12
Create a list in range 1 to 10 first the computer picks one number and you guess that
number then if your guess is correct, you win else you lose?
6. sum()
sum() function adds only integer elements of a list and returns the sum.
Syntax :
sum(list_name)
1 n = [7, 6, 9, 2, 3]
2
3 print("Sum of numbers list:",sum(n))
PS. max(), min() and sum() functions only works for homogenous data type elements, else your code will
return an error.
EXERCISE 9.13
Create a list of random five numbers then check whether there is duplicated number or
not if it is there delete it, if sum of all numbers is even print maximum of the list
else print minimum of the list.
Page 139
1 # write your answer code here
2
What if you want to duplicate all items of a list in the list itself?
1. Multiplication operator ( * )
The “ * ” operator works to repeat elements in the list by the said number of times. For this one operand
should be list and the other operand should be integer, else we get TypeError.
Syntax :
no. of repeat * list_name
In Operators Chapter we compared variables of different data types. Now we are going to compare two
Lists? How? Let us see…
2. Relational Operators
We can use relational operators (<, <=,>,>=) on the List elements for comparing two lists.
Initially the first two items are compared, and if they are not the same then the corresponding result is
returned.
If they are equal, the next two items are compared, and so on
While comparing lists which are loaded with strings the following things are considered for the comparison.
False
False
True
False
False
What if you want to check whether “oat” is in your twin nested list or not?
3. Membership Operators
We can check if the element is a member of a list or not by using membership operators. They are:
in operator : If the element is a member of list, then the in operator returns True otherwise False.
not in operator : If the element is not in the list, then not in operator returns True otherwise False.
Page 141
Ex 9.50 ( Membership operators )
EXERCISE 9.14
Create a list of random three numbers 1 to 10, then if 2 is in the list duplicate the
list else delete the list?
Page 142
When should we go for tuple data structure?
If we are going to define a data which is not going to change over the period, then we should go for tuple data
structure. For example, week days, calendar months, years etc.
Empty Tuple
Single value tuple
Tuple with group of values
By using tuple() function
1. Empty Tuple
Syntax :
tuple_name = ()
1 emp = ()
2
3 print(emp)
4 print(type(emp))
()
<class 'tuple'>
If a tuple has only one object, then that object should end with a comma separator otherwise python,
internally, will not consider it as a tuple.
1 name = ("John")
2 a = (11)
3
4 print(name)
5 print(a)
6 print(type(name))
7 print(type(a))
John
11
<class 'str'>
<class 'int'> Page 143
We can create a single value tuple in two ways:
Syntax :
tuple_name = (element,)
1 name = ("John",)
2 a = (11,)
3
4 print(name)
5 print(a)
6 print(type(name))
7 print(type(a))
('John',)
(11,)
<class 'tuple'>
<class 'tuple'>
Tuple can contain group of objects; those objects can be of the same type or different types. While creating
tuple with group of values parentheses are optional.
Syntax :
tuple_name = (elements)
Page 144
Ex 9.55 ( Parenthesis is optional for tuple )
Syntax :
tuple_name = tuple(list_name)
Syntax :
tuple_name = tuple(start, stop, step)
(1, 3, 5, 7, 9)
Tuple Immutability
Tuple having immutable nature. If we create a tuple then we cannot modify the elements of the existing tuple.
Page 145
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
<ipython-input-38-11caf04c28a2> in <cell line: 2>()
1 my_tuple = (10, 20, 30, 40)
----> 2 my_tuple[1] = 70
Syntax :
new_tuple = sorted(tuple_name)
Syntax :
new_tuple = sorted(tuple_name, reverse=True)
Tuple Packing
We can create a tuple by packing a group of variables.
Syntax :
tuple_name = elements
Page 146
Ex 9.61 ( Tuple packing )
Tuple Unpacking
Tuple unpacking is the reverse process of tuple packing, we can unpack a tuple and assign its values to
different variables.
Syntax :
elements = tuple_name
a = 10 b = 20 c = 30 d = 40
Note: At the time of tuple unpacking the number of variables and number of Values should be the same,
otherwise you will get ValueError.
Page 147
EXERCISE 9.14
Create a tuple of random three numbers 1 to 10, then if 2 is in the tuple sort the tuple
else reverse sort then unpack the tuple?
Key Takeaways
Data Structure is a particular way of organizing data in a computer.
A list is a data structure which can store a group of elements or objects in a single variable.
You can access elements of a list using indexing, slicing, or loops.
You can insert elements in a list using append(), insert(), extend() methods.
You can delete elements of list using remove(), pop(), clear(), *= methods and del statement.
You can arrange elements of a list using sort() and reverse() methods.
A list within another list is called a nested list.
The process of giving a new name to an existing one is called Aliasing.
The process of creating duplicate independent objects is called cloning.
You can use operators ( *, membership and relational operators ) and methods ( len(), count(),
max(), min(), random.choice(), sum() ) on a list.
Tuple is a collection of objects, which are ordered and can’t be changed.
List objects are mutable Whereas Tuple objects are immutable.
Page 148
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER TEN
Objectives
What is a loop?
What are the advantages of loops?
What are the two types of loops in Python?
What is an infinite loop?
What is a nested loop?
What are break, continue, and pass statements?
What is the difference between pass and comment?
What is list comprehension?
Introduction to Loops
Computers are great at repeating the same task over and over. They never get bored or make a mistake. You
could ask a computer a thousand times in the first result would be just as accurate as the last, which isn’t
something we can say about us humans. Have you ever tried to do something at thousand times in a row, it be
enough to drive you loopy.
The ability to accurately perform repetitive tasks and never get tired is why computers are so great for
automation. It doesn’t matter how complex the task is your computer will do it as many times as you tell it to.
Page 149
Advantages of loops
It provides code reusability.
Using loops, we do not need to write the same code again and again.
Using loops, we can traverse over the elements of sequence data types.
What is loop?
A loop is a construction that allows you to execute a block of code multiple times repeatedly until the program
meets a certain given condition. It consists of two parts - a condition and a body.
Every loop has a condition. This is the part that controls if the loop should continue or stop. All loops
continue their iterations if the condition is true. The condition is any valid value or expression that could be
evaluated to a value. A value of 0 or '\0' (null) is considered as "false" and everything else is "true"
► Body
The body is one or more valid statements. If it consists of more than one statement, the body must be enclosed
in curly brackets { } .
The loop starts by entering the condition. If it is "true" the body will be executed. Then the execution repeats
the check of the condition and then the body. It looks like this:
Page 150
begin -> condition(true) -> body -> condition(true) -> body ... condition(false) -> end.
while Loop
The while loop contains an expression/condition. As per the syntax colon (:) is mandatory otherwise it throws
syntax error. Condition gives the result as bool type, either True or False. The loop keeps on executing the
statements until the condition becomes False.
Condition: Once the initializations done, then it will go for condition checking which is the heart of the while
loop. The condition is checked and if it returns True, then execution enters the loop for executing the
statements inside.
After executing the statements, the execution goes to the increment/decrement section to increment the
iterator. Mostly, the condition will be based on this iterator value, which keeps on changing for each iteration.
This completes the first iteration.
In the second iteration, if the condition is False, then the execution comes out of the loop else it will proceed
as explained in the above point.
Increment/Decrement section: This is the section where the iterator is increased or decreased.
Suppose you have a folder that contains List of Songs: Michael Jackson Thriller Album, Then you want to
play all music in the album. How? Let us see…
PS. For sake of simplicity we consider that the folder contains only 4 songs from the album.
Page 151
Ex 10.1 ( while loop )
1 Music = 'Thriller'
2
3 i = 1
4 while i <= 3:
5 print("Playing",Music)
6 i+=1
Playing Thriller
Playing Thriller
Playing Thriller
Before starting the loop, we have made some assignments( i = 1). This is called the Initialization.
After initialization, we started the while loop with a condition i <= 3. This condition returns True until i is less
than 3.
After the music played, we are incrementing the value of i using the operator i+=1. This is called the
incrementation/decrementing.
For each iteration the value of i will increase and when the i value reaches 4, then the condition i<=3 returns
False. At this iteration, the execution comes out of the loop without executing the statements inside. Hence the
music is not played for 4th time.
EXERCISE 10.1
Playing WBSS
Playing Thriller
Playing Beat It
Playing PYT
Page 152
EXERCISE 10.2
A Fibonacci Sequence is a series of numbers where each number is the sum of the two
numbers that precede it. 0, 1, 1, 2, 3, 5, 8, …
Basically, for loop is used to iterate elements one by one from sequences like string, list, tuple, etc. This loop
can be easily understood when compared to while loop. While iterating elements from sequence we can
perform operations on every element.
Only iterable data types are used in sequence, those are List, Tuple, Set, Dictionary and String.
Suppose you have a folder that contains List of Songs: Michael Jackson Thriller Album, Then you want to
play all music in the album. How? Let us see…
PS. For sake of simplicity we consider that the folder contains only 4 songs from the album.
Playing WBSS
Playing Thriller
Playing Beat It
Playing PYT
EXERCISE 10.3
Suppose you want to listen only one music throughout your life, How you achieve this? Let’s see
In nite Loop
The loop which never ends, or the loop whose condition never gets False is called an infinite loop. This loop
never exits. In order to come out of the loop we need to manually do it by command Ctrl + C .
1 import itertools
2 Music = ['Thriller']
3
4 for i in itertools.count():
5 print("Playing",Music)
Playing ['Thriller']
Playing ['Thriller']
. . .
EXERCISE 10.4
Page 154
Syntax of infinite while loop :
while True:
statements
1 Music = 'Thriller'
2
3 while True:
4 print("Playing",Music)
Playing ['Thriller']
Playing ['Thriller']
Playing ['Thriller']
...
EXERCISE 10.5
Suppose you want to play two albums (The weeknd and Michael Jackson) from music folder?
Nested Loops
If a loop is written inside another loop then it is called a nested loop. Let’s understand it with an example.
Page 155
Playing D.D.
Playing Outside
Playing WBBS
Playing Thriller
Playing Beat It
while condition_2:
statements
Increment/Decrement_2
Increment/Decrement_1
Playing D.D.
Playing Outside
Playing WBBS
Playing Thriller
Playing Beat It
while condition:
statements
Increment/Decrement
Page 156
Ex 10.8 ( Nested for-while Loops )
Playing D.D.
Playing Outside
Playing WBBS
Playing Thriller
Playing Beat It
Playing D.D.
Playing Outside
Playing WBBS
Playing Thriller
Playing Beat It
EXERCISE 10.6
You might face a situation in which you need to exit a loop completely when an external condition is
triggered or there may also be a situation when you want to skip a part of the loop and start next execution.
Python provides break and continue statements to handle such situations and to have good control on your
loop.
break Statement
The break statement terminates the loop containing it. Control of the program flows to the statement
immediately after the body of the loop.
If the break statement is inside a nested loop (loop inside another loop), the break statement will terminate the
innermost loop.
Suppose you want to play only the first two songs of the album?
Playing WBSS
Playing Thriller
Page 158
EXERCISE 10.7
continue Statement
The continue statement is used to skip the rest of the code inside a loop for the current iteration only. Loop
does not terminate but continues on with the next iteration.
Playing WBSS
Playing Beat It
Playing PYT
EXERCISE 10.8
pass Statement
The pass statement is used when you have to include some statement syntactically but doesn’t want to
perform any operation.
Page 159
Syntax of pass statement:
for variable in sequence:
statements
pass
Playing WBSS
Playing Beat It
Playing PYT
EXERCISE 10.9
EXERCISE 10.10
Page 160
Lesson Five : List Comphrension
1 original_list = [1, 2, 3, 4, 5]
2 cloned_list = []
3
4 for i in original_list:
5 cloned_list.append(i)
6
7 print("Original List:", original_list)
8 print("Cloned List:", cloned_list)
The above code can be written in a single line using list comprehensions.
Here Iterable represents a list, set, tuple, dictionary or range object. The result of list comprehension is a new
list based on the applying conditions.
1 original_list = [1, 2, 3, 4, 5]
2
3 cloned_list = [i for i in original_list]
4
5 print("Original List:", original_list)
6 print("Cloned List:", cloned_list)
Page 161
Ex 10.15 ( List Comprehensions with if statement )
Tuple Comprehension
PS. Tuple comprehension is not supported by Python.
When attempting to perform tuple comprehension, the result is not a tuple, it is a list.
1 numbers = (1, 2, 3, 4, 5)
2 print("Original Tuple:", numbers)
3 print(type(numbers))
4
5 tuple_comp = [i*2 for i in numbers]
6 print("Compressed Tuple:", tuple_comp)
7 print(type(tuple_comp))
However, you can use generator expressions to create tuples in a similar way. A generator expression is
enclosed in parentheses instead of square brackets, which are used for list comprehension. The expression
after execution will return a generator object rather than a tuple object, so we need to convert it into a tuple.
1 numbers = (1, 2, 3, 4, 5)
2 print("Original Tuple:", numbers)
3 print(type(numbers))
4
5 tuple_comp = tuple(i*2 for i in numbers)
6 print("Compressed Tuple:", tuple_comp)
7 print(type(tuple_comp))
Page 162
Original Tuple: (1, 2, 3, 4, 5)
<class 'tuple'>
Compressed Tuple: (2, 4, 6, 8, 10)
<class 'tuple'>
EXERCISE 10.11
Create a list using list comprehension that includes only the prime numbers from the
original list?
Page 163
EXERCISE 10.12
Draw an Isosceles Triangle /Christmas Tree/ pattern which looks like as follows.
Page 164
EXERCISE 10.13
Draw Life Span /Hour Glass/ pattern which looks like as follows
1
2 2
3 3 3
4 4 4 4
1 current_NO = 1
2 stop = 2
3 r = int(input("Enter No. of rows:"))
4
5 for i in range(r):
6 for j in range(1, stop):
7 print(current_NO, end=' ')
8 current_NO += 1
9 print("")
10 stop += 2
Page 165
Enter No. of rows:4
1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16
EXERCISE 10.14
Page 166
EXERCISE 10.15
Key Takeaways
Page 167
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER ELEVEN
Set
Objectives
What is a set?
How can you insert elements into a set?
What is the difference between the add() and update() methods?
How can you delete elements from a set or delete the set itself?
What operations can you perform on a set?
What methods can you use on a set?
What is a frozen set?
What is Set?
Sets are also one of the data types just as lists and tuples. If we want to represent a group of unique elements
then we can go for sets.
Page 168
How To Create a Set?
There are three ways to create a set in Python. Let’s see them with examples.
We can create set by using curly braces {} and all elements separated by comma separator in set.
Syntax :
set_name = {elements}
As we discussed earlier in creating a list using range function, The range() function creates a sequence of
numbers, starting from 0 by default, and increments by 1 (by default), and stops before a specified number.
Syntax :
set_name = set(range(start, stop, step))
From the above programs, we can observe that the order of the elements is not preserved.
Page 169
Ex 11.3 ( Duplicates are not allowed )
You can create set by using set() function. Generally, we use this function for creating sets from other data
types like list, tuple etc…
Syntax :
set_name = list(elements)
PS. We already discussed earlier in Data Type Chapter Lesson 4 - Data Type Conversion.
Syntax :
set_name = set()
1 d = {}
2 print(d)
3 print(type(d))
4
5 s = set()
6 print(s)
7 print(type(s))
{}
<class 'dict'>
set()
<class 'set'>
Page 170
Lesson Two : Insertion of Set Elements
Suppose, FCB bought extra forward player, then How to add him to the set?
1. add() method
The add() method is used to add elements to the set.
Syntax :
set_name.add(new_element)
Suppose, FCB bought extra forward ( more than one ) players, then How to add them to the set?
2. update() method
To add multiple items to the set. The arguments are not individual elements, but are sequential data type. like
list, tuple, range etc.
Syntax :
set_1.update(set_2)
1 forward_players = {'Messi','Fati','Pedri'}
2
3 new_forwards = {'Ronaldo','Neymar'}
4 forward_players.update(new_forwards)
5 print("FCB Forwards\n",forward_players)
FCB Forwards
{'Fati', 'Neymar', 'Ronaldo', 'Pedri', 'Messi'}
Page 171
Difference between add() and update()
We can use add() to add individual items to the set, whereas update() is used to add multiple items to set.
The add() method can take one argument whereas update() method can take any number of arguments but the
only point is all of them should be sequence data type.
3. copy() method
This method returns a shallow copy of the set.
Syntax :
new_set = copied_set.copy()
EXERCISE 11.1
Create set of files ~ ( Img_01.png, Avatar.mp4 ), add new file ‘Track01.mp3’ then Rename
‘Track01.mp3’ to ‘Music01.mp3’, finally Copy all files to new set (Folder)?
Suppose, The club FCB is in bankruptcy want to sell one random forward player. How could you remove
him from the set? Let us see…
1. pop() method
This method removes an arbitrary / random element from the set and returns the element removed.
Syntax :
set_name.pop()
Page 172
Ex 11.8 ( pop() method )
Messi is sold.
FCB Forwards set()
Hell No… Messi is crucial player for FCB so let us keep him and sell another player ~ Pedri
2. remove() method
This method removes specific elements from the set. If the specified element is not present in the set then we
will get KeyError.
Syntax :
set_name.remove(element)
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-28-ddb392e3944f> in <cell line: 3>()
1 forward_players = {'Messi', 'Fati', 'Pedri'}
2
----> 3 forward_players.remove('Ronaldo')
4 print("FCB Forwards",forward_players)
KeyError: 'Ronaldo'
Page 173
3. discard() method
This method removes the specified element from the set. If the specified element is not present in the set, then
we won’t get any error.
Syntax :
set_name.discard(element)
4. clear() method
This method removes all elements from the set.
Syntax :
set_name.clear()
EXCERCISE 11.2
Create set of files ~ ( Img_01.png, Pic.jpeg, Avatar.mp4 ), then delete all image files?
Page 174
1 # write your answer code here
2
Suppose, you want to know all Spanish and FCB Forward players? How could you do it? Let us see…
1. union() method
This method return all elements present in both sets.
Syntax:
A.union(B) or A | B
EXCERCISE 11.3
Create two sets Folder_1 and Folder_2, then print all files in Folder_1 and Folder_2?
Page 175
Suppose, you want to know all FCB Spanish Forward players? How could you do it? Let us see…
2. intersection() method
This method returns common elements present in both set A and set B.
Syntax :
A.intersection(B) or A & B
3. intersection_update()
The intersection_update() updates the set calling intersection_update() method with the intersection of sets.
Syntax :
A.intersection_update(B)
Create two sets Folder_1 and Folder_2, then delete all duplicated files?
Suppose, you want to know all Non-Spanish FCB Forward Players? or Spanish but not FCB Forward
Players? How could you do it? Let us see…
4. difference() method
This method returns the elements present in set A but not in set B.
Syntax :
A.difference(B) or A – B
Page 177
5. difference_update() method
The difference_update() updates the set calling difference_update() method with difference of sets.
Syntax :
A.difference_update(B)
What if you want to know all Forward Players who plays for FCB or Spain, but not both?
6. symmetric_difference()
This method returns elements present in either set A or set B but not in both.
Syntax :
A.symmetric_difference(B) or A ^ B
Page 178
Ex 11.20 ( symmetric_difference() method )
7. symmetric_difference_update()
The symmetric_difference_update() method finds the symmetric difference of two sets and updates the set
calling it.
Syntax:
A.symmetric_difference_update(B)
EXERCISE 11.5
Create two sets Folder_1 and Folder_2, then print all non-duplicated files?
Syntax :
A.issubset(B)
Page 179
Ex 11.22 ( membership operators in sets )
False
True
issuperset() method returns True if a set has every elements of another set. If not, it returns False.
Syntax :
A.issuperset(B)
True
False
isdisjoint() method returns True if two sets are disjoint sets. If not, it returns False.
Syntax :
A.isdisjoint(B)
PS. All issubset(), issuperset() and isdisjoint() methods are not commutative.
Page 180
Ex 11.24 ( isdisjoint() method )
False
True
True
EXERCISE 11.6
Create two sets Folder_1 & Folder_2, then delete duplicated (subset) folder and keep
super folder?
Frozen Set
Frozen set is similar to a set, but it is immutable, meaning its elements cannot be changed after creation.
Syntax :
frozen_set_name = frozenset(set_name)
Page 181
frozenset({'Messi', 'Pedri', 'Fati'})
<class 'frozenset'>
EXERCISE 11.7
len()
count()
max(), min(), sum()
multiplication *
Relational Operator
Membership operator
Key Takeaways
Page 182
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER TWELVE
Dictionary
Objectives
What is a dictionary?
How can you insert and update elements in a dictionary?
How can you access dictionary elements?
How can you delete elements from a dictionary or delete the dictionary itself?
What is dictionary comprehension?
In python, to represent a group of individual objects as a single entity then we have used lists, tuples, sets. If
we want to represent a group of objects as keyvalue pairs then we should go for dictionaries.
What is Dictionary?
Dictionary is an unordered collection of items. Each item of a dictionary has a key/value pair.
Characteristics of Dictionary
Dictionary will contain data in the form of key, value pairs.
Key and values are separated by colon : symbol.
One key – value pair can be represented as an item.
Duplicate keys are not allowed but Duplicate values can be allowed.
Heterogeneous objects are allowed for both key and values.
Insertion order is not preserved.
Dictionary objects are mutable & dynamic.
Indexing and slicing concepts are not applicable.
Page 183
How to Create dictionary?
There are multiple ways to create a dictionary.
We can create empty dictionaries by using curly braces. And later on we can add the key value pairs into it.
Syntax :
dictionary_name = {}
1 p = {}
2
3 print(p)
4 print(type(p))
{}
<class 'dict'>
This can be used to create an empty dictionary. Later, we can add elements to that created dictionary.
Syntax :
dictionary_name = dict()
1 p = dict()
2
3 print(p)
4 print(type(p))
{}
<class 'dict'>
Page 184
3. Using curly brace { } and colon (:)
Syntax:
dictionary_name = {key1:value1,..., keyN:valueN}
Suppose, you want to create dictionary of English Premier League Top Goal Scorers with respect to their
total goal. How could you do it? Let us see…
The fromkeys() method creates a new dictionary from the given sequence of elements with a value provided
by the user.
Syntax :
dictionary_name.fromkeys(A, value)
Page 185
Ex 12.5 ( creating dictionary using fromkeys() )
The zip() function takes one or more sequences and combines the corresponding items in the sequences into a
dictionary. It stops when the shortest sequence is exhausted.
Syntax:
dictionary_name = dict(zip(A, B))
Suppose, A player ~ “Vardy” scored more goals and he becomes Top Goal Scorer. How to add Vardy to the
dictionary? Let us see…
Page 186
Syntax:
dictionary_name[key] = value
Suppose, “Son” scored two more goals in last night game. How to update Son’s goals? Let us see…
Syntax:
dictionary_name[key] = value
update() method
The update() method updates the dictionary with the elements from the another dictionary object or from an
iterable of key/value pairs.
Syntax:
dictionary_name.update(key=value,...)
Page 187
Ex 12.9 ( update() method case 1 )
{'Salah': 13, 'Kane': 12, 'Son': 14, 'Haaland': 11, 'Vardy': 12}
Syntax:
dictionary_name.update(new_dictionary)
{'Salah': 13, 'Kane': 12, 'Son': 14, 'Haaland': 11, 'Vardy': 12}
EXERCISE 12.1
Create a contact dictionary which contains phone no. and name as key-value pair then
insert a contact Abel, +251 9 12546782, finally update its phone no. to +251 9 23468494?
By using key
By using get() method
By using setdefault() method
By using random(choice()) method
By using items(), keys(), values() methods
Page 188
What if you want to know how many goals did “Son” scored in Premier League?
1. Using key
We can access dictionary values by using keys. Keys play a main role to access the data.
Syntax :
dictionary_name[key]
Son’s Goals: 12
PS. While accessing, if specified key is not available then we will get KeyError.
Ex 12.12 ( KeyError )
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-12-104a187712c7> in <cell line: 3>()
1 goal_scorers = {'Salah':13, 'Kane':12, 'Son':12}
2
----> 3 print("Messi’s Goals:",goal_scorers['Messi'])
KeyError: 'Messi'
2. get() method
This method used to get the value associated with the key. This is another way to get the values of the
dictionary based on the key. The biggest advantage it gives over the normal way of accessing a dictionary is,
this doesn’t give any error if the key is not present.
Syntax:
dictionary_name.get(key)
Page 189
Case 1: If the key is available, then it returns the corresponding value otherwise returns None. It won’t
raise any error.
Case 2: If the key is available, then returns the corresponding value otherwise returns default value
which we give.
Syntax :
dictionary_name.get(key, default value)
Son's Goal: 12
Messi's Goal: None
Son's Goal: 12
Messi isn’t a premier league player.
PS. There is also another precise way of handling this error, which we shall discuss later in Exception
Handling Chapter.
Create a contact dictionary which contains phone no. and name as key-value pair then
search a contact Phone no. of ‘Abel’?
3. setdefault() method
The setdefault() method returns the value of a key (if the key is in dictionary). If not, it inserts key with a
value to the dictionary.
Syntax:
dictionary_name.setdefalut(key, value)
Son Goals: 12
Alison Goals: None
{'Salah': 13, 'Kane': 12, 'Son': 12, 'Alison': None}
Son Goals: 12
Alison Goals: 0
Page 191
EXERCISE 12.3
Create a contact dictionary which contains phone no and name then set default Name as
‘Unknown’?
Suppose, Premier League completed, but there are three top goal scorers, who have scored equal No. of
goals = 23. Which player should be awarded? How to solve this problem? Let us see…
4. random.choice() method
Sometimes, while working with dictionaries, we can have a situation in which we need to find a random pair
from dictionary. This type of problem can come in games such as lotteries etc.
Syntax:
import random
random.choice(list(dictionary_name.keys()))
1 import random
2 goal_scorers = {'Salah':13, 'Kane':12, 'Son':12}
3
4 print("The Winner is " ,end="")
5 print(random.choice(list(goal_scorers.keys())))
EXERCISE 12.4
Create a contact dictionary which contains phone no. and name then call to random
contact?
Page 192
Syntax:
dictionary_name.items()
Syntax:
dictionary_name.keys()
Syntax:
dictionary_name.values()
Player-Goal Pair
dict_items([('Salah', 13), ('Kane', 12), ('Son', 12)])
Page 193
EXERCISE 12.5
Create a contact dictionary which contains phone no. and name then print all phone no.
and name of contacts?
There are many ways of deleting & clearing elements from a dictionary. Let’s try to understand each.
Suppose, A player – “Kane” accused for doping, then he disqualified from the league. How to remove him
from top goal scorers dictionary? Let us see…
1. del keyword
del keyword deletes an item of specified key.
Syntax:
del dictionary_name[key]
KeyError: 'Messi'
2. pop() method
This method removes an item of specified key and returns the corresponding value.
Syntax:
dictionary_name.pop(key)
PS. If the specified key is not available, then we will get KeyError.
Page 195
Old Top Goal Scorers
{'Salah': 13, 'Kane': 12, 'Son': 12}
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-35-e34871d094c7> in <cell line: 4>()
2
3 print('Old Top Goal Scorers\n',goal_scorers)
----> 4 goal_scorers.pop('Messi')
5 print('New Top Goal Scorers\n',goal_scorers)
KeyError: 'Messi'
3. popitem() method
This method removes an arbitrary item(key-value) from the dictionary and returns it.
Syntax:
dictionary_name.popitem()
1 p = {}
2
3 p.popitem()
4 print("After popitem:", p)
Page 196
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-38-dde00e1ca7ba> in <cell line: 3>()
1 p = {}
2
----> 3 p.popitem()
4 print("After popitem:", p)
4. clear() method
Clear() method removes all entries in the dictionary. After deleting all entries, it just keeps an empty
dictionary.
Syntax:
dictionary_name.clear()
{}
EXERCISE 12.6
Create a contact dictionary which contains phone no. and name then delete contact of
Abel?
len() function
This function returns the no. of items in a dictionary.
Syntax:
len(dictionary_name)
Page 197
Ex 12.28 ( len() function )
Dictionary Comprehension
Just as we had list comprehensions, we also have this concept applicable for dictionaries even.
Dictionary comprehension is a concise way of creating dictionaries in Python using an iterable object, such as
a list, tuple, or another dictionary. It allows you to create dictionaries with specific key-value pairs based on a
specified condition or transformation.
1 numbers = [1, 2, 3, 4, 5]
2
3 squared_numbers = {i: i**2 for i in numbers}
4 print(squared_numbers)
5 print(type(squared_numbers))
EXERCISE 12.7
Create a dictionary from a list of favorite football players, with player names as keys
and character counts as values using dictionary comprehension?
Hint:
List -> ["Ronaldo", "Messi", "Neymar"]
Dictionary -> {"Ronaldo": 7, "Messi": 5, "Neymar": 6}
Page 198
Key Takeaways
A dictionary is an unordered collection of items.
You can insert elements into a dictionary using the assignment operator and update() method.
You can access dictionary elements using keys, get(), setdefault(), random.choice(),
items(), keys() and values() methods.
You can delete elements from a dictionary using del keyword, pop(), popitem() and clear()
methods.
Dictionary comprehension is a concise way of creating dictionaries in Python using an iterable object.
. asdgh
ashgd
ashgd
asdgv
asdghf
ashdgf
Page 199
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER THIRTEEN
FOURTEEN
Objectives
What are different types of programming paradigms?
What is Object-oriented programming?
What is Class and Object?
What is Constructor?
What is self?
What are class variables?
What is method?
What is static variable?
What are class methods and static methods?
What are local variables?
What are setter and getter methods?
What is Encapsulation?
What is Name Mangling?
What is nested class?
What is garbage collection?
What is inheritance?
What are different types of inheritance?
What is Polymorphism?
What is Overriding?
What is super() function in Python?
What is Overloading?
What is Duck Typing?
What is Abstraction?
What is Interface?
Page 200
Lesson One : Introduction to Object Oriented Programming
All the three approaches mentioned above are programming paradigms. A programming paradigm is nothing
but the style of writing a program. We can also call them as methodologies which are used in writing a
software program. Different languages follow different methodologies.
Functional oriented programming is a program paradigm where programs are built around functions.
Functions can be used as parameters, can be returned, can be used in other functions etc. Here functions are
everything and they should always return the same output for a particular input.
After OOPs
Object-oriented programming (OOP) is a way of organizing and designing computer programs. It focuses on
creating reusable pieces of code called objects, which can be thought of as individual "things" that have
specific characteristics and can perform certain actions.
Python follows both functional oriented and object oriented programming approaches.
The class for a television might include specifications such as the brand name, model number, and screen size.
It would also describe what a television can do, like turning on and off, changing channels, and adjusting the
volume.
Page 201
Based on this blueprint, you can create actual televisions. Each of these televisions is an "object" that follows
the instructions or steps provided by the class. The constructor is like a customized set of instructions that are
executed automatically when a new TV object is created based on the class.
The constructor could be a step where we input the brand, model, and size of the TV. So, when we create a
new TV object using the class, the constructor will be automatically triggered, and the specified values will be
assigned to the respective properties of the TV object.
Just like in the factory, where multiple TVs are made using the same blueprint, you can create multiple TV
objects using the same class.
Each television object you create has its own unique characteristics. For example, one TV object might be a
Samsung brand with a model number "ABC123" and a screen size of 55 inches. Another TV object could be
an LG brand with a model number "XYZ789" and a screen size of 65 inches.
Think of the class as the blueprint that guides the creation of TVs, and the objects as the actual televisions
produced using that blueprint. The class defines what a television is and what it can do, while the objects
represent specific instances of televisions that exist in the real world.
Once you have a television object, you can interact with it. You can turn it on or off, change the channel, or
adjust the volume. These actions are like the behaviors defined in the class. Each television object knows how
to perform these actions because it was created based on the class's instructions.
What is Class?
A class is like a blueprint or a template for creating objects. It defines the properties (also known as attributes
or variables) and behaviors (also known as methods or functions) that objects of that class will have. Think of
a class as a description of what an object should look like and what it should be able to do.
What is Object?
An object, on the other hand, is an instance or a specific occurrence of a class. It is created based on the
blueprint provided by the class. You can think of an object as a real-world example based on a blueprint.
What is Constructor?
Constructor is a special method within a class that is automatically called when an object of that class is
created. It is used to initialize the object's attributes or perform any necessary setup operations. It’s not
required to explicitly invoke or call it.
Page 202
How to de ne a class?
What is self?
self is a default variable that refers to a current class object.
By using a self variable, we can access instance variables and instance methods. It can also be some other
name rather than ‘self’, but the most commonly used and preferred is ‘self’.
Differentiating between Instance and Local Variables: Sometimes, a method (a function inside a
class) might have variables with the same name as the instance variables. Using self helps you
distinguish between these variables and prevents confusion. Without self, you would create new,
separate variables that only exist within the method, and they wouldn't affect the object's attributes.
Method Invocation: When you call a method on an object, you need to use self to refer to that specific
object.
Object Identity: In a store full of televisions, each TV is unique and has its own identity. Similarly,
when you have multiple objects created from the same class, self helps you refer to a particular object
and perform actions on it. It ensures that the correct object is being acted upon and maintains its
individuality.
1 class Television:
2 brand = "Sony"
3
4 def turn_on(self):
5 print(self.brand, "TV is on.")
Page 203
The above example code doesn’t give any output because we haven’t created any object to access the class
members (attributes).
1 my_tv = Television()
2 print(my_tv)
--str--() is one of the magical methods. Whenever we are trying to print any object reference internally,
then this method will be called. It returns output, about the location of the object, in the string format
Syntax:
--str--() method:
1 class Television:
2 brand = "Sony"
3
4 def turn_on(self):
5 print(self.brand, "TV is on.")
6
7 def __str__(self):
8 return (f'This is a {self.brand} Television object')
9
10 my_tv = Television()
11 print(my_tv)
1 type(my_tv)
__main__.Television
Page 204
After creating the object of a class, we can access the attributes available in that class with the created object
as shown below.
object_name.method_name() or class_name.method_name(object_name)
object_name.variable_name
Sony TV is on.
Sony TV is on.
'Sony'
EXERCISE 13.1
Create a class called "Bank" with bank_name property and display_bank() method?
Syntax:
def --init--(self):
// body of constructor
No, it’s not mandatory for a class to have a constructor. It completely is based on our requirement whether to
have a constructor or not. At the time of object creation if any initialization is required then we should go for a
constructor, else it’s not needed.
Page 205
Ex 13.6 ( Define a class with Constructor )
1 class Television:
2 def __init__ (self):
3 print("constructor is executed automatically at the time of TV creation.")
4
5 my_tv = Television()
Yes, we can call constructor explicitly with object name. But since the constructor gets executed
automatically at the time of object creation, it is not recommended to call it explicitly.
1 class Television:
2 def __init__ (self):
3 print("constructor is executed automatically at the time of TV creation.")
4
5 my_tv = Television()
6 my_tv.__init__()
Constructors can be categorized into two types: parameterized and non-parameterized constructors.
1 class Television:
2 def __init__ (self):
3 print("constructor is executed automatically at the time of TV creation.")
4 print(self)
5
6 my_tv = Television()
Page 206
2. Parameterized Constructor
A parameterized constructor is a constructor that takes one or more parameters as input. It allows you to pass
specific values during object creation and use those values to initialize the object's attributes accordingly.
Yes, the main concept of OOPs is class acts as a template for the objects. So, any number of objects can be
created for one class.
1 class Television:
2 def __init__(self, brand, model, screen_size):
3 self.brand = brand
4 self.model = model
5 self.screen_size = screen_size
6 print("This TV is", brand, screen_size,'inch', model)
7
8 salon_tv = Television("Sony", "Class X80K", 65)
9 bedroom_tv = Television("Samsung", "Class N5300 Series", 32)
EXERCISE 13.2
Create a class called "BankAccount" with customer_name and account_number properties and
calculate_balance() method?
Page 207
Lesson Three : Class Variables and Methods
Instance Variables
If the value of a variable is changing from object to object then such variables are called as instance variables.
1. By using a constructor.
2. By using instance methods.
3. By using object name
Since different TV have different brand, model & screen size, so we need to define variable during object
creation
We can declare and initialize instance variables inside a constructor by using self variable.
Every object in Python has an attribute denoted as --dict-- , which python creates internally. This displays
the object information in dictionary form. It maps the attribute name to its value.
1 class Television:
2 def __init__(self, brand, model, screen_size):
3 self.brand = brand
4 self.model = model
5 self.screen_size = screen_size
6
7 salon_tv = Television("Sony", "Class X80K", 65)
8 bedroom_tv = Television("Samsung", "Class N5300 Series", 32)
9 print(salon_tv.__dict__)
10 print(bedroom_tv.__dict__)
1. Instance Methods
2. Class Methods
3. Static Methods
1. Instance Methods
Instance methods are methods which act upon the instance variables of the class. They are bound with
instances or objects, that's why called as instance methods. The first parameter for instance methods should be
self variable which refers to instance. Along with the self variable it can contain other variables as well.
Suppose display and resolution attributes are not part of object creation but display info method, so you
need to declare these variables inside a method.
We can declare and initialize instance variables inside instance method by using self variable.
1 class Television:
2 def __init__(self, brand, model, screen_size):
3 self.brand = brand
4 self.model = model
5 self.screen_size = screen_size
6
7 def display_details(self):
8 self.resolution = "4K"
9 self.display = "LED"
10
11 print("TV Details")
12 print("Model :", self.brand, self.model)
13 print("Screen Size :", self.screen_size, "inch")
14 print("Display :", self.resolution, self.display)
Page 209
1 my_tv = Television("Sony", "Class X80K", 65)
2 my_tv.display_details()
3 print(my_tv.__dict__)
TV Details
Model : Sony Class X80K
Screen Size : 65 inch
Display : 4K LED
{'brand': 'Sony', 'model': 'Class X80K', 'screen_size': 65, 'resolution': '4K', 'display
Price is not part of the TV device and the same brand & model TV can be sold with different price in
different places, so we need to declare price using object name.
We can declare and initialize instance variables by using object name as well
1 class Television:
2 def __init__(self, brand, model, screen_size):
3 self.brand = brand
4 self.model = model
5 self.screen_size = screen_size
6
7 def display_details(self):
8 self.resolution = "4K"
9 self.display = "LED"
10
11 print("TV Details")
12 print("Model :", self.brand, self.model)
13 print("Screen Size :", self.screen_size, "inch")
14 print("Display :", self.resolution, self.display)
15
16 my_tv = Television("Sony", "Class X80K", 65)
17 my_tv.price = 2400
18 print(my_tv.__dict__)
Page 210
Ex 13.13 ( Accessing instance variables )
1 class Television:
2 def __init__(self, model):
3 self.brand = "Sony"
4 self.model = model
5
6 def display_details(self):
7 print("TV Model :", self.model) # accessing instance variable using self
8
9 my_tv = Television("Class X80K")
10 my_tv.display_details()
11 print("This TV brand is", my_tv.brand) # accessing instance variable using object name
Static Variables
If the value of a variable is not changing from object to object, such types of variables are called static
variables or class level variables. We can access static variables either by class name or by object name.
Accessing static variables with class names is highly recommended than object names.
1 class Television:
2 display = "LED"
3
4 print("The TV display is", Television.display) # accessing static variable using class name
5
6 my_tv = Television()
7 print("The TV display is", my_tv.display) # accessing static variable using object name
Generally, we can declare and initialize static variable within the class and outside of the methods. This is the
preferred way.
Ex 13.15 ( Declaring static variable inside class and outside of the method )
1 class Television:
2 display = "LED"
3
4 print(Television.__dict__)
We can declare and initialize static variables within the constructor by using class’s name.
1 class Television:
2 display = "LED"
3
4 def __init__(self):
5 Television.brand = "Sony"
6
7 my_tv = Television()
8 print(Television.__dict__)
We can declare and initialize static variable inside instance method by using class name just as we have done
in the constructor.
1 class Television:
2 display = "LED"
3
4 def __init__(self):
5 Television.brand = "Sony"
6
7 def mute(self):
8 Television.volume = 0
9 print("Volume :", Television.volume)
Page 212
1 my_tv = Television()
2 my_tv.mute()
3 print(Television.__dict__)
Volume : 0
{'__module__': '__main__', 'display': 'LED', '__init__': <function Television.__init__ a
We can declare and initialise static variable inside class method in two ways,
Just as instance methods have self as the default first variable, class method should have cls as the first
variable. Along with the cls variable it can contain other variables as well.
1 class Television:
2 display = "LED"
3
4 def __init__(self):
5 Television.brand = "Sony"
6
7 def mute(self):
8 Television.volume = 0
9 print("Volume :", Television.volume)
10
11 @classmethod
12 def change_mode(cls):
13 Television.mode = "AV"
14 print("Mode :", Television.mode)
15
16 my_tv = Television()
17 my_tv.change_mode()
18 print(Television.__dict__)
Mode : AV
{'__module__': '__main__', 'display': 'LED', '__init__': <function Television.__init__ a
Page 213
We can also do the initialization in the class method using the cls variable. cls is predefined variable in
python. We should pass the cls parameter to the class methods just as we use self for instance methods.
1 class Television:
2 display = "LED"
3
4 def __init__(self):
5 Television.brand = "Sony"
6
7 def mute(self):
8 Television.volume = 0
9 print("Volume :", Television.volume)
10
11 @classmethod
12 def change_mode(cls):
13 Television.mode = "AV"
14 print("Mode :", Television.mode)
15
16 @classmethod
17 def display_details(cls):
18 cls.model = "Class X80K"
19 print("TV Model :", Television.model)
20
21 my_tv = Television()
22 my_tv.display_details()
23 print(Television.__dict__)
We can declare and initialize static variables inside a static method by using class name.
3. Static Method
Static methods are extremely similar to python class level methods, the difference being that a static method
is bound to a class rather than the objects for that class. This means that a static method can be called without
an object for that class. This also means that static methods cannot modify the state of an object as they are
not bound to it.
Page 214
Advantages of Python static method
Static methods have a very clear use-case. When we need some functionality not w.r.t an Object but
w.r.t the complete class, we make a method static. This is pretty much advantageous when we need to
create Utility methods as they aren’t tied to an object lifecycle usually. Finally, note that in a static
method, we don’t need the self to be passed as the first argument.
Before method if we write @staticmethod decorator then that method will become a staticmethod.
1 class Television:
2 display = "LED"
3
4 def __init__(self):
5 Television.brand = "Sony"
6
7 def mute(self):
8 Television.volume = 0
9 print("Volume :", Television.volume)
10
11 @classmethod
12 def change_mode(cls):
13 Television.mode = "AV"
14 print("Mode :", Television.mode)
15
16 @classmethod
17 def display_details(cls):
18 cls.model = "Class X80K"
19 print("TV Model :", Television.model)
20
21 @staticmethod
22 def connect_to_netflix():
23 Television.web_url = "https://netflix.com"
24 print("Connecting to Netflix...")
25
26 Television.connect_to_netflix()
27 print(Television.__dict__)
Connecting to Netflix...
{'__module__': '__main__', 'display': 'LED', '__init__': <function Television.__init__ a
Page 215
Accessing a static variable
We have already discussed with examples, how static variables can be accessed outside of class earlier. Now,
we shall discuss how we can access static variable in (within the class),
Inside constructor
Inside instance method
Inside class method
Inside static method
We can access static variables inside the constructor by using either self or class name.
1 class Television:
2 brand = "Sony"
3 model = "Class X80K"
4 display = "LED"
5 resolution = "4K"
6 width = 16
7 height = 9
8 netflix_web_url = "https://netflix.com"
9
10 def __init__(self):
11 # access inside a constructor
12 print("Display :", self.display, Television.resolution)
13
14 def aspect_ratio(self):
15 #access inside instance method
16 print("Aspect Ratio is", self.width,":", Television.height)
17
18 @classmethod
19 def display_details(cls):
20 # access inside class method
21 print("TV Model :", cls.brand, Television.model)
22
23 @staticmethod
24 def connect_to_netflix():
25 # access inside static method
26 print("Connecting to", Television.netflix_web_url)
27
28 my_tv = Television()
29 my_tv.aspect_ratio()
30 my_tv.display_details()
31 my_tv.connect_to_netflix()
Display : LED 4K
Aspect Ratio is 16 : 9
TV Model : Sony Class X80K
Connecting to https://netflix.com
Page 216
Local Variables
The variable which we declare inside of the method is called a local variable. Generally, for temporary usage
we create local variables to use within the methods. The scope of these variables is limited to the method in
which they are declared. They are not accessible out side of the methods.
1 class Television:
2 volume = 15
3
4 def volume_up(self):
5 min_volume, max_volume = 0, 100 #local variable
6
7 if Television.volume == max_volume:
8 Television.volume == max_volume
9 else:
10 Television.volume += 1
11 print("Volume :", Television.volume)
12
13 my_tv = Television()
14 my_tv.volume_up()
Volume : 16
1 class Television:
2 volume = 15
3
4 def volume_up(self):
5 min_volume, max_volume = 0, 100 #local variable
6
7 if Television.volume == max_volume:
8 Television.volume == max_volume
9 else:
10 Television.volume += 1
11 print("Volume :", Television.volume)
12
13 def volume_down(self):
14 if Television.volume == min_volume: # 'min_volume' is local variable of volume_up()
15 Television.volume == min_volume
16 else:
17 Television.volume += 1
18 print("Volume :", Television.volume)
19
20 my_tv = Television()
21 my_tv.volume_down()
Page 217
-------------------------------------------------------
--------------------
NameError Traceback
(most recent call last)
<ipython-input-17-1946f5a9f7e8> in <cell line: 21>()
19
20 my_tv = Television()
---> 21 my_tv.volume_down()
<ipython-input-17-1946f5a9f7e8> in volume_down(self)
12
13 def volume_down(self):
---> 14 if Television.volume == min_volume:
15 Television.volume == min_volume
16 else:
EXERCISE 13.3
What if you want to check the existence of a channel before changing it?
Setter methods can be used to set values to the instance variables. They are also known as mutator methods.
Their main aim is to only set values to instance variables, hence they don’t return anything.
Syntax:
def set_variable(self, variable_name):
self.variable_name = variable_name
Getter methods are used to get the values of instance variables. They return the value in the instance variable.
Getter methods also known as accessor methods.
Syntax:
def get_variable(self):
return self.variable_name
Page 218
Ex 13.24 ( Setter and Getter Methods )
1 class Television:
2 def __init__(self):
3 self.channels = {1:"Aljezzira", 2:"BBC", 3:"CNN"}
4
5 def change_channel(self, channel):
6 if channel >= 0 and channel < len(self.channels):
7 self.channel = channel
8 channel_name = self.get_channel()
9 print("Now you are watching", channel_name)
10 else:
11 print("Channel does not exist!")
12
13 def get_channel(self):
14 return self.channels[self.channel]
15
16 my_tv = Television()
17 my_tv.change_channel(2)
18
19 my_tv = Television()
20 my_tv.change_channel(5)
EXERCISE 13.4
Create an account number validation class that enforces the following rules:
Example : 100345
Page 219
Lesson Four : Encapsulation
What is Encapsulation?
Encapsulation is a way to restrict the direct access to some components of an object, so users cannot access
state values for all of the variables of a particular object.
Encapsulation can be used to hide both variables and methods associated with an instantiated class or object.
Bene ts of Encapsulation
Data Hiding: Encapsulation allows us to hide internal implementation details from the user, which
makes our code more robust and less prone to errors.
Code Reusability: Encapsulated code can be easily reused, tested, and debugged.
Encapsulation is achieved by using access modifiers. However, Python does not have explicit access
modifiers like public, private, and protected that are found in other object-oriented programming languages
like Java or C++.
Protected: Attributes and methods that are accessible within the class and its subclasses. They are
denoted by a single underscore prefix.
Private: Attributes and methods that are accessible only within the class. They are denoted by a double
underscore prefix.
In Python, when you want to make a variable or method "protected" or "private" within a class, you can give
it a special name. This special name is called "name mangling".
Name mangling is a technique used in Python to create a form of name convention for variables and methods
that are intended to be "protected" or "private" within a class.
In Python, the convention is to use a single leading underscore ( _ ) to indicate that a variable or method is
"protected", and a double leading underscore ( __ ) to indicate that it's "private".
PS. You can modify both protected and private variables outside the class but can't access only private
variable, Which is weird.
Page 220
Ex 13.25 ( Creating public, protected and private attributes )
1 class Television:
2 def __init__(self):
3 self.channel = "BBC" # Public attribute
4 self._volume = 15 # Protected attribute
5 self.__brand = "Sony" # Private attribute
6
7 def turn_on(self):
8 print(f"The {self.__brand} television is now turned on.")
9
10 def _change_channel(self, channel):
11 print(f"The channel has been changed to {channel}.")
12
13 def __adjust_volume(self, volume):
14 print(f"The volume has been adjusted to {volume}.")
15
16 my_tv = Television()
17 print(my_tv)
1 my_tv._change_channel("CNN")
1 my_tv.__adjust_volume(30)
-------------------------------------------------------
--------------------
AttributeError Traceback
(most recent call last)
<ipython-input-5-088d40274ff1> in <cell line: 2>()
1 # calling private method outside a class
----> 2 my_tv.__adjust_volume(30)
1 my_tv._volume = 0
2 print(my_tv._volume)
3
4 my_tv.__brand = "Samsung"
5 print(my_tv.__brand)
Page 221
0
Samsung
The important note here is that name mangling is all about safety and not security. It will not keep you
protected against intentional wrongdoing; just, accidental overriding.
1 print(my_tv._volume)
1 print(my_tv.__brand)
Samsung
As you can see, attempting to access the private variable from outside the class results in an AttributeError.
One way to access it, if that’s necessary, is to create a getter method inside a class that would return the value
of the private variable.
1 class Television:
2 def __init__(self):
3 self.channel = "BBC" # Public attribute
4 self._volume = 15 # Protected attribute
5 self.__brand = "Sony" # Private attribute
6
7 def turn_on(self):
8 print(f"The {self.__brand} television is now turned on.")
9
10 def _change_channel(self, channel):
11 print(f"The channel has been changed to {channel}.")
12
13 def __adjust_volume(self, volume):
14 print(f"The volume has been adjusted to {volume}.")
15
16 def get_brand(self):
17 return self.__brand
18
19 my_tv = Television()
20 print(my_tv.get_brand())
Sony
Page 222
EXERCISE 13.5
Create a "BankAccount" class that has a "balance" property, and ensure that the balance
property cannot be modified outside the class?
Syntax:
class OuterClass:
def __ init__(self):
self.NestedClass = self.NestedClass(self)
// Outer class variables & method
class NestedClass:
// Nested class constructor, variables & method
To create an inner class object, first create an outer class object, then use it to create the inner class object and
access its members.
1 class Television:
2 def __init__(self):
3 self.volume = 15
4 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
5 self.remote = self.Remote(self)
6
7 def turn_on(self):
8 print("The TV is on.")
9
10 class Remote:
11 def __init__(self, television):
12 self.battery_percentage = 100
13 self.television = television
14
15 def change_channel(self, channel):
16 print(f"Changing channel to {self.television.channels[channel]}")
17
18 def increase_volume(self):
19 self.television.volume = self.television.volume + 1
20 print("Increasing volume:", self.television.volume)
21
Page 223
1 tv = Television()
2 tv.turn_on()
3
4 # Using the nested Remote class
5 tv.remote.change_channel(2)
6 tv.remote.increase_volume()
The TV is on.
Changing channel to BBC
Increasing volume: 16
EXERCISE 13.6
In old languages like C++, programmers are responsible for both creation and destruction of objects.
Usually a programmer should take very much care to create objects, and sometimes he may neglect
destruction of useless objects.
Due to this negligence, at a certain point of time there may be a chance, total memory can be filled with
useless objects which creates memory problems and total application will be down with Out of memory error.
But in Python, internally a program will run in background always to destroy useless objects.
So, the chance of failing a Python program with memory problems are very little.
Garbage collection is an automatic process that manages the memory occupied by objects.
Objective:
The main objective of Garbage Collector is to destroy useless objects and freeing up memory for future use. If
an object does not have any reference variable, then that object is eligible for Garbage Collection.
By default, the Garbage collector is enabled, but we can disable it based on our requirement. In order to do so,
we need to import the gc module.
Methods:
1 import gc
2 print(gc.isenabled())
3 gc.disable()
4 print(gc.isenabled())
5 gc.enable()
6 print(gc.isenabled())
False
False
True
What is Inheritance?
Inheritance, in general, is the passing of properties to someone. In programming languages, the concept of
inheritance comes with classes.
The existing class is called a super class or base class or parent class.
Inheritance allows sub classes to inherit the variables, methods and constructors of their super class.
Advantages of Inheritance:
While declaring subclass, we need to pass super class name into subclass’s parenthesis
1 class Television:
2 def __init__(self):
3 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
4
5 def turn_on(self):
6 print("The TV is on.")
7
8 def change_channel(self, channel):
9 self.channel = channel
10 print(f"Changing channel to {self.channels[self.channel]}")
Page 225
1 class Flat_TV():
2 def __init__(self):
3 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
4
5 def turn_on(self):
6 print("The TV is on.")
7
8 def change_channel(self, channel):
9 print(f"Changing channel to {self.channels[channel]}")
10
11 def HDMI_mode(self):
12 self.mode = "HDMI"
13 print("Mode :", self.mode)
14
15 my_tv = Television()
16 my_tv.turn_on()
17 my_tv.change_channel(3)
18
19 my_flat_tv = Flat_TV()
20 my_flat_tv.turn_on()
21 my_flat_tv.change_channel(3)
22 my_flat_tv.HDMI_mode()
The TV is on.
Changing channel to CNN
The TV is on.
Changing channel to CNN
Mode : HDMI
Single inheritance
Multilevel inheritance
Multiple inheritance
Why would we write same functions in two classes, Since we can inherit it?
Single Inheritance
Creating a subclass or child class from a single superclass/parent class is called single inheritance.
Diagrammatic representation of Python Single Inheritance is given below.
Page 226
Syntax:
class Parent_Class:
// Parent class constructor, variables & method
class Child_Class(Parent_Class):
// Child class constructor, variables & method
1 class Television:
2 def __init__(self):
3 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
4
5 def turn_on(self):
6 print("The TV is on.")
7
8 def change_channel(self, channel):
9 self.channel = channel
10 print(f"Changing channel to {self.channels[self.channel]}")
11
12 class Flat_TV(Television):
13 def HDMI_mode(self):
14 self.mode = "HDMI"
15 print("Mode :", self.mode)
16
17 my_flat_tv = Flat_TV()
18 my_flat_tv.turn_on()
19 my_flat_tv.change_channel(3)
20 my_flat_tv.HDMI_mode()
The TV is on.
Changing channel to CNN
Mode : HDMI
EXERCISE 13.7
Create "BankHQ" as child class and "BankBranch" as parent class using single
inheritance?
Page 227
Multi-Level Inheritance
If a class is derived from another derived class then it is called multi level inheritance. Diagrammatic
representation of Python Multilevel Inheritance is given below.
Syntax:
class Grand_Parent_Class:
// Grand Parent class constructor, variables & method
class Parent_Class(Grand_Parent_Class):
// Parent class constructor, variables & method
class Child_Class(Parent_Class):
// Child class constructor, variables & method
1 class Television:
2 def __init__(self):
3 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
4
5 def turn_on(self):
6 print("The TV is on.")
7
8 def change_channel(self, channel):
9 self.channel = channel
10 print(f"Changing channel to {self.channels[self.channel]}")
11
12 class Flat_TV(Television):
13 def HDMI_mode(self):
14 self.mode = "HDMI"
15 print("Mode :", self.mode)
16
17 class Smart_TV(Flat_TV):
18 def connect_to_netflix(self):
19 self.web_url = "https://netflix.com"
20 print("Connecting to Netflix...")
Page 228
1 my_smart_tv = Smart_TV()
2 my_smart_tv.turn_on()
3 my_smart_tv.change_channel(3)
4 my_smart_tv.HDMI_mode()
5 my_smart_tv.connect_to_netflix()
The TV is on.
Changing channel to CNN
Mode : HDMI
Connecting to Netflix...
EXERCISE 13.8
Create "BankHQ" as child class, "BankBranch" as parent class and "BankAccount" as grand
parent class using multilevel inheritance?
Multiple Inheritance
If a child class is derived from multiple superclasses then it is called multiple inheritance. Diagrammatic
representation of Multiple Inheritance is given below.
Syntax:
class Mother_Class:
// Mother Parent class constructor, variables & method
class Father_Class:
// Father class constructor, variables & method
Page 229
What if you want to connect your smart TV with a smart speaker to enjoy the music clip audio?
1 class Television:
2 def __init__(self):
3 self.volume = 15
4 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
5
6 def turn_on(self):
7 print("The TV is on.")
8
9 def change_channel(self, channel):
10 self.channel = channel
11 print(f"Changing channel to {self.channels[self.channel]}")
12
13 class Smart_Speaker:
14 def increase_volume(self):
15 self.volume = self.volume + 1
16 print("Volume :", self.volume)
17
18 class Smart_TV(Television, Smart_Speaker):
19 def connect_to_netflix(self):
20 self.web_url = "https://netflix.com"
21 print("Connecting to Netflix...")
22
23 my_smart_tv = Smart_TV()
24 my_smart_tv.turn_on()
25 my_smart_tv.change_channel(3)
26 my_smart_tv.increase_volume()
27 my_smart_tv.connect_to_netflix()
The TV is on.
Changing channel to CNN
Volume : 16
Connecting to Netflix...
What if both parent classes have a method with the same name? Suppose the television has a speaker, and
the smart speaker also has a speaker. Which speaker's volume are you increasing?
There may be a chance that two parent classes can contain methods which are having the same method name
in both classes. Syntactically this is valid.
Page 230
Ex 13.38 ( Parent classes having same method names )
1 class Television:
2 def __init__(self):
3 self.volume = 15
4 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
5
6 def turn_on(self):
7 print("The TV is on.")
8
9 def change_channel(self, channel):
10 self.channel = channel
11 print(f"Changing channel to {self.channels[self.channel]}")
12
13 def increase_volume(self):
14 self.volume = self.volume + 1
15 print("TV Volume :", self.volume)
16
17 class Smart_Speaker:
18 def increase_volume(self):
19 self.volume = self.volume + 1
20 print("Speaker Volume :", self.volume)
21
22 class Smart_TV(Television, Smart_Speaker):
23 def connect_to_netflix(self):
24 self.web_url = "https://netflix.com"
25 print("Connecting to Netflix...")
26
27 my_smart_tv = Smart_TV()
28 my_smart_tv.turn_on()
29 my_smart_tv.change_channel(3)
30 my_smart_tv.increase_volume()
31 my_smart_tv.connect_to_netflix()
The TV is on.
Changing channel to CNN
TV Volume : 16
Connecting to Netflix...
In the above scenario, you increase the TV volume, not the speaker, because it depends on the order of
inheritance of parent classes in the child class.
Page 231
Ex 13.39 ( Order of inheritance )
1 class Television:
2 def __init__(self):
3 self.volume = 15
4 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN"}
5
6 def turn_on(self):
7 print("The TV is on.")
8
9 def change_channel(self, channel):
10 self.channel = channel
11 print(f"Changing channel to {self.channels[self.channel]}")
12
13 def increase_volume(self):
14 self.volume = self.volume + 1
15 print("TV Volume :", self.volume)
16
17 class Smart_Speaker:
18 def increase_volume(self):
19 self.volume = self.volume + 1
20 print("Speaker Volume :", self.volume)
21
22 class Smart_TV(Smart_Speaker, Television):
23 def connect_to_netflix(self):
24 self.web_url = "https://netflix.com"
25 print("Connecting to Netflix...")
26
27 my_smart_tv = Smart_TV()
28 my_smart_tv.turn_on()
29 my_smart_tv.change_channel(3)
30 my_smart_tv.increase_volume()
31 my_smart_tv.connect_to_netflix()
The TV is on.
Changing channel to CNN
Speaker Volume : 16
Connecting to Netflix...
EXERCISE 13.9
What if both parent and child class have a method with the same name?
Page 232
Lesson Six : Polymorphism
What is Polymorphism?
Polymorphism is the ability of an object to take on many forms. In other words, polymorphism allows objects
of different classes to be treated as if they are of the same class.
1. Overriding
Method Overriding
Constructor Overriding
2. Overloading
Method Overloading
Constructor Overloading
Operator Overloading
1. Overriding
Overriding refers to the process of implementing something again, which already exists in parent class, in
child class.
All the members available in the parent class, those are by-default available to the child class through
inheritance. If the child class is not satisfied with parent class implementation, then child class is allowed to
redefine that method in the child class based on its requirement. This concept is called overriding. Overriding
concept applicable for both methods and constructors.
Method Overriding is the ability of a child class to provide its own implementation of a method that is already
defined in its parent class.
In other words, method overriding allows a child class to "override" or replace the implementation of a
method that it inherits from its parent class.
Page 233
Ex 13.40 ( Method Overriding )
1 class Smart_Speaker:
2 def __init__(self):
3 self.volume = 15
4
5 def increase_volume(self):
6 self.volume = self.volume + 1
7 print(f"Smart Speaker Volume : {self.volume}")
8
9 class Smart_TV(Smart_Speaker):
10 def increase_volume(self):
11 self.volume = self.volume + 1
12 print(f"Smart TV Volume : {self.volume}")
13
14 my_smart_tv = Smart_TV()
15 my_smart_tv.increase_volume()
Smart TV Volume : 16
If child class does not have constructor, then parent class constructor will be executed at the time of child
class object creation. If child class has a constructor, then child class constructor will be executed at the time
of child class object creation.
1 class Smart_Speaker:
2 def __init__(self):
3 self.volume = 15
4
5 def increase_volume(self):
6 self.volume = self.volume + 1
7 print(f"Smart Speaker Volume : {self.volume}")
8
9 class Smart_TV(Smart_Speaker):
10 def __init__(self):
11 self.volume = 20
12
13 def increase_volume(self):
14 self.volume = self.volume + 1
15 print(f"Smart TV Volume : {self.volume}")
16
17 my_smart_tv = Smart_TV()
18 my_smart_tv.increase_volume()
Smart TV Volume : 21
super() is a predefined function in python. By using super() function in child class, we can call,
Ex 13.42 ( Calling super class constructor from child class constructor using super() )
1 class Smart_Speaker:
2 def __init__(self):
3 self.volume = 15
4 print("Default Smart Speaker Volume :", self.volume)
5
6 class Smart_TV(Smart_Speaker):
7 def __init__(self):
8 self.volume = 20
9 super().__init__()
10 print("Smart TV Volume :", self.volume)
11
12 my_smart_tv = Smart_TV()
When both superclass and child class may have the same method names, same variable names, some
scenarios may come where we want to use both of them. In such a case, using the super() function we can call
the parent class method.
Ex 13.43 ( Calling super class method from child class method using super() )
1 class Smart_Speaker:
2 volume = 15
3 def increase_volume(self):
4 self.volume = self.volume + 1
5 print("Smart Speaker Volume :", self.volume)
6
7 class Smart_TV(Smart_Speaker):
8 volume = 20
9 def increase_volume(self):
10 super().increase_volume()
11 print("Smart TV Volume :", self.volume)
12
13 my_smart_tv = Smart_TV()
14 my_smart_tv.increase_volume()
Television Volume : 21
Smart TV Volume : 21
Page 235
What if we want to access parent class method of nested inheritance in child class method?
In the case where the grandparent, parent, and child classes all have a method with the same name,
super(class_name, self).method_name will call the method of super class of mentioned class name.
1 class Speaker:
2 volume = 10
3 def increase_volume(self):
4 self.volume = self.volume + 1
5 print("Speaker Volume :", self.volume)
6
7 class Smart_Speaker(Speaker):
8 volume = 15
9 def increase_volume(self):
10 self.volume = self.volume + 1
11 print("Smart Speaker Volume :", self.volume)
12
13 class Smart_TV(Smart_Speaker):
14 volume = 20
15 def increase_volume(self):
16 super(Smart_Speaker, self).increase_volume()
17 print("Smart TV Volume :", self.volume)
18
19 my_smart_tv = Smart_TV()
20 my_smart_tv.increase_volume()
Speaker Volume : 21
Smart TV Volume : 21
What if both parent and child class have a variable with the same name?
Ex 13.45 ( Calling super class variable from child class method using super() )
1 class Smart_Speaker:
2 volume = 15
3 def increase_volume(self):
4 self.volume = self.volume + 1
5 print("Smart Speaker Volume :", self.volume)
6
7 class Smart_TV(Smart_Speaker):
8 volume = 20
9 def increase_volume(self):
10 self.volume = super().volume + 1
11 print("Smart TV Volume :", self.volume)
12
13 my_smart_tv = Smart_TV()
14 my_smart_tv.increase_volume()
Smart TV Volume : 16
Page 236
Different cases for using super() function
You can access parent class static variables inside child class method.
You can call parent class instance, static & class methods from child class constructor.
You can call parent class instance, static & class methods from child class method.
You can call parent class static method & class method from child class (class method).
But, you can't call parent class instance method & constructor from child class (class method).
Ex 13.46 ( Calling super class instance method from child class (class method) using super() )
1 class Smart_Speaker:
2 volume = 15
3
4 def increase_volume(self):
5 self.volume = self.volume + 1
6 print("Smart Speaker Volume :", self.volume)
7
8 class Smart_TV(Smart_Speaker):
9 volume = 20
10
11 @classmethod
12 def increase_volume(cls):
13 super().increase_volume()
14 print("Smart TV Volume :", Smart_TV.volume)
15
16 my_smart_tv = Smart_TV()
17 my_smart_tv.increase_volume()
-------------------------------------------------------
--------------------
TypeError Traceback
(most recent call last)
<ipython-input-35-0f3ec70c2cdc> in <cell line: 17>()
15
16 my_smart_tv = Smart_TV()
---> 17 my_smart_tv.increase_volume()
<ipython-input-35-0f3ec70c2cdc> in increase_volume(cls)
11 @classmethod
12 def increase_volume(cls):
---> 13 super().increase_volume()
14 print("Smart TV Volume :",
Smart_TV.volume)
15
As discussed above, you can't call parent class instance method & constructor from child class (class
method). But there is way to access them it using cls keyword inside super() .
Page 237
Syntax:
super(child_class_name, cls).method_name(cls)
Ex 13.47 ( Calling super class instance method from child class (class method) using cls )
1 class Smart_Speaker:
2 volume = 15
3
4 def increase_volume(self):
5 self.volume = self.volume + 1
6 print("Smart Speaker Volume :", self.volume)
7
8 class Smart_TV(Smart_Speaker):
9 volume = 20
10
11 @classmethod
12 def increase_volume(cls):
13 super(Smart_TV, cls).increase_volume(cls)
14 print("Smart TV Volume :", Smart_TV.volume)
15
16 my_smart_tv = Smart_TV()
17 my_smart_tv.increase_volume()
EXERCISE 13.10
You are building a banking application and need to create a hierarchy of bank account
classes.
Requirements:
2. Implement a "SavingAccount" class that inherits from "BankAccount" and has the
following additional:
Property: interest_rate
Method: calculate_interest() (calculates the interest earned on the account
balance)
Method: withdraw(amount) (overridden to handle withdrawal limit)
Page 238
What if we have two methods with same name in a single class?
2. Overloading
Overloading in Python is an implementation where a class can have multiple methods with the same name,
but with different parameters.
Method Overloading
Constructor Overloading
Operator Overloading
Method overloading is when a class has multiple methods with the same name, but with different parameters.
But in Python Method overloading is not possible. If we are trying to declare multiple methods with the same
name and different number of arguments, then Python will always consider only the last method.
1 class Television:
2 def __init__(self):
3 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN", 4: "FIFA TV"}
4 self.channel = 3
5
6 def change_channel(self, channel):
7 self.channel = channel
8 print(f"Changing TV channel to {self.channels[self.channel]}")
9
10 def change_channel(self, command):
11 self.command = command
12 if self.command == "Up":
13 self.channel += 1
14 print(f"Changing Smart TV channel to {self.channels[self.channel]}")
15 elif self.command == "Down":
16 self.channel -= 1
17 print(f"Changing Smart TV channel to {self.channels[self.channel]}")
18 else:
19 print("You have pressed wrong button!")
20
21 my_tv = Television()
22 my_tv.change_channel(1)
23 my_tv.change_channel("Up")
Page 239
How we can handle overloaded method requirements in Python?
Most of the time, if a method with a variable number of arguments is required then we can handle it with
default arguments or with a variable length of argument methods.
1 class Television:
2 def __init__(self):
3 self.channels = {1: "Aljezzira", 2: "BBC", 3: "CNN", 4: "FIFA TV"}
4 self.channel = 3
5
6 def change_channel(self, command):
7 if type(command) == int:
8 self.channel = command
9 print(f"Changing TV channel to {self.channels[self.channel]}")
10 elif type(command) == str:
11 self.command = command
12 if self.command == "Up":
13 self.channel += 1
14 print(f"Changing TV channel to {self.channels[self.channel]}")
15 elif self.command == "Down":
16 self.channel -= 1
17 print(f"Changing TV channel to {self.channels[self.channel]}")
18 else:
19 print("You have pressed wrong button!")
20 else:
21 print("Unavailable command!")
22
23 my_tv = Television()
24 my_tv.change_channel(1)
25 my_tv.change_channel("Up")
26 my_tv.change_channel("Down")
27
28 my_tv.change_channel(2.0)
29 my_tv.change_channel("Select")
Constructor overloading is also not possible in Python. If we define multiple constructors, only the last
constructor will be considered.
Page 240
Ex 13.50 ( Constructor Overloading )
1 class Television:
2 def __init__(self, mode):
3 self.mode = mode
4 print(f"TV Mode : {self.mode}")
5
6 def __init__(self, channel, volume):
7 self.channel = channel
8 self.volume = volume
9 print(f"Now, You are watching {self.channel}")
10 print(f"Volume of TV: {self.volume}")
11
12 my_tv = Television("BBC", 15)
13 my_tv = Television("AV")
In the above program only constructor with two arguments is working. But based on our requirement we can
declare constructor with default arguments and variable length arguments.
1 class Television:
2 def __init__(self, mode=None, channel=None, volume=None):
3 self.mode = mode
4 self.channel = channel
5 self.volume = volume
6 print(f"TV Mode : {self.mode}")
7 print(f"Now, You are watching {self.channel}")
8 print(f"Volume of TV: {self.volume}")
9
10 my_tv = Television(mode="AV")
11 print("\n")
12 my_tv = Television(channel="BBC", volume=15)
TV Mode : AV
Now, You are watching None
Volume of TV: None
Page 241
TV Mode : None
Now, You are watching BBC
Volume of TV: 15
If we use the same operator for multiple purposes, then it is nothing but operator overloading.
‘+’ addition operator can be used for Arithmetic addition and String concatenation as well ‘*’ multiplication
operator can be used for multiplication for numbers and repetition for strings, lists, tuples etc
1 print(10 + 20)
2 print("Python" + "Programming")
3 print([1, 2, 3] + [4, 5, 6])
30
PythonProgramming
[1, 2, 3, 4, 5, 6]
1 print(10 * 20)
2 print("Python" * 3)
3 print([1, 2, 3] * 3)
200
PythonPythonPython
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Duck typing refers to the programming style, in which the object passed to a method supports all the attributes
expected from it. The important thing here is not about the object type, but about what attributes and methods
the object supports.
In duck typing, while creating a data, it’s not required to declare the argument type explicitly. Based on
provided value the type will be considered automatically. Since Python is considered as a Dynamically Typed
Programming Language, it follows Duck Typing.
PS. “If it walks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.”
Imagine you want to increase volume of both TV and Speaker with a single common remote control?
Page 242
Ex 13.54 ( Duck typing philosophy )
1 class Television:
2 volume = 20
3 def increase_volume(self):
4 self.volume = self.volume + 1
5 print("Smart TV Volume :", self.volume)
6
7 class Speaker:
8 volume = 15
9 def increase_volume(self):
10 self.volume = self.volume + 1
11 print("Smart Speaker Volume :", self.volume)
12
13 class Remote:
14 def volume_up(self, object):
15 object.increase_volume()
16
17 my_remote_control = Remote()
18 my_tv = Television()
19 my_remote_control.volume_up(my_tv)
20
21 my_speaker = Speaker()
22 my_remote_control.volume_up(my_speaker)
Smart TV Volume : 21
Smart Speaker Volume : 16
In the above program, the function volume_up() takes an object and calls for the increase_volume()
method of it. With duck typing, the function is not worried about what object type of object it is. The only
thing that matters is whether the object has a method with name increase_volume() supported or not.
EXERCISE 13.11
You are working on a banking application and need to implement a system that can handle
different types of accounts (e.g., BankAccount, DebitCard) using a common interface.
Requirements:
Page 243
2. Implement a "DebitCard" class with the following:
What is an Abstraction?
Abstraction is the process of simplifying complex things by focusing on the important parts and hiding
unnecessary details. It allows us to create models or representations of real-world objects or concepts that
capture their essential characteristics.
Just like we use a remote control to operate a TV without knowing the internal circuitry, abstraction lets us
use objects and functions in our code without understanding how they are implemented behind the scenes. We
work with a higher-level view that provides the necessary functionality while hiding the complexity.
Abstraction helps programmers to organize code, make it easier to understand, and promote reusability. It
allows us to focus on what needs to be done rather than how it's done, enabling efficient problem-solving and
creating more maintainable and flexible software.
Based on the implementation the methods can be divided into two types:
Implemented methods
Un-implemented methods
Page 244
1. Implemented methods:
A method which has a both method name and method body, that method is called an implemented method.
They are also called concrete methods or non-abstract methods. The methods which we have seen in the
previous chapters are implemented i.e having method name and body as well.
2. Un-implemented methods:
A method which has only method name and no method body, that method is called an unimplemented
method. They are also called as non-concrete or abstract methods.
An abstract method is a method that is declared in a class, but has no implementation. It is a method that has
no body and exists only as a declaration.
Syntax:
from abc import ABC, abstractmethod
class Class_Name:
def --init--(self):
// body of constructor
@abstractmethod
def Unimplemented_Method_Name(self):
pass
def Implemented_Method_Name(self):
print("implemented method")
An abstract class is like a general template or blueprint for a group of related objects. It defines common
characteristics and behaviors that these objects should have. However, an abstract class itself cannot be
directly used to create objects.
Class which contains one or more abstract methods is called an abstract class. Abstract class can contain
Constructors, Variables, abstract methods, non-abstract methods, and Subclass.
PS. A method which has implementation in the abstract class is called as Concrete Method.
Page 245
Let's consider the example of a television. A television can have various types like Smart TV, LED TV, or
Plasma TV. While they may have some common features like powering on, powering off, and changing
channels, each type of television can have its own specific behaviors or additional features.
Since abstract method is an unimplemented method, we need to put a pass statement, else it will result
in error.
Abstract methods should be implemented in the subclass or child class of the abstract class.
If the implementation of the abstract method is not provided in subclass, then that subclass,
automatically, will become an abstract class.
Then, if any class is inheriting this subclass, then that subclass should provide the implementation for
abstract methods.
An abstract class can contain more than one subclass. If different child classes require different kinds of
implementations, in that case an abstract class can contain more than one subclass.
If any class is inheriting ABC class, and that class doesn’t contain an abstract method, then we can
create an object to that class.
If any class is not inheriting ABC class, then we can create an object for that class even though it
contains an abstract method.
We can create objects for child classes of abstract classes to access implemented methods.
Page 246
1 class SmartTV(Television):
2 def increase_volume(self):
3 self.volume += 1
4 print("Smart TV Volume :", self.volume)
5
6 def decrease_volume(self):
7 self.volume -= 1
8 print("Smart TV Volume :", self.volume)
9
10 my_smart_tv = SmartTV()
11 my_smart_tv.power_on()
12 my_smart_tv.increase_volume()
13 my_smart_tv.decrease_volume()
Page 247
1 my_tv_remote = Remote()
2 my_tv_remote.power_on()
3 my_tv_remote.change_channel(2)
An abstract class is a class which can contains few implemented methods and few unimplemented methods as
well. When we know about requirements partially, but not completely, then we should go for abstract class.
Concrete class is a class which is fully implemented. It contains only implemented methods. When we know
complete implementation about requirements, then we should go for concrete class.
We have discussed that an abstract class is a class which may contain some abstract methods as well as non-
abstract methods also. Imagine there is an abstract class which contains only abstract methods and doesn’t
contain any concrete methods, such classes are called Interfaces. Therefore, an interface is nothing but an
abstract class which can contains only abstract methods.
Points to Remember:
Page 248
1 class SmartTV(Television):
2 def power_on(self):
3 print("The TV is powered on.")
4
5 def increase_volume(self):
6 self.volume += 1
7 print("Smart TV Volume :", self.volume)
8
9 def decrease_volume(self):
10 self.volume -= 1
11 print("Smart TV Volume :", self.volume)
12
13 my_smart_tv = SmartTV()
14 my_smart_tv.power_on()
15 my_smart_tv.increase_volume()
16 my_smart_tv.decrease_volume()
Since, Interfaces will not contain implemented methods, when we don't know anything about implementation
of requirements, then we should go for interfaces.
EXERCISE 13.12
You are building a banking application and need to create an abstract base class for
bank accounts with common functionality.
Requirements:
deposit(amount): Deposits specified amount into the account and print it.
withdraw(amount): Withdraws specified amount from the account.
get_balance(): Returns the current balance of the account.
calculate_interest(): Calculates the interest earned on the account balance.
Page 250
Machine Learning from Scratch with Python, Scikit-Learn & PyTorch by Bemnet Girma
CHAPTER FOURTEEN
Exception Handling
Objectives
What is Error?
What are types of error in programming?
What are Syntax Error?
What are Runtime Error?
What are types of program execution flow?
What is an Exception?
What is the difference between error and exception?
What is Exception Handling?
How to Handle Exception in Python?
What is finally Block?
What are types of exception?
What are Predefined Exceptions?
What are Custom Exceptions?
Exception handling is a way to deal with unexpected or exceptional situations that can occur while running a
program. It helps you handle errors and prevent your program from crashing.
Think of it this way: Imagine you're following a recipe to bake a cake. As you go step by step, you may
encounter unexpected situations like running out of a specific ingredient or accidentally burning the cake.
Exception handling is like having a backup plan or alternative actions to take when these unexpected
situations happen.
Page 251
In programming, similar unexpected situations can occur. For example, you might try to open a file that
doesn't exist, divide a number by zero, or receive invalid input from a user. These situations can cause errors,
and if not handled properly, they can cause your program to stop working.
What is Error?
An error refers to an unexpected or exceptional condition that occurs during the execution of a program.
Errors can arise due to various reasons, such as invalid input, resource unavailability, programming mistakes,
or external factors beyond the program's control.
When an error occurs, it disrupts the normal flow of the program and can lead to undesired or incorrect
behavior.
To handle these situations, you use exception handling. It allows you to anticipate and catch these errors, and
instead of letting your program crash, you can take control and respond in a more controlled and graceful
manner.
Types of Error:
In any programming language there are two types of errors. They are:
Syntax Errors
Runtime Errors
1. Syntax Errors
The errors which occur because of invalid syntax are called syntax errors.
1 speed = 113
2 if speed > 113
3 print("Driving beyond the speed limit!")
Here we missed to place a colon in the if condition, which is violating the syntax. Hence, syntax error.
The programmer is responsible to correct these syntax errors. Once all syntax errors are corrected then only
program execution will be started.
Page 252
2. Runtime Errors
While executing the program if something goes wrong then we will get Runtime Errors. They might be
caused due to,
Let's say you are working on a program that calculates the average speed of a moving object based on the
distance traveled and the time taken.
The formula for calculating average speed is: speed = distance / time
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4
5 speed = distance / time
-------------------------------------------------------
--------------------
ZeroDivisionError Traceback
(most recent call last)
<ipython-input-10-c2a3b7613add> in <cell line: 5>()
3 fuel_consumed = 10
4
----> 5 speed = distance / time
PS. Exception Handling concept applicable for Runtime Errors but not for syntax errors.
Based on the success of execution, the program execution flow can be categorized into two types:
In a program if all statements are executed as per the conditions, successfully and we get output then that flow
is called as normal flow of the execution. Below program will get executed successfully from starting to
ending.
Page 253
Ex 14.3 ( Normal Flow )
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4
5 speed = distance / time
6 print(f"Speed = {speed} mph")
7 mileage = distance / fuel_consumed
8 print(f"Mileage = {mileage} MPG")
If any error occurs at runtime (executing code) then immediately program flow gets terminated abnormally,
without executing the other statements. This kind termination is called an abnormal flow of the execution.
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4
5 speed = distance / time
6 print(f"Speed = {speed} mph")
7 mileage = distance / fuel_consumed
8 print(f"Mileage = {mileage} MPG")
-------------------------------------------------------
--------------------
ZeroDivisionError Traceback
(most recent call last)
<ipython-input-13-92efc4d8ad54> in <cell line: 5>()
3 fuel_consumed = 10
4
----> 5 speed = distance / time
6 print(f"Speed = {speed} mph")
7 mileage = distance / fuel_consumed
The above program terminated in the middle where run time error occurred. As discussed, if runtime error
occurs it won’t execute remaining statements.
What is an Exception?
An unwanted or unexpected event which disturbs the normal flow of the program is called exception.
Whenever an exception occurs, then immediately program will terminate abnormally. In order to get our
program executed normally, we need to handle those exceptions on high priority.
Page 254
What is the difference between error and exception?
Errors and exceptions are both problems that can happen in a program. The difference is how they are dealt
with.
Errors are major problems that stop the program from running correctly. These are usually caused by bugs in
the code or issues with the system the program is running on. Once an error happens, the program cannot
continue.
Exceptions are a specific type of problem that can be fixed. They interrupt the normal way the program
works. However, the program can catch and handle exceptions. This allows the program to deal with the
problem and keep running.
Exception handling does not mean repairing or correcting the exception. Instead, it is the process in which we
define a way, so that the program doesn’t terminate abnormally due to the exceptions.
In python, for every exception type, a corresponding class is available and every exception is an object to its
corresponding class. Whenever an exception occurs, Python Virtual Machine (PVM) will create the
corresponding exception object and will check for handling code.
If handling code is not available, then Python interpreter terminates the program abnormally and prints
corresponding exception information to the console. The rest of the program won’t be executed.
Exception Hierarchy:
Note: Every Exception in Python is a class. The BaseException class is the root class for all exception classes
in python exception hierarchy and all the exception classes are child classes of BaseException. The
Programmers need to focus and understand clearly the Exception and child classes.
Page 255
Lesson Two : Exception Handling Using try except Block
The try-except block is used to catch and handle exceptions. It allows you to write code that may
potentially raise an exception within the try block and specify how to handle the exception within the except
block.
try block: try is a keyword in python. The code which may or expected to raise an exception, should
be written inside the try block.
except block: except is a keyword in python. The corresponding handling code for the exception, if
occured, needs to be written inside the except block.
Syntax:
try:
// code which may raise an exception
except Exception:
// exception handling code
How it works?
If an exception is raised in the try block, the code execution within the try block is immediately halted,
and the program flow is transferred to the corresponding except block that matches the raised exception.
Any code that follows the problematic code within the try block will not be executed.
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 except ZeroDivisionError:
9 print("Exception Passed")
10
11 mileage = distance / fuel_consumed
12 print(f"Mileage = {mileage} MPG")
Exception Passed
Mileage = 12.0 MPG
Page 256
If there is no exception, then should be normal flow with normal termination. In this case, the except block
won’t execute.
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 except ZeroDivisionError:
9 print("Exception Passed")
10
11 mileage = distance / fuel_consumed
12 print(f"Mileage = {mileage} MPG")
If an exception occurs before the try block then the program terminates abnormally. Only the code inside the
try block will be checked for the exception and its handling code. But, if there is any exception for the code
before the try block, then abnormal termination
1 distance = 120
2 time = 0
3 fuel_consumed = 0
4
5 mileage = distance / fuel_consumed
6 print(f"Mileage = {mileage} MPG")
7
8 try:
9 speed = distance / time
10 print(f"Speed = {speed} mph")
11 except ZeroDivisionError:
12 print("Exception Passed")
13
14 print("Fuel Level = Low")
Page 257
-------------------------------------------------------
--------------------
ZeroDivisionError Traceback
(most recent call last)
<ipython-input-17-482d110ccb2d> in <cell line: 5>()
3 fuel_consumed = 0
4
----> 5 mileage = distance / fuel_consumed
6 print(f"Mileage = {mileage} MPG")
7
EXERCISE 14.1
Write a Python function that takes a list and an index as input, and returns the element
at the specified index. If the user tries to access an index that is out of range, the
function should catch the IndexError and print an appropriate error message?
In the above examples, in the exception handling code, we are printing our custom message like “Exception
Passed” etc. Rather than that, we can also print exception information by creating a reference to the exception.
Syntax:
except Exception as e:
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 except ZeroDivisionError as e:
9 print("Exception Information:", e)
10
11 mileage = distance / fuel_consumed
12 print(f"Mileage = {mileage} MPG")
Page 258
EXERCISE 14.2
Write a Python function that takes a dictionary and a key as input, and returns the
value associated with the key. If the user tries to access a key that does not exist in
the dictionary, the function should catch the KeyError and print an appropriate error
message?
In python, try with multiple except blocks are allowed. Sometimes, there may be the possibility that a piece of
code can raise different exceptions in different cases. In such cases, in order to handle all the exceptions, we
can use multiple except blocks. So, for every exception type a separate except block we have to write.
Syntax:
try:
code which may raise an exception
except Exception 1:
Exception 1 handling code
except Exception 2:
Exception 1 handling code
Page 259
Can we handle multiple exceptions in a single except block?
Rather than writing different except blocks for handling different exceptions, we can handle all them in one
except block. The only thing is we will not have the flexibility of customizing the message for each exception.
Rather, we can take the reference to the exception and print its information as shown in one of the examples
above.
Syntax:
except (Exception 1, Exception 2, Exception 3, ...) as e:
Parenthesis are mandatory, and this group of exceptions is internally considered as tuple.
EXERCISE 14.3
Write a Python function that takes a temperature value and a temperature scale (Celsius,
Fahrenheit, or Kelvin) as input, and converts the temperature to the other two scales?
What if we don't know the exception type occured in the try block? Page 260
Default except Block:
We can use default except block to handle any type of exceptions. It’s not required to mention any exception
type for the default block. Whenever we don’t have any idea of what expectation the code could raise, then
we can go for default except block.
We know that we can have multiple except blocks for a single try block. If the default except block is one
among those multiple ones, then it should be at last, else we get SyntaxError.
Page 261
EXERCISE 14.4
Write a Python function that takes a string as input and converts it to an integer. If
the user inputs a string that cannot be converted to an integer, the function should
catch the ValueError and print an appropriate error message. The function should also
handle any other exceptions that might occur, such as TypeError if the user inputs a non-
string value?
In any project after completing the tasks, it is recommended to destroy all the unwanted things that are created
for the completion of the task. For example, if I have opened a database connection in my code and done
some tasks related to the database. After the tasks are completed, it is recommended to close the connection.
These clean-up activities are very important and should be handled in our code.
finally is a keyword in python which can be used to write a finally block to do clean-up activities.
try block: There is no guarantee like every statement will be executed inside the try block. If an
exception is raised at the second line of code in the try block at, then the remaining lines of code in that
block will not execute. So, it is not recommended to write clean up code inside the try block.
except block: There is no guarantee that an except block will execute. If there is no exception then
except block won’t be executed. Hence, it is also not recommended to write clean up code inside except
block.
So, a separate block is required to write clean-up activities. This block of code should always execute
irrespective of the exceptions. If no exception, then clean-up code should execute. If an exception is raised
and is also handled , then also clean-up code should execute. If an exception is raised, but not handled, then
also clean-up code should execute.
All the above requirements, which can’t be achieved by try except block, can be achieved by finally block.
The finally block will be executed always, irrespective of the exception raised or not, exception handled or
not.
Page 262
Case 1: If there is no exception, then finally block will execute.
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9 except ZeroDivisionError as e:
10 print("Exception Information:", e)
11 finally:
12 # cleanup and reset everything
13 Power = False
14 distance = 0
15 time = 0
16 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Case 2: If an exception is raised and handled with except block, then also finally block will be executed.
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9 except ZeroDivisionError as e:
10 print("Exception Information:", e)
11 finally:
12 # cleanup and reset everything
13 Power = False
14 distance = 0
15 time = 0
16 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Page 263
Case 3: If an exception raised inside try block but except block doesn’t handle that particular exception, then
also finally block will be executed.
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9 except ValueError as e:
10 print("Exception Information:", e)
11 finally:
12 # cleanup and reset everything
13 Power = False
14 distance = 0
15 time = 0
16 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
EXERCISE 14.5
Write a Python program that takes a series of numbers from user, and then calculates the
average of the numbers. If the user enters a non-numeric value, the program should catch
the ValueError and prompt the user to enter a valid number. Ensure that the program
continues to take input from the user, even if an exception is raised, by using the
finally clause?
Page 264
Nested try-except-finally blocks:
In python nested try except finally blocks are allowed. We can take try-except-finally blocks inside try block.
We can take try-except-finally blocks inside except block. We can take try-except-finally blocks inside finally
block
Case 1: If no exception raised then outer try, inner try, inner finally, outer finally blocks will get executed.
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9
10 try:
11 mileage = distance / fuel_consumed
12 print(f"Mileage = {mileage} MPG")
13
14 except ZeroDivisionError:
15 print(f"Can't divide {distance} by {fuel_consumed}.")
16
17 except:
18 print("Default Exception: Please provide valid input only!")
19
20 finally:
21 # cleanup and reset everything
22 Power = False
23 distance = 0
24 time = 0
25 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Case 2: If an exception is raised in an outer try, then outer except blocks are responsible to handle that
exception.
Page 265
Ex 14.17 ( Nested blocks with exception raised in outer try )
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4 Power = True
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 try:
9 mileage = distance / fuel_consumed
10 print(f"Mileage = {mileage} MPG")
11 except ZeroDivisionError:
12 print(f"Can't divide {distance} by {fuel_consumed}.")
13 except:
14 print("Default Exception: Please provide valid input only!")
15 finally:
16 # cleanup and reset everything
17 Power = False
18 distance = 0
19 time = 0
20 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Case 3: If an exception raised in inner try block then inner except block is responsible to handle, if it is
unable to handle then outer except block is responsible to handle.
1 distance = 120
2 time = 2
3 fuel_consumed = 0
4 Power = True
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 try:
9 mileage = distance / fuel_consumed
10 print(f"Mileage = {mileage} MPG")
11 except ZeroDivisionError:
12 print(f"Can't divide {distance} by {fuel_consumed}.")
13 except:
14 print("Default Exception: Please provide valid input only!")
15 finally:
16 # cleanup and reset everything
17 Power = False
18 distance = 0
19 time = 0
20 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Page 266
Speed = 60.0 mph
Can't divide 120 by 0.
Power = False, Distance = 0 miles, Time = 0 Hrs
1 distance = 120
2 time = 2
3 fuel_consumed = 0
4 Power = True
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 try:
9 mileage = distance / fuel_consumed
10 print(f"Mileage = {mileage} MPG")
11 except ValueError:
12 print(f"Can't divide {distance} by {fuel_consumed}.")
13 except:
14 print("Default Exception: Please provide valid input only!")
15 finally:
16 # cleanup and reset everything
17 Power = False
18 distance = 0
19 time = 0
20 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
EXERCISE 14.6
Write a Python function that takes length & width of a rectangle as input to calculate
area? The function should handle the following exceptions using nested try except block:
Yes, we can use else blocks with try-except-finally blocks. The else block will be executed if and only if there
are no exceptions inside the try block. If no exception then try, else and finally blocks will get executed.
Page 267
What if you want to convert the speed from mph to km/hr?
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9 except ZeroDivisionError:
10 print(f"Can't divide {distance} by {fuel_consumed}.")
11 else:
12 speed_in_kmph = speed * 1.60934
13 print(f"Speed in kmph = {speed_in_kmph} km/hr")
14 finally:
15 # cleanup and reset everything
16 Power = False
17 distance = 0
18 time = 0
19 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
If an exception is raised inside the try block, then the except block will get executed but the else block won’t.
1 distance = 120
2 time = 0
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9 except ZeroDivisionError:
10 print(f"Can't divide {distance} by {fuel_consumed}.")
11 else:
12 speed_in_kmph = speed * 1.60934
13 print(f"Speed in kmph = {speed_in_kmph} km/hr")
14 finally:
15 # cleanup and reset everything
16 Power = False
17 distance = 0
18 time = 0
19 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Only try block is invalid, only except block is invalid, only finally block is invalid.
try with except combination is valid → try block follows except block.
try with finally combination is valid → try block follows finally block.
try , except and else combination is valid → try , except blocks follows else block.
1 try:
2 speed = distance / time
3 print(f"Speed = {speed} mph")
1 except:
2 print("Default Exception: Please provide valid input only!")
1 finally:
2 # cleanup and reset everything
3 Power = False
4 distance = 0
5 time = 0
6 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
Page 269
Ex 14.25 ( try with except combination )
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 except ZeroDivisionError:
9 print(f"Can't divide {distance} by {fuel_consumed}.")
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4 Power = True
5
6 try:
7 speed = distance / time
8 print(f"Speed = {speed} mph")
9 finally:
10 # cleanup and reset everything
11 Power = False
12 distance = 0
13 time = 0
14 print(f"Power = {Power}, Distance = {distance} miles, Time = {time} Hrs")
1 distance = 120
2 time = 2
3 fuel_consumed = 10
4
5 try:
6 speed = distance / time
7 print(f"Speed = {speed} mph")
8 except ZeroDivisionError:
9 print(f"Can't divide {distance} by {fuel_consumed}.")
10 else:
11 speed_in_kmph = speed * 1.60934
12 print(f"Speed in kmph = {speed_in_kmph} km/hr")
Write a Python function that takes an amount and a currency code as input, and returns
the equivalent amount in a target currency?
try block: Attempt to retrieve the exchange rate for the given currency code from a
dictionary.
except block: Catch any KeyError caused by accessing a currency does not exist in
the dictionary.
else block: Execute code to perform the currency conversion and return the result.
Exceptions can be classified into two types based on how they are defined and used in the context of
exception handling:
1. Custom Exceptions
2. Predefined Exceptions.
The exceptions which we handled in the examples till now are predefined ones. They are already available
builtin exceptions. If any exception occurs, then Python Virtual Machine will handle those exceptions using
the predefined exceptions.
Sometimes based on project requirement, a programmer needs to create his own exceptions and raise
explicitly for corresponding scenarios. Such types of exceptions are called customized Exceptions or
Programmatic Exceptions. We can raise a custom exception by using the keyword raise .
The first step is to create a class for our exception. Since all exceptions are classes, the programmer is
supposed to create his own exception as a class. The created class should be a child class of in-built
“Exception” class.
Page 271
Syntax:
class Exception_Name(exception):
def --init--():
self.arf = arg
In the second step raise the exception where it required. When the programmer suspects the possibility of
exception, then he can raise his own exception using raise keyword
Syntax:
raise Exception_Name("message")
1 class NegativeError(Exception):
2 def __init__(self, data):
3 self.data = data
4 try:
5 distance = int(input("Enter the distance: "))
6 if distance < 0:
7 raise NegativeError(distance)
8 except NegativeError as e:
9 print(f"You provided {e}. Please provide positive integer values only")
1 class NegativeDistanceException(Exception):
2 def __init__(self, message):
3 self.msg = message
4
5 class NegativeTimeException(Exception):
6 def __init__(self, message):
7 self.msg = message
8
9 distance = int(input("Enter distance in miles:\n"))
10 time = int(input("Enter time in hours:\n"))
11
12 if distance < 0:
13 raise NegativeDistanceException("The distance you provide is negative!")
14 elif time < 0:
15 raise NegativeTimeException("The time you provide is negative!")
16 else:
17 print("Please provide only valid inputs! and Try again!")
Page 272
Enter distance in miles:
100
Enter time in hours:
-2
-------------------------------------------------------
--------------------
NegativeTimeException Traceback
(most recent call last)
<ipython-input-75-98792ac33b72> in <cell line: 12>()
13 raise NegativeDistanceException("The
distance you provide is negative!")
14 elif time < 0:
---> 15 raise NegativeTimeException("The time you
provide is negative!")
16 else:
17 print("Please provide only valid inputs! and
EXERCISE 14.8
Write a Python function that takes a password as input and validates it against the
following rules:
Key Takeaways
An error is an unexpected or exceptional condition that occurs during the execution of a program.
There are two types of errors in programming; Syntax error and Runtime error.
The error which occurs because of invalid syntax is called syntax error.
Runtime error is an error that occurs during the execution of a program.
Based on the success of execution, the program execution flow can be categorized into two types:
Normal Flow and Abnormal Flow.
An unwanted or unexpected event which disturbs the normal flow of the program is called exception.
Errors indicate serious issues that cannot be fixed, while exceptions deal with specific problems that
can be resolved.
Exception handling is a way to deal with unexpected or exceptional situations that can occur while
running a program.
Page 273
The try-except block is used to catch and handle exceptions.
finally is a keyword which can be used to write a finally block to do clean-up activities.
Exceptions can be divided into two types: Custom Exceptions and Predefined Exceptions.
Predefined exceptions are exceptions that are already defined as part of the programming language or
framework.
Custom exceptions are programmer-defined exceptions used to handle specific exceptional conditions
or errors.
Page 274
QUICK REFERENCE
A
• Abnormal flow refers to the termination of a program's normal execution due to the occurrence
of a runtime error or exception, without completing the remaining statements.
• Abstraction is the process of simplifying complex things by focusing on the important parts and
hiding unnecessary details.
• add() is a method used to add individual items to a set.
• Aliasing is the process of giving a new name to an existing one.
• append() is a method we can add elements to the list.
• Argument is a variable (which contains data) or a parameter which is sent to the function as
input
• Arithmetic operators perform basic mathematical calculations such as +, -, x, and %.
• Assignment operators assign values to variables using the '=' symbol.
B
• Bitwise Operators are operators used to perform bitwise calculations on integers.
• break statement is a statement that terminates a loop.
C
• Class is like a blueprint or a template for creating objects.
• Class methods are methods which act upon the class variables or static variables of the class.
• Class variables are variables that are defined within a class.
• clear() is a method used to remove all the elements from a sequence-based data structure.
• Cloning is the process of creating duplicate independent objects.
• Comment is a programmer-readable explanation or annotation in the source code.
• Compiler is a program that translates code written in one programming language into a
language that a computer can understand and execute.
• Compound operators combine arithmetic and assignment operators (+=, -=, =, /=, %=, *=, //=).
• Conditional Statements are statements executed based on the condition.
• Constructor is a special method within a class that is automatically called when an object is
created.
• continue statement is a statement that skips the rest of the code for the current iteration.
• copy() is a method used to copy all the elements from one list to another.
• count() is a method to find the number of occurrences of element present in the sequence-based
data structure.
• Custom exceptions are programmer-defined exceptions used to handle specific exceptional
conditions or errors.
D
• Data Structure is a particular way of organizing data in a computer.
• Data Type is type of data that to be stored in a variable.
• Decorator is a special function which adds some extra functionality to an existing function.
Page 275
• del is a statement used to delete an element at a given index.
• Dictionary comprehension is a concise way of creating dictionaries in Python using an iterable
object.
• Dictionary is an unordered collection of items.
• difference_update() is method which updates the set calling difference_update() method with
difference of sets.
• difference() is a method which returns the elements present in set A but not in set B.
• discard() is a method removes the specified element from the set. If the specified element is not
present in the set, then we won’t get any error.
• Duck typing is a programming style, in which the object passed to a method supports all the
attributes expected from it.
E
• Encapsulation is a way to restrict the direct access to some components of an object.
• Error is an unexpected or exceptional condition that occurs during the execution of a program.
• eval() function takes the expression in the form of string and evaluates it and returns the result.
• Exception handling is a way to deal with unexpected or exceptional situations that can occur
while running a program.
• Exception is unwanted or unexpected event which disturbs the normal flow of the program.
• extend() is a method used to append the elements from one list to the end of another list.
F
• finally is a keyword which can be used to write a finally block to do clean-up activities.
• find() is a method that returns an index of the first occurrence of the given substring.
• for loop is a control flow statement that allows you to execute a block of code a specific number
of times.
• Frozen set is similar to a set, but it is immutable, meaning its elements cannot be changed after
creation.
• Function is a group of statements or a block of code to perform a certain task.
• Functional oriented programming is a program paradigm where programs are built around
functions.
G
• Garbage collection is an automatic process that manages the memory occupied by objects
• Generators are just like functions which give us a sequence of values one as an iterable.
• get() is a method used to get the value associated with the key in a dictionary.
• Getter methods are methods which are used to get values of instance variables.
I
• IDE is a graphic interface to write, run, debug and also convert code to machine code.
• Identity operators compare the memory location (address) of two variables to check for identity.
• Indentation is the spaces at the beginning of a code line to indicate a block of code.
• index() is a method to find a substring in forward direction.
• Indexing refers to the position of characters within a string.
• Infinite loop is a loop that never ends because its condition never becomes false.
• Inheritance is the process of creating new classes from already existing classes.
Page 276
• input() is a function that can accept values from a user (you).
• insert() is a method used to add the elements to the list at the specified index (position).
• Interface is an abstract class which contains only abstract methods and doesn’t contain any
concrete methods.
• Interpreter is a program that directly executes code written in a programming language without
prior translation into a machine-readable form.
• intersection_update() is a method which updates the set calling intersection_update() method
with the intersection of sets.
• intersection() is a method which returns common elements present in both set A and set B.
• isdisjoint() is a method which returns True if two sets are disjoint sets. If not, it returns False.
• issubset() is a method which returns True if all elements of a set are present in another set. If
not, it returns False.
• issuperset() is a method which returns True if a set has every elements of another set. If not, it
returns False.
• items() is a method which returns list of tuples representing key-value pairs.
J
• join() is a method used to join a group of strings (list or tuple) with respect to the given
separator.
• Jupyter Notebook is a popular IDE for data science and machine learning tasks.
K
• keys() is a method which returns all keys.
• Keywords are special reserved words, that have specific meanings and purposes.
L
• Lambda function is a short anonymous function that can be defined inline without a name.
• len() is a method used to get the length or the number of items in a given sequence.
• List comprehension is a concise way of creating lists using iterable objects like tuples, strings,
and lists.
• List is a data structure which can store a group of elements or objects in a single variable.
• Local variables are variable which we declare inside of the method.
• Logical Operators are operators which do some logical operation on the operands and return
True or False.
• Loop is a repetitive construction in programming.
M
• max() is a method used to find the maximum value from the given sequence.
• Membership operators are operators which are used to check whether an element is present in
a sequence of elements or not.
• Method is a function that is associated with a specific object or class.
• min() is a method used to find the minimum value from the given sequence.
N
• Name mangling is a technique used to create "protected" or "private" attributes within a class.
• Nested class is a class inside another class.
Page 277
• Nested function is a function that is defined inside another function.
• Nested if statement is an if statement inside another if statement.
• Nested list is a list within another list.
• Nested loop is a loop that is written inside another loop.
• Normal flow refers to the successful execution of a program's statements without any
interruptions or errors, resulting in the expected output.
O
• Object is instance of a class.
• Object-oriented programming (OOP) is a way of organizing and designing computer programs.
• Operator is a symbol used to perform actions or operations on variables.
• Overloading is the ability to define multiple methods in a class with the same name but different
parameters.
• Overriding is the process of redefining a method in a child class that already exists in the parent
class.
P
• pass statement is a statement used as a placeholder.
• Polymorphism is the ability of an object to take on many forms.
• pop() is a method used to remove and return an item from a list, set, or dictionary.
• popitem() is a method used to remove an arbitrary item(key-value) from the dictionary and
returns it.
• Predefined exceptions are exceptions that are already defined as part of the programming
language or framework.
• print() is a function that can print the specified message to your computer screen.
• Procedural programming is like following a step-by-step procedure or a set of instructions.
• Programming is the process of preparing an error-free program for a device.
• Programming language is a formal language to communicate with a computer through
instructions.
• Python is a high-level programming language known for its simplicity and readability.
R
• random.choice() is a method used to randomly select and return an item from a sequence.
• Recursive function is a function when it is called by itself.
• Relational operators check relations between operands, such as greater than or less than.
• remove() is a method used to randomly select and return an item from a sequence.
• replace() is a method used to replace old string with new string.
• reverse() is a method which reverses the order of list elements.
• Runtime error is an error that occurs during the execution of a program.
S
• self is a default variable that refers to a current class object.
• Set is a collection of unique elements.
• setdefault() is a method which returns the value of a key (if the key is in dictionary). If not, it
inserts key with a value to the dictionary.
• Setter methods are methods which are used to set values of instance variables.
Page 278
• Slicing refers to extracting a substring from a string.
• sort() is a method used to rearrange the elements of a list in a specific order, typically the default
natural sorting order.
• split() is a method used to split the given string according to the specified separator.
• Static methods are class-level methods that are not bound to specific instances of a class.
• Static variable is a variable that is associated with a class, not with a specific instance of that
class.
• String is a sequence of characters.
• strip() is a predefined methods to remove spaces in Python.
• sum() is a method used to calculate the total or sum of all the elements in a sequence.
• super() function is a built-in function that allows you to call a method in a parent from a child
class.
• symmetric_difference_update() is a method which finds the symmetric difference of two sets
and updates the set calling it.
• symmetric_difference() is a method which returns elements present in either set A or set B but
not in both.
• Syntax error is an error which occurs because of invalid syntax.
• Syntax is set of rules you must follow to run your program correctly.
T
• try-except block is used to catch and handle exceptions.
• Tuple is a collection of objects, which are ordered and can’t be changed.
• type() is a function, which is used to check data type of a variable.
U
• union() is a method which returns all elements present in both set A and set B.
• update() is a method used to add multiple items to a set.
V
• values() is a method which returns all values of a dictionary.
• Variable is the name which we give to the memory location which holds some data.
W
• while loop is a control flow statement that allows you to execute a block of code repeatedly as
long as a certain condition is true.
Page 279
No content here - this page is intentionally blank.
FUN-DAMENTALS OF
PYTHON PROGRAMMING
Gateway for the Joy of Programming