2022 Edition
Notes on Programming with
Python
By Saif Bashar
Programs included
Video Lectures included
Notes on Programming with Python © 2022 by Saif Bashar is licensed
under CC BY-NC-ND 4.0
Notes on Python
By Saif Bashar
DISCLAIMER: THIS IS A FREE BOOK FOR EDUCATIONAL PURPOSES ONLY, ALL TRADEMARKS
ARE THE PROPERTY OF THEIR RESPECTIVE OWNERS.
FEEDBACK: FOR REPORTING MISTAKES YOU CAN SEND YOUR FEEDBACK AT S4IFBN@[Link]
More info : [Link] 2
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
INTRO
Python is an interpreted scripting, open-source, cross-platform,
object-oriented, high-level, general-purpose programming language. Python is a
dynamic type language and it is case sensitive. Created by Guido van Rossum and
first released in 1991. Python 3 came out in 2008.
Python is a dynamic language or it does not force you to declare variable types
before using them. It allows you to accomplish more with fewer lines of code,
dynamic languages are often slower than compiled static languages. But their
speed is improving as their interpreters become more optimized.
Python is an interpreted language, not a compiled language. It is processed at
runtime. which can save you considerable time during program development
because no compilation and linking are necessary.
It supports multiple programming paradigms beyond the object-oriented
programming paradigm, such as procedural and functional programming.
Python is widely used and has a large community and is always in the top five
programming languages. It is used by tech companies to build their applications
like Spotify, Netflix, Dropbox, Reddit, Instagram, Pinterest, Quora, etc.
Python can be used in various environments:
- Terminal applications
- GUI application
- Web (client, server) sides, cloud
- Mobile devices
- Embedded devices
Python does not use parentheses to group lines of code or semicolons to
indicate the end of a line, it uses indentation instead, so be careful and
always indent your code in a proper way.
More info : [Link] 3
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Python has about 37 keywords:
and as assert async await break case class
continue def del elif else except False finally
for from global if import in is lambda
match None nonlocal not or pass raise return
True try while with yield
Programs written in Python are typically much shorter than equivalent C, C++,
or Java programs, for several reasons:
- The high-level data types allow you to express complex operations in a
single statement.
- Statement grouping is done by indentation instead of beginning and
ending brackets.
- No variable or argument declarations are necessary.
-----------------------------------------
References:
- Official Language documentation: [Link]
- Introducing Python, Bill Lubanovic, O’Reilly, 2015.
Codes in these notes are tested on Python 3.10.2
Using PyCharm IDE 2021.3.1
Online interpreter: [Link]
All the code snippets in this book will be hosted on [Link]
and Github at this repo.
</> -> [Link]
[>] Python / Introduction -> [Link]
More info : [Link] 4
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
PART 1 DATA STRUCTURES
DATA TYPES
Everything in Python is an object. Objects whose value can change are said to
be mutable; objects whose value is unchangeable once they are created are
called immutable.
An object’s mutability is determined by its type; for instance, numbers,
strings, and tuples are immutable, while dictionaries and lists are mutable.
If a variable is not defined (assigned a value), trying to use it will give you
an error. A variable in Python inherits its type from its value.
A variable name is a reference for the object in memory, Python objects can
have multiple names.
a = b = c = 13
All three variables a, b and c will refer to the same int object in memory with
value 13.
Values in Python are called literals
Program 1.1
# Getting user information
user_id = 43958975
age = 40
user_name = "Saif Bashar"
website = "[Link]
gender = "M"
is_student = True
height = 1.73
Note that Python programmers prefer to use the snake case rather than the camel
case in naming identifiers, also the identifiers naming follows the same rules
in most programming languages, and remember that Python is case sensitive.
Use the hash symbol # for single line comments
More info : [Link] 5
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Use the print function to print out the values, it takes one or more arguments.
print(user_id, user_name, age, website)
Python/Program 1.1 -> [Link]
Use the input function to get the values from the user, note that the input
function takes a prompt message to display to the user.
Program 1.2
user_name = input("Enter name: ")
user_id = input("Enter id: ")
age = input("Enter age: ")
print(user_id, user_name, age)
Python/Program 1.2 -> [Link]
[>] Python / Data Types -> [Link]
We can use the underscore symbol for assigning unwanted values
name, _ = "Saif", 40
More info : [Link] 6
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
NUMBERS
Integers are whole numbers; they can be positive, negative, or zero. An integer
size is very big in Python 3, it can be more than 64 bits and it can hold a
googol. Decimals are also supported to represent fractions called
floating-point numbers.
Arithmetic Operators
We have +, -, *, / float division, // integer division, % mod operator, and **
exponent operator, which is the same order of operations as most programming
languages.
googol = 10**100
print(googol)
Scientific notation is also supported
a = 1.0e6 + 1.0e6
Also, we can use +=, -=, *=, /=, %=, **=, //=
Python converts all integers to floats before performing division, The modulus
operator in Python works with integer and float numbers.
The expression -3**2 will give -9 because the exponentiation is applied before
the negation.
Complex numbers can be represented as:
a = 1 + 2j
b = 2 + 4j
print(a + b)
More info : [Link] 7
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Example on using numbers with arithmetic operators
Program 1.3
# Calculating expenditures
current_money = 70000
book_price = 15000
food_price = 12000
discount_rate = 0.22
discount = (book_price + food_price) * discount_rate
money_spent = (book_price + food_price) - discount
current_money -= money_spent
print("Remaining amount: ", current_money)
Python/Program 1.3 -> [Link]
[>] Python / Numbers -> [Link]
Operators Precedence
** Exponent
~ + - Complement, unary minus, unary plus
* / % // Multiply, divide, modulus, floor division
+ - Addition, subtraction
>> << Right and left shift
& Bitwise AND
^ | XOR, bitwise OR
<= < > >= Comparison
== != Equality
= %= *= //= /= += -= **= Assignment
is, is not Identity
in, not in Membership
More info : [Link] 8
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
BUILT-IN FUNCTIONS
Python provides various built-in functions that we can use in our programs. We
have seen some built-in functions so far in these notes like the print(),
input() functions, there are many more.
We can list all the available methods for a specific variable of any type using
the dir() function, and the help() function can also be used to display
documentation for the language classes.
Built-in type casting functions:
type(13) # returns the object’s type <class int>
id(4) # returns the object’s id
int(4.5) # returns 4
float(4) # returns 4.0
bool(-1) # returns True
chr(65) # returns the letter A
ord("A") # returns the ascii 65
str(4) # returns "4"
eval("[1,2]") # returns list of integers [1, 2]
eval("4**2 + 1") # returns 17
number = complex(4, 8)
print([Link])
print([Link])
Convert a string to an integer
price = input("Enter price: ")
print(int(float(price)))
You can even do this 😊
print(int(float(input("Enter price: "))))
More info : [Link] 9
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Convert decimal to binary, octal, and hexadecimal
d = 17
print(bin(d)) # 0b10001 or 0B10001
print(oct(d)) # 0o21 or 0O21
print(hex(d)) # 0x11 or 0X11
Bitwise Operators
Bitwise operators work at the bits level: ~, &, |, ^, >>, <<
Program 4.1
ip = 192 # 11000000
mask = 250 # 11111010
offset = 4
ip_mask = ip ^ mask
print(bin(ip_mask))
ip_mask = ip << offset
print(bin(ip_mask))
Python/Program 1.4 -> [Link]
Math built-in functions
abs(-11) # returns 11
round(1.5) # returns 2
max(1.5, 2.3, 6.4) # returns 6.4
min(1.5, 2.3, 6.4) # returns 1.5
divmod(9, 5) # returns 1, 4
pow(3, 7) # returns 2187
More info : [Link] 10
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
2
−𝑏 ± 𝑏 − 4𝑎𝑐
Solving the quadratic equation , where 𝑥 = 2𝑎
Program 1.5
a = 1
b = 5
c = 6
m = pow((b**2 - 4 * a * c), 0.5)
x1 = (-b + m) / 2 * a
x2 = (-b - m) / 2 * a
print(x1, x2)
Python/Program 1.5 -> [Link]
Built-in functions reference: [Link]
[>] Python / Built-in Function -> [Link]
More info : [Link] 11
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
[ LISTS ]
The first type of data structure in Python is the List which is an ordered set
of comma-separated elements enclosed by square brackets (not necessarily of the
same type) that are mutable which means we can insert and delete elements,
unlike strings. And we can access the element by its index which starts with
zero for the first element.
Lists are created with square brackets
primes = [] # empty list
primes = list() # empty list
primes = [2, 3, 5, 7, 11, 13]
names = ["Saif", "Zainab", "Mohammed", "Majid"]
List() function can convert any iterable object into a list.
list("567") # returns list of strings
list(range(0, 10)) # generate list of integers
Lists have order and they can be indexed and sliced, list index starts with
zero
Indexing, List[offset]
print(names[0]) # indexing prints Saif
print(primes[5]) # indexing prints 13
print(primes[-2]) # indexing prints 11
More info : [Link] 12
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Slicing, List [start : end : step]
All slice operations return a new list containing the requested elements. This
means that the slice returns a shallow copy of the list.
primes = [2, 3, 5, 7, 11, 13]
print(primes[1:4]) # slicing prints [3, 5, 7]
print(primes[1:4:2]) # slicing prints [3, 7]
print(primes[:2]) # slicing prints [2, 3]
print(primes[3:]) # slicing prints [7, 11, 13]
print(primes[::-1]) # slicing reverse the list
print(len(primes)) # prints list length 6
print(sum(primes)) # prints summation 41
Assignment to slices is also possible, and this can even change the size of the
list or clear it entirely.
names = ["Saif", "Zainab", "Mohammed", "Majid"]
names[0] = "Hussien" # change the first elements
names[2:4] = ["Osama", "Hasan"] # change elements in index 2 and 3
names[2:4] = [] # remove elements in index 2 and 3
names[:] = [] # clear the list
Adding elements to the end of a list or a specific index
months = ['Jan', 'Feb', 'Mar']
[Link]('Apr') # adding list element in the end
[Link](4, 'May') # adding list element at index 4
Removing elements from a list
[Link]('Apr') # removing element
del months[3] # removing element at index 3
[Link]() # remove and return the last element
[Link](1) # remove and return the second element
Clearing a list
[Link]() # returns empty list
del months # delete the list and free memory
More info : [Link] 13
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Combining (merging) lists
L1 = [1, 2, 3, 4]
L2 = [5, 6, 7, 8]
L1 += L2 # returns [1, 2, 3, 4, 5, 6, 7, 8]
[Link](L2) # returns [1, 2, 3, 4, 5, 6, 7, 8]
[>] Python / List (Part 1) -> [Link]
Other List Methods
store = ["bread", "milk", "coffee", "tea", "sugar", "salt"]
[Link]('milk') # returns index 1
'tea' in store # returns True
[Link]('coffee') # count occurrences
[Link]() # sorting list
sorted_store = sorted(store) # return a sorted copy
[Link]() # reverse a list
[Link](reverse=True) # reverse a list
new_store = store # copying lists, but changes affect
# Both lists
new_store = [Link]() # copying lists (shallow copy)
new_store = store [:] # copying lists (shallow copy)
new_store = list(store) # copying lists (shallow copy)
Using the unpacking operator * with lists
list = [1, 2, 3, 4, 5]
a, *b, c = list
print(a) # prints 1
print(b) # prints [2, 3, 4]
print(c) # prints 5
More info : [Link] 14
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Two Dimensional lists
Lists can contain elements of different types, including other lists
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
print(matrix[0][0]) # prints the first element
print(matrix[2][2]) # prints the last element
This is allowed also
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10] ]
print(matrix[3][0]) # prints 10
2D lists of students
student_grades = [
["ali", 76, 78, 98],
["ahmed", 78, 94, 62],
["sara", 71, 92, 90]
]
student_grades[1][1] = 75 # updating value
student_grades.pop(0) # remove student 0
student_grades.append(["noor", 67, 78, 98]) # adding new student
[>] Python / List (Part 2) -> [Link]
More info : [Link] 15
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
" STRINGS "
Strings are ordered sequences of characters, they are immutable variables
assigning values to an indexed position in the string results in an error,
strings are enclosed by either double quotes or single quotes, we can have
single quotes inside double-quoted strings, or double quotes inside
single-quoted strings.
Taking an input as a string and printing it
name = input('Type your name: ')
print('Hello '+ name)
Strings can be concatenated with the + or += operator, and repeated with *
'z' * 10 # returns "zzzzzzzzzz"
The in operator returns True or False
print('py' in 'python')
Indexing and slicing also supported in strings
name = "saif"
'z' + name[1:] # returns "zaif"
name[-1] # returns "f"
name[1:3] # returns "ai"
name[::-1] # returns "fias"
len(name) # returns 4
Escape characters are supported with strings:
\n for a new line
\t for tab space
\b for backspace
\r for carriage return
\\ for escaping \
\' for escaping '
\" for escaping "
More info : [Link] 16
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
If you don’t want characters prefaced by \ to be interpreted as special
characters, you can use the raw string by adding an r before the first quote.
It is called raw string
path = r"C:\work\newfolder"
A string can be broken into multiple lines using the backslash character \ it
can be used to indicate that the string continues on the next line.
The triple single-quotes or triple double-quotes in a string to support
multiline string
text = """ this is a text
message that can be
spread along multiple
lines
"""
[>] Python / Strings (Part 1) -> [Link]
More info : [Link] 17
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
String methods
Various methods can be used with string variables for string manipulation, the
original string will not be changed, so any modifications will need to be saved
to a new variable.
msg = "hello world!"
[Link]() # capitalize the first letter only
[Link]() # capitalize the first letter of every word
[Link]() # returns the string in uppercase
[Link]() # returns the string in lowercase
[Link]() # swaps the letters case
[Link]() # returns true or false
[Link]() # returns true or false
[Link]() # returns true or false check if all alphabetic
[Link]() # returns true or false check if its alphanumeric
[Link]('k') # False
[Link]('!') # True
[Link]('w') # return the location, error if not found
[Link]('w', 0, 10) # specify start and end
[Link]('o') # returns the first occurrence of a letter or word
# returns -1 if a letter or word not found
[Link]('o', 0, 10) # specify start and end
[Link]('o') # returns the first occurrence backwards
[Link]('o') # returns the first occurrence backwards
[Link]('hello', 'hi') # replace words (all occurrences)
[Link]('o', 'oo', 1) # replace only one occurrence
name = "Saif Bashar"
[Link]() # returns ['Saif', 'Bashar']
names = "[Link]"
[Link](".") # returns ['Saif', 'Ali', 'Ahmed']
[Link](".", 1) # returns ['Saif', '[Link]']
name = ['Saif', 'Bashar'] # convert a list to a string
full_name = ' '.join(name) # returns "Saif Bashar"
More info : [Link] 18
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
text = "....hello there.... I am a student of computer science...."
new_text = [Link]('.') # remove the dots from the beginning and the end
new_text = [Link]('.') # remove the dots from the right side
new_text = [Link]('.') # remove the dots from the left side
[>] Python / Strings (Part 2) -> [Link]
Strings Formatting
Using format() method and the curly braces as placeholders
address = 'Baghdad, Karada'
rent = 700000
text = 'House in {} rent is {} '.format(address, rent)
print(text)
Format integers with separators
balance = 675675445543525
new_balance = '{:,}'.format(balance)
You can even specify the location of the inserted strings
print('The {2} {1} {0}'.format('fox', 'brown', 'quick')) # or
print('The {q} {b} {f}'.format(f='fox', b='brown', q='quick'))
the output: The quick brown fox
Note that the format method can also specify the precision for float numbers
print('the result = {:0.50f}'.format(22 / 7))
Numbers width also can be specified
print("No: {0:2} squared is {1:4} and cubed is {2:4}".format(1, 1**2, 1**3))
print("No: {0:2} squared is {1:4} and cubed is {2:4}".format(2, 2**2, 2**3))
print("No: {0:2} squared is {1:4} and cubed is {2:4}".format(3, 3**2, 3**3))
print("No: {0:2} squared is {1:4} and cubed is {2:4}".format(4, 4**2, 4**3))
print("No: {0:2} squared is {1:4} and cubed is {2:4}".format(5, 5**2, 5**3))
More info : [Link] 19
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Use <, >, ^ for left, right and center alignments
print("No: {0:2} squared is {1:<4} and cubed is {2:<4}".format(4, 4**2, 4**3))
print("No: {0:2} squared is {1:>4} and cubed is {2:^4}".format(5, 5**2, 5**3))
f-Strings
Python supports placeholders by prefixing strings with f and using curly braces
for the variables, it performs type conversion to string automatically
first_name = 'saif'
last_name = 'bashar'
msg = f'Hi my name is {first_name} {last_name}'
print(msg)
Using the f-strings to format numbers
balance = 675675445543525
new_balance = '{balance:,}'
print(f'the result = {22 / 7:0.50f}')
Strings Alignments
text = "Hello There, I am a student of computer science"
new_text = [Link](100) # center alignment within 100 spaces
new_text = [Link](100) # left alignment within 100 spaces
new_text = [Link](100) # right alignment within 100 spaces
Strings Filling
number = "13"
print([Link](5)) # prints 00013
[>] Python / Strings (Part 3) -> [Link]
More info : [Link] 20
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
( TUPLES )
Tuples are ordered sequences of elements like lists but they are immutable
collections of data we cannot add, delete or change the data once initialized.
Guido van Rossum, the creator of Python, tweeted “I pronounce tuple
too-pull on Mon/Wed/Fri and tub-pull on Tue/Thu/Sat. On Sunday I don’t talk
about them.”
Creating a tuple using parenthesis, tuples elements can be accessed by its
index as we did with lists
T1 = () # empty tuple
T1 = (1) # not tuple just number 1
T1 = (1,) # tuple with one element
T1 = (1, "ali", 30, "baghdad")
T1 = 1, "ali", 30, "baghdad" # this is also a tuple
T1[0] = 2 # invalid
L1 = [1, "ali", 30, "baghdad"]
tuple(L1) # convert list to tuple
list(T1) # convert tuple to list
x, y, z = T1 # tuple unpacking
List of tuples
coordinates = [(4, 7), (6, 9), (9, 10)] # list of tuples
Why do we use tuples rather than lists?
- Tuples take less space
- Cannot change items by mistake
- Functions arguments are passed as tuples
- Useful in returning multiple values from functions
Tuple methods
.count( ) , .index( )
[>] Python / Tuples -> [Link]
More info : [Link] 21
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
{ 0 : DICTIONARIES }
A dictionary is unordered key-value pair elements, dictionaries are mutable.
The dictionary items are accessed by their keys, keys should be unique and
immutable data types.
Dictionaries are created with curly brackets and comma-separated key: value
pairs
D0 = {} # empty dictionary
student = {'name':'ahmed', 'age': 25, 'subjects': ['math', 'programming']}
D2 = dict(Name="Ali", Age=30) # also valid
D1["Name"] = "Ahmed" # updating a value
D1["Address"] = "Baghdad" # adding key-value
D2 = {"Address": "Basra", "Salary": 200} # will remove old values
[Link](D2) # joining dictionaries
del D1["Address"] # deleting element
[Link]('name')
[Link]() # deleting all elements
D1 = {} # deleting all elements
"Address" in D1 # returns True or False
print([Link]("Address")) # return value for a key
print([Link]("Address")) # return value for a key
print([Link]("City", "Not found")) # return Not found
print(D1["Address"]) # return value for a key
print([Link]()) # returns list of keys
print([Link]()) # returns list of values
print(list([Link]())) # return list of key-value tuples
More info : [Link] 22
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
All the following code will produce the same dictionary:
{'a': 'b', 'c': 'd', 'e': 'f'}
L1 = [('a', 'b'), ('c', 'd'), ('e', 'f')] # list of tuples
L2 = ['ab', 'cd', 'ef'] # list of strings
T1 = (['a', 'b'], ['c', 'd'], ['e', 'f']) # tuple of lists
T2 = ('ab', 'cd', 'ef') # tuple of strings
print(dict(L1), dict(L2), dict(T1), dict(T2))
Like lists copying dictionaries with shallow copy
D3 = [Link]()
We can use tuples as dictionary keys because they are immutable
houses = {
(44.79, 33.14, 285): 'My House',
(38.89, 47.03, 13): 'Your House'
}
[>] Python / Dictionaries -> [Link]
More info : [Link] 23
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
{ SETS }
Sets are an unordered collection of unique elements.
S1 = {} # create an empty dictionary
S1 = set() # create an empty set
S1 = {1, 2, 3, 4, 5}
S2 = {1, 3, 2, 5, 7}
[Link](6) # adding elements
[Link]() # removing the first element
[Link](5) # removing the element with 5 value
[Link](9) # removing with no error if not found
[Link](S2) # combining two sets
Set Operations
S3 = S1 & S2 # gives the intersection
S3 = [Link](S2) # gives the intersection
S4 = S1 | S2 # gives the union
S4 = [Link](S2) # gives the union
S5 = S1 - S2 # gives the difference
S5 = [Link](S2) # gives the difference
S6 = S1 ^ S2 # gives the symmetric difference
S6 = S1.symmetric_difference(S2) # gives the symmetric difference
S1 <= S2 # check S1 subset of S2
[Link](S2) # check S1 subset of S2
S1 < S2 # check S1 proper subset of S2
S1 >= S2 # check S1 superset of S2
[Link](S2) # check S1 superset of S2
S1 > S2 # check S1 proper superset of S2
letters = "letters" # convert string to set
print(set(letters)) # only unique letters
More info : [Link] 24
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Converting
L1 = [1, 2, 3, 4, 5, 5] # convert list to set
print(set(L1)) # only unique numbers
colors = ('black', 'white', 'red') # convert tuple to set
print(set(colors))
fruit = {'apple': 'yellow', 'orange': 'orange', 'cherry': 'red'}
print(set(fruit)) # convert dictionary keys to set
Using sets inside a dictionary
food = {
'burger': {'meat', 'tomato', 'cheese'},
'pizza': {'cheese', 'olive'},
'fried chicken': {'chicken', 'potatoes'}
}
We can make a set immutable using the frozenset() function.
We cannot use a set of sets but we can do so using the frozenset()
{frozenset({1, 2}), frozenset({3, 4})}
[>] Python / Sets -> [Link]
More info : [Link] 25
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
PART 2 CODE STRUCTURES
CONDITIONALS
Conditional statements are a type of code structure statements, be careful when
using code structure statements to keep the indentation right since Python does
not use curly braces nor special keywords to group statements like other
languages, Python uses white spaces.
Each subsection of code is recommended to have 4 spaces of indentation (tab)
according to PEP-8
Note that every value is True except:
Keyword False
Int Zero 0
Float Zero 0.0
Null None
Empty list []
Empty string ''
Empty string “”
Empty tuple ()
Empty dictionary {}
Empty set set()
Simple if-else statement
A = 13
if A:
print('Not Zero')
else:
print('Zero')
Various types of operators can be used to test data
Relational Operators
We have six relational operators: >, <, >=, <=, ==, !=
Logical Operators
Three logical operators: and, or, not
More info : [Link] 26
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Membership & Identity Operators
in, not in, is, is not
Refer to operators precedence Page 7
Indentation Matters
Here both print statements will execute, because of the indentation
name = 'Saif'
if name == 'Saif':
print('Hello ' + name)
print('Nice to meet you')
Here only the second print will execute, why?
name = 'Ahmed'
if name == 'Saif':
print('Hello ' + name)
print('Nice to meet you')
Multiple Conditions
Checking numbers positive or negative
num = float(input("Enter a number: "))
if num >= 0:
if num == 0:
print("Zero")
else:
print("Positive number")
else:
print("Negative number")
More info : [Link] 27
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Checking Traffic lights
color = 'green'
if color == 'red':
print('Stop')
elif color == 'yellow':
print('Ready')
elif color == 'green':
print('Go')
else:
print('Not Valid Color')
Using pass keyword to postpone the if-statement without stopping the program
x = 4
if x != 4:
pass
print("Not printed")
Note on comparing floats
round function can be used to compare float numbers note that we can specify
the number of digits after the decimal to round the number with
x = round(0.1 + 0.1 + 0.1, 3)
print(x == round(0.3, 3))
More info : [Link] 28
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Match Statement
Recently added to Python language
grade = 79
match grade:
case grade if grade >= 90:
print("Excellent")
case grade if grade >= 80:
print("Very good")
case grade if grade >= 70:
print("Good")
case grade if grade >= 60:
print("Medium")
case grade if grade >= 50:
print("Pass")
case grade if 49 >= grade >= 0:
print("Fail")
case _:
print('invalid number')
Another example
http_error = 404
match http_error:
case 400 | 401 | 403 | 404:
print("Not found")
case 500:
print("Server Error")
case _:
print('No Internet')
[>] Python / Conditionals -> [Link]
More info : [Link] 29
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
LOOPS
Loops are code structures that repeat a section of code based on a condition,
Python provides two types of loops
1- While loop (indefinite)
Example on a simple loop that prints the numbers from 1 to 10
A = 1
while A < 10:
print(A)
A += 1
Looping through list elements (doubling list elements)
A = [1, 2, 3, 4, 5]
i = 0
while i < len(A):
A[i] *= 2
print(A[i], end=' ')
i += 1
Example on an infinite loop that capitalizes text and breaks if the letter q or
Q is entered, we can use break and continue to break the loop or skip an
iteration based on some condition.
while True:
text = input("Enter text to capitalize, [q to quit]: ")
if text == "q" or text == "Q":
break
print([Link]())
print("Program Finished")
More info : [Link] 30
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Finding the squares of odd numbers only
i = 0
while i < 100:
if i % 2 == 0:
i += 1
continue
print(i * i, end=' ')
i += 1
print("Program Finished")
Finding the factorial of a number
ans = input("Enter a number: ")
fact = 1
x = int(ans)
while x > 0:
fact *= x
x -= 1
print("Factorial is: ", fact)
Finding the Fibonacci sequence
a, b = 0, 1
while a < 10:
print(a)
a, b = b, a + b
A while loop can have an else statement which executed in the case of no
immediate break happened for the loop
a = 5
i = 0
while i < 5:
i += 1
else:
print('condition is false')
More info : [Link] 31
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Searching for the number 13 in a list
numbers = [1, 6, 0, 5, 13, 3, 8, 2]
i = 0
while i < len(numbers):
if numbers[i] == 13:
print("13 was found")
break
i += 1
else:
print("13 was not found")
[>] Python / Loops (Part 1) -> [Link]
2- For loop (definite)
A = [10, 20, 30, 40, 50]
for item in A:
print(item)
Use the enumerate() function to return the element and its index as a tuple
grades = [45, 87, 67, 98, 99, 78]
for index, grade in enumerate(grades):
print(index, grade)
Finding divisors
x = 100
divisors = ()
for i in range(1, x):
if x % i == 0:
divisors += (i, )
print(divisors)
More info : [Link] 32
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Looping through a dictionary
D1 = {1:'saif', 2:'ahmed'}
for number, name in [Link]():
print(number, name)
We can also use [Link]() and [Link]() to loop through keys or values.
Similar to while loop, for has an optional else that checks if the for
completed normally. If the break was not called, the else statement is run.
This is useful when you want to verify that the previous for loop ran to
completion, instead of being stopped early with a break.
range() function
The range function generates a sequence of numbers range(start, stop, step) and
can be used with loops. Generate numbers from 200 to 0
for i in range(200, -1, -1):
print(i, end=' ')
zip() function
We can iterate over multiple sequences in parallel using zip() function,
without needing to rely on multi-dimensional lists
days = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
fruits = ['apple', 'cherry', 'orange', 'grape']
drinks = {'cola', 'coffee', 'tea', 'water', 'juice'}
for day, fruit, drink in zip(days, fruits, drinks):
print(day, fruit, drink)
Note that the loop will execute to the length of the shortest data collection
More info : [Link] 33
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Simple Arabic-English dictionary
english = ('hello', 'program', 'student', 'teacher')
arabic = (' 'معلم,' 'طالب,' 'برنامج,')'مرحبا
D1 = dict(zip(english, arabic))
for item in [Link]():
print(item)
[>] Python / Loops (Part 2) -> [Link]
More info : [Link] 34
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
COMPREHENSIONS
A comprehension is a compact way of creating a Python data structure from one
or more iterators. It is a shorter way to write code. It works with lists,
sets, dictionaries, and generators.
List Comprehensions
List comprehensions follows the syntax:
new_list = [<expression> for <element> in <collection>]
For example, creating a list using list comprehension
numbers = [number for number in range(10)]
instead of this way
numbers = []
for number in range(10):
[Link](number)
doubling list elements
doubles = [number * 2 for number in numbers]
list comprehension can have conditional expression
odds = [number for number in range(10) if number % 2 == 1]
We can use if-else statement also, but it's written before the for loop
numbers = [1, 3, 6, 4, 23, 67, 89, 23, 200]
result = ['Even' if number % 2 == 0 else 'Odd' for number in numbers]
More info : [Link] 35
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
And instead of this:
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
list = []
for fruit in fruits:
if "a" in fruit:
[Link](fruit)
we can do this:
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
list = [fruit for fruit in fruits if "a" in fruit]
Return the item if it is not banana, if it is banana return orange 😊
list = [fruit if fruit != "banana" else "orange" for fruit in fruits]
Comprehension with nested loops, regular nested loops look like this:
matrix = []
for row in range(3):
for col in range(3):
[Link]((row, col))
Using list comprehensions will look like this:
matrix = [(row, col) for row in range(3) for col in range(3)]
Converting temperatures using list comprehensions
celsius = [0, 50, 100, 75, 32]
fahrenheit = [((9/5)*temp+32) for temp in celsius]
Set Comprehensions
Set comprehension also possible, for example generate a set of numbers larger
than 5 and smaller than 10
numbers = {number for number in range(10) if number >= 5}
More info : [Link] 36
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Dictionary Comprehensions
Dictionary comprehension is also possible, for example calculating character
frequencies in a sentence.
sentence = 'Hi my name is saif'
freq = {letter: [Link](letter) for letter in sentence}
print(freq)
Generator Comprehensions
Tuples do not have comprehensions, the following code will return a generator
belonging to the generator class which can be used to provide data to an
iterator.
numbers = (number for number in range(10))
Now we can use this generator like this:
for number in numbers:
print(number)
[>] Python / Comprehensions -> [Link]
More info : [Link] 37
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
USER DEFINED FUNCTIONS
A function in programming is a block of code that performs a specific task and
can be called multiple times in our programs. The function syntax in Python is
simple, this is a function that does nothing.
def do_nothing(): # function implementation
pass
do_nothing() # function call
A function that says hello
def say_hello():
print('hello')
say_hello()
A function that takes your name and greet you
def say_hello():
name = input("What's your name?: ")
print('hello ', name)
say_hello()
Send your name to the function to greet you
def say_hello(name):
print('hello', name)
name = input("What's your name?: ")
say_hello(name)
More info : [Link] 38
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
A function that adds two numbers, The values you pass into the function when
you call it are known as arguments. When you call a function with arguments,
the values of those arguments are copied to their corresponding parameters
inside the function. Also called positional arguments.
def add(A, B): # function receive two parameters
return A + B # function returns a value
result = add(10, 20)
print(result)
We can return more than one value as a tuple in Python
def double_triple(A):
return A/2, A*A, A*A*A # function returns three values
half, double, triple = double_triple(10)
print(half, double, triple)
Default Arguments
Note that default arguments must be at the end of the parameters list
def add(A=10, B=20): # default arguments
return A + B
result = add()
print(result)
We can send any number of arguments to a function using the unpacking operator,
the args will be treated as a tuple of the sent values
def add(*args): # unpacking operator
result = 0
for x in args:
result += x
return result
print(add(9, 7, 8, 6, 8))
print(add(8, 6, 8))
print(add())
More info : [Link] 39
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Keyword Arguments
Specify arguments by the names of their corresponding parameters, the
parameters will be passed as key, value pairs. The kwargs will be a dictionary.
def student_info(name, *args, **kwargs):
print(name, args, kwargs)
student_info('ahmed', 75, 65, 62, 67, 56, level=2, address='Baghdad')
[>] Python / User-Defined Functions (Part 1) -> [Link]
Type Hinting
We can hint the function input and return data types as type of function
documentation
def add(a: int, b: int) -> int:
return a + b
print(add(5, 8))
More info : [Link] 40
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Functions are Objects
As everything in Python is an object, functions are also treated as objects we
can assign them to variables, use them as arguments to other functions and
return them from functions. We can also use functions inside collections,
functions are immutable so we can also use them as dictionary keys.
def read() -> tuple:
name = input('Username: ')
password = input('Password: ')
return name, password
def check(read) -> str:
name, password = read()
if name == 'saif' and password == '12345':
return 'login success'
else:
return 'invalid username or password'
result = check(read)
print(result)
Variables Scope (namespace)
Variables have scope or namespaces in programs, defining a variable in the
global scope can be accessed anywhere in the program, but we cannot modify a
global variable inside a function.
Variables defined inside functions have local scope, to access a global
variable inside a function, we can use the global keyword.
Referring to global variable
x = 10
def increment_x():
global x
x += 5
print(x)
increment_x()
More info : [Link] 41
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Inner functions
We can define functions inside another functions
x = 20
def outer():
x = 10
def inner():
nonlocal x
print(x)
x += 1
inner()
print(x)
outer()
print(x)
another example
def knights(saying):
def inner(quote):
return f"We are the knights who say: {quote}"
return inner(saying)
print(knights('Ni!'))
Recursion
Recursion is also supported in Python, recursion is when a function calls
itself, it needs a base case to stop the calling loop.
def display(n):
print(n)
if n == 10:
return
return display(n+1)
display(1)
[>] Python / User-Defined Functions (Part 2) -> [Link]
More info : [Link] 42
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Closures
An inner function acts as a closure, this is a function that is dynamically
generated by another function and can both change and remember the values of
variables that were created outside the function.
def outer():
saying = 'Hey!'
def inner(): # remembers the value of saying
return f"We are the knights who say: {saying}"
return inner # return the function (closure)
func1 = outer()
print(func1())
the outer function will return a reference of the function object (inner) and
will be assigned to the func1 object. The inner function will remember the
object saying and can change it even when the outer function is finished
executing.
The object saying is called a free variable, the closure is a function with an
extended scope that contains free variables. A closure closes over the free
variables from their environment.
Another example:
A function with memory will remember the last counter value
def counter1(start):
def inc(step=1):
nonlocal start
start += step
print(start)
return inc
func1 = counter1(1)
func1()
func1()
More info : [Link] 43
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
A function with no memory will not remember the last counter value
def counter2(start):
def inc(step=1):
nonlocal start
start += step
print(start)
inc()
counter2(1)
counter2(1)
[>] Python / Closures -> [Link]
Decorators
A decorator is a function that takes one function as an input and returns
another function (modified function). Used to modify a function without
changing its source code. Decorators add functionality to your code.
Basic Example:
def decorator(func):
def wrapper():
print('code executed before func code')
func()
print('code executed after func code')
return wrapper
@decorator
def func():
print('code inside func')
func()
The decorator received the func function as a parameter and returned modified
version of this function named wrapper.
You can modify multiple functions with a decorator and you can also add as many
decorators as you want to a function.
More info : [Link] 44
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Suppose we want to measure the time each function will take in our program we
can use the time module to record the time before and after the function
finishes processing.
This code without a decorator (note the repeated lines of code)
import time, math
def double(list):
start = [Link]()
result = []
for number in list:
[Link](number * number)
print('finished processing')
end = [Link]()
print('done in ' + str( end - start) + ' seconds')
def triple(list):
start = [Link]()
result = []
for number in list:
[Link](number * number * number)
print('finished processing')
end = [Link]()
print('done in ' + str( end - start) + ' seconds')
def roots(list):
start = [Link]()
result = []
for number in list:
[Link]([Link](number))
print('finished processing')
end = [Link]()
print('done in ' + str( end - start) + ' seconds')
list = range(1, 1000000)
double(list)
triple(list)
roots(list)
More info : [Link] 45
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
The same previous program with a decorator (repeated lines now deleted) What if
we have 100 functions in our program and we want to measure their time,
decorator is useful here without the need to repeat the code.
import time, math
def measure(func):
def wrapper(*args, **kwargs):
start = [Link]()
func(*args, **kwargs)
end = [Link]()
print('done in ' + str(end - start) + ' seconds')
print('finished processing')
return wrapper
@measure
def doubles(list):
result = []
for number in list:
[Link](number * number)
@measure
def triples(list):
result = []
for number in list:
[Link](number * number * number)
@measure
def roots(list):
result = []
for number in list:
[Link]([Link](number))
list = range(1, 10000000)
doubles(list)
triples(list)
roots(list)
[>] Python / Decorators -> [Link]
More info : [Link] 46
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Lambda Expression
A lambda is a small anonymous function (without a name also called anonymous
functions) usually written in a single line used for simple operations, the
syntax is:
lambda <input>: expression
2
For example, the result of the equation: 𝑥 + 5𝑥 − 7
g = lambda x: x**2 + 5*x - 7
print(g(9))
lambdas can take any number of inputs and it also can take no input
Another example: if we want to capitalize list of days and concatenate a number
with each day
We can do it like this with regular function:
days = ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri']
def newdays(days):
for index, day in enumerate(days):
new_day = str(index + 1) + ' ' + [Link]()
print(new_day)
newdays(days)
Or using lambda
days = ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri']
for index, day in enumerate(days):
new_day = lambda day: str(index + 1) + ' ' + [Link]()
print(new_day(day))
We can also send the lambda as an argument to another function
days = ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri']
def edit(days, func):
for day in days:
print(func(day))
edit(days, lambda day: [Link]() + '!')
More info : [Link] 47
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Also it can be used as a key value in sort method, to change the sort method
behavior, for example sorting the following list based on the second element of
the tuple in a list of tuples:
days = [
('sat', 0), ('sun', 10), # number represent working hours
('mon', 11), ('tue', 8),
('wed',9), ('thu',8),
('fri', 0) ]
[Link](key= lambda day: day[1]) # sort on working hours
print(days)
Sort based on the length of the word
names = ['ahmed', 'noor', 'ali', 'sara', 'mohammed', 'mustafa']
[Link](key=lambda name: len(name))
print(names)
Lambda Conditionals
Conditional if-else statement can be used with lambda, with this syntax:
lambda <input> : output1 if expression else output2
Example:
age = 20
skill = True
job = False
check = lambda age, skill, job: True if age>=18 and skill==True and job==False else False
print(check(age, skill, job))
[>] Python / Lambda Expression -> [Link]
More info : [Link] 48
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
The following functions enable us to write shorter code in a more pythonic way
filter() function
takes a function and an iterator as arguments, and it filters the result based
on a Boolean expression and returns a filter object.
For example, filtering the odd numbers in a list of numbers
numbers = [5, 7, 8, 2, 10, 9, 6, 3, 6, 1]
odds = list(filter(lambda number: number % 2 == 1, numbers))
map() function
it maps a function to the iterator’s elements; it also takes a function and an
iterator as arguments and returns a map object.
For example, finding the square root of the odd numbers list above
odd_squares = list(map(lambda odd: [Link](odd), odds))
or shortly:
odd_squares = list(map([Link], odds))
reduce() function
it also takes a function and an iterator as arguments, but it applies the
function to each pair of items in the iterator object, and reduces the result
to a single value.
For example, finding the multiplication of all the odd_squares elements from
above
from functools import reduce
mult_odd_squares = reduce(lambda x, y: x*y, odd_squares)
More info : [Link] 49
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
A more concrete example, suppose we have the following list of tuples of
employees with their salaries and working hours per day.
emp = [
('saif', 800, 10),
('ahmed', 900, 11),
('ali', 1000, 12),
('sara', 850, 9),
('noor', 950, 9),
('hasan', 1050, 12),
('mohammed', 2050, 12),
('mohsen', 700, 7) ]
And we want to find the summation of salaries that are above 900, the
traditional way of doing this is to define a regular function:
def sum_salaries(emp):
sum = 0
for e in emp:
if e[1] > 900:
sum += e[1]
print(e)
print('sum', sum)
sum_salaries(emp)
Or it can be solved in much shorter code using filter(), map() and reduce()
functions
sals_above900 = list(filter(lambda e: e[1] > 900, emp))
sals = map(lambda s: s[1], sals_above900)
sums = reduce(lambda x, y: x+y, sals)
print(sums)
or in one line 😊
print(reduce(lambda x, y: x+y,
map(lambda s: s[1], list(filter(lambda e: e[1] > 900, emp)))))
[>] Python / filter(), map(), reduce() -> [Link]
More info : [Link] 50
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Generators
A generator is a sequence creation object, used as a data source for iterators,
for example the range() function which returns a list of numbers. Every time we
iterate through a generator it keeps track of where it was the last time It was
called and returns the next value. This is different from a normal function
which has no memory of previous calls.
If we want to create a large sequence and the code is too large for a generator
comprehension we can write a generator function, it is a normal function but
returns its value with a yield statement rather than return statement.
Generator functions can be suspended and resumed, useful in reading large
amounts of data that do not fit in memory, in regular functions the large data
will be held in memory.
Suppose we want to find the square root for million numbers, using regular
functions
import math
list = range(1000000)
def sqrt1(list):
newlist = []
for i in list:
s = [Link](i)
[Link](s)
return newlist
new_list = sqrt1(list)
print(new_list)
More info : [Link] 51
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Using a generator function the square root can be calculated for one number a
time.
import math
list = range(1000000)
def sqrt2(list):
for i in list:
s = [Link](i)
yield s
gen1 = sqrt2(list)
print(next(gen1))
print(next(gen1))
print(next(gen1))
print(next(gen1))
print(next(gen1))
Checking the size difference
import sys
print([Link](new_list))
print([Link](gen1))
[>] Python / Generators -> [Link]
More info : [Link] 52
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
EXCEPTIONS
Types of Errors:
- Syntax errors
- Runtime errors
- Logic errors
Errors detected during execution are called exceptions
List of built-in exceptions [Link]
For example dividing by zero gives a ZeroDivisionError, we can handle
exceptions in Python with try, except block
A = int(input('Enter first number: '))
B = int(input('Enter first number: '))
try:
C = A / B
print(C)
except: # default exception
print('Error happened')
else: # will run if no error happened
print('no errors')
finally: # always run
print('ok')
print('the rest of the program')
print('the rest of the program')
More info : [Link] 53
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
We can also make an exception for a specific error type and print a default
message for that error
try:
A = int(input('Enter first number: '))
B = int(input('Enter first number: '))
C = A / B
print(C)
except ZeroDivisionError as err:
print(err)
except ValueError as err:
print(err)
else:
print('no errors')
finally:
print('ok')
print('the rest of the program')
print('the rest of the program')
Handling IndexError
L = [1, 2, 3, 4, 5]
try:
L[3] = 7
except IndexError as err:
print(err)
else:
print('no index error happened')
finally:
print('ok')
print(L)
More info : [Link] 54
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
We can also raise our own exceptions and stop the execution of the program, for
example sometimes values are accepted in the language but cannot be accepted in
our program.
id = int(input("Enter ID: "))
name = input("Enter name: ")
age = int(input("Enter age: "))
if age < 0:
raise Exception("age cannot be a negative value")
elif 0 <= age <= 5:
print('not a student yet')
elif 6 <= age <= 12:
print('you are an elementary school student')
elif 13 <= age <= 15:
print('you are an intermediate school student')
elif 16 <= age <= 19:
print('you are a secondary school student')
else:
print('you are a college or graduated student')
print('program will continue here')
[>] Python / Exceptions -> [Link]
We can also use the assert keyword to validate values and raise an
AssertionError, for example:
id = int(input("Enter ID: "))
name = input("Enter name: ")
age = int(input("Enter age: "))
assert age>0, f' age cannot be less than zero, {age} was entered'
print('program will continue here')
More info : [Link] 55
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
FILES
Opening files for reading from the beginning (default)
f = open('[Link]', mode='r')
print([Link]()) # read all file contents
[Link]()
Note that calling the read method again will return an empty string because the
first read method sets the indicator at the end of the file, so we need to set
back the cursor to the beginning of the file using the seek method.
[Link](0) # return the indicator to location zero
[Link]() # gives the current position of the indicator
We can read a specific number of characters with the read method
[Link](10) # read ten characters from where the indicator is
Reading a file line by line using readlines method
for line in [Link]():
print(line, end='')
[Link]()
Reading very large files line by line using a generator function
path = r'C:\Users\Saif\OneDrive\Desktop\[Link]'
def read_text():
f = open(path, "r")
for line in [Link]():
yield line
gen_text = read_text()
print(next(gen_text))
print(next(gen_text))
print(next(gen_text))
More info : [Link] 56
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Note that we have to close the file after finishing our work with it, or we can
use the with statement then the file closing will happen automatically and it
is a safer way to work with files.
Also, we should handle exceptions while working with files because it
frequently happens.
try:
with open('[Link]', mode='r') as f:
text = [Link]()
print(text)
except:
print('Error Reading file')
Opening a file for writing and clear its contents if exists
f = open('[Link]', mode='w')
[Link]("hi this is a first line\n")
[Link]("hi this is a second line")
[Link]()
Opening file for appending data at the end of the file (writing)
f = open('[Link]', mode='a')
[Link]("\nhi this is a third line")
[Link]()
Opening file for reading and write with clearing the contents if exists
f = open('[Link]', mode='w+')
[Link]("\nhi this is a new line")
[Link](0)
print([Link]())
[Link]()
Opening file for reading and writing without clearing the contents and start
writing at the beginning
f = open('[Link]', mode='r+')
More info : [Link] 57
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Opening file for reading and writing without clearing the contents and start
writing at the end
f = open('[Link]', mode='a+')
Reading binary files (audio, image, video, system files)
with open('[Link]', 'rb') as f1:
img_data = [Link]()
print(img_data)
with open('test.mp3', 'rb') as f2:
mp3_data = [Link]()
print(mp3_data)
For more info: [Link]
[>] Python / Files -> [Link]
More info : [Link] 58
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
PART 3 OBJECT ORIENTED PROGRAMMING
CLASSES & OBJECTS
Classes are used to model real-world concepts and organize code into logical
entities, to group data and functionality. each class can be stored in a file,
this file can be imported and reused in other programs. Think of a class as a
user-defined data structure.
It is a convention to capitalize the class name.
Defining a simple class to represent a Student
class Student:
def read(self): # instance method
[Link] = input('Name: ') # instance attribute
[Link] = input('Age: ')
[Link] = input('Level: ')
def display(self): # instance method
print([Link], [Link], [Link])
saif = Student() # object creation (class instance)
[Link]() # method calling
[Link]() # method calling
All instance methods receive the self argument which represents the current
instance (object) it must be the first argument in the instance method, it is
named self as a convention we can name it anything we want.
The class members are called and accessed using the dot operator.
[>] Python / Classes & Objects -> [Link]
More info : [Link] 59
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Constructors & Destructors
Adding a constructor and a destructor to classes is important in OOP, the class
constructor has a special name __init__ it is a dunder method, its job to
initialize the object’s data and it is called automatically when the object is
created.
class Student:
def __init__(self): # class constructor
[Link] = input('Name: ')
[Link] = input('Age: ')
[Link] = input('Level: ')
def __del__(self): # class destructor
del [Link]
del [Link]
del [Link]
def display(self):
print([Link], [Link], [Link])
ali = Student() # constructor called
[Link]() # method calling
del ali # destructor called
The class destructor is also a special dunder method named __del__ used to
delete class data and free up the memory. It is called automatically when the
object scope ends. Although Python has an automatic garbage collector.
More info : [Link] 60
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
We can also send the data to the constructor with the object creation
class Student:
def __init__(self, name, age, level): # class constructor
[Link] = name
[Link] = age
[Link] = level
def display(self):
print([Link], [Link], [Link])
ahmed = Student('Ahmed', 20, 2) # object creation
[Link]()
ali = Student('Ali', 22, 4) # object creation
[Link]()
We can check an object is it an instance of a specific class using the
isinstance() function which returns true or false
print(isinstance(ali, Student))
[>] Python / Constructor & Destructor -> [Link]
We can also use *args and **kwargs in case we do not know how many attributes
the class will have, remember *args is treated as tuple and **kwargs as a
dictionary
class Student:
def __init__(self, *args, **kwargs):
[Link] = kwargs
[Link] = args
def display(self):
print([Link]['name'], [Link]['address'], [Link]['university'])
print([Link])
ali = Student(56, 76, 87, 98, 90, 89, name='Ali Mohammed', age=20, height=1.73,
address='Baghdad', university='UOT')
[Link]()
More info : [Link] 61
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Encapsulation
Making the class data or methods private to achieve the encapsulation concept
of OOP we add double underscores in front of the attributes or methods.
class Student:
def __init__(self, name, age, level):
self.__name = name # private attributes
self.__age = age
self.__level = level
def display(self):
print(self.__name, self.__age, self.__level)
ahmed = Student('Ahmed', 20, 2)
[Link]()
print(ahmed.__name) # cannot access
We can access private attributes using setters and getters
def set_name(self, name): # instance method (setter)
self.__name = name
def get_name(self): # instance method (getter)
return self.__name
[>] Python / Encapsulation -> [Link]
More info : [Link] 62
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Properties
A more pythonic way is to use properties instead of setters and getters by
using built-in decorators @property for getter and @[Link] for setter both
for a method called name()
class Student:
def __init__(self, name, age, level):
[Link] = name # name property calling
[Link] = age # age property calling
[Link] = level # level property calling
def display(self):
print([Link], [Link], [Link])
@property # name property (getter)
def name(self):
return self.__name
@[Link] # name setter
def name(self, name):
self.__name = name
@property # age property (getter)
def age(self):
return self.__age
@[Link] # age setter
def age(self, age):
self.__age = age
@property # level property (getter)
def level(self):
return self.__level
@[Link] # level setter
def level(self, level):
self.__level = level
More info : [Link] 63
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
ahmed = Student('Ahmed', 20, 2)
[Link]()
[Link] = 'Ahmed Ali' # setter called
print([Link]) # getter called
We can access properties as we access attributes, The advantage of using
properties instead of direct access to attributes. if we want to change the
definition of the attribute the change can be done inside the class only
without changing the callers.
from math import pi
class Circle:
def __init__(self, radius):
self.__radius = radius
@property
def area(self):
return self.__radius**2 * pi
@property
def premeter(self):
return 2 * self.__radius * pi
c1 = Circle(5)
print([Link])
print([Link])
We can add some validations to the setter methods to accept certain input
values, try using assert keyword.
[>] Python / Properties -> [Link]
More info : [Link] 64
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
Class Attributes & Class Methods
We can define attributes and methods that belong to the class not to specific
objects. Class attributes and method are shared among all objects created form
the class.
Class attributes are defined outside the instance methods, for example:
class Employee:
total = 0 # class attribute
employees = [] # class attribute
bonus = 200 # class attribute
def __init__(self, **kwargs):
self.__data = kwargs
[Link] += 1 # total number of objects
[Link](self)
def display(self):
print(self.__data['name'], self.__data['salary'])
def give_bonus(self):
self.__data['salary'] += [Link]
emp1 = Employee(name='Saif', age=40, salary=900, address='Kut')
emp2 = Employee(name='Ali', age=32, salary=800, address='Najaf')
emp3 = Employee(name='Noor', age=33, salary=960, address='Mosul')
emp4 = Employee(name='Sara', age=30, salary=910, address='Erbil')
print(str([Link]) + ' Employees') # access class attribute
for e in [Link]:
e.give_bonus()
for e in [Link]:
[Link]()
More info : [Link] 65
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
We have seen the instance methods that take the self parameter to refer
to the current object instance, there are another type of methods called
class methods or class decorators that can change the behavior of the
class methods, it takes cls parameter to refer to the class instead of
self that refers to the instance. class methods also can be used to
change class attributes, for example adding a method in the previous
example to change the values of the class attribute bonus. Class methods
are decorated with @classmethod decorator, add to the previous class the
following class method:
@classmethod
def change_bonus(cls):
[Link] += 50
return [Link]
Class methods are called by the name of the class, like this:
print(Employee.change_bonus())
Static Methods
Another type of methods are static methods also called utility methods that can
be called with or without being bonded to an object. Decorated by the
@staticmethod decorator. Static methods cannot be used to change the state of
the object. So, it does not take parameters that refer to the object or the
class no self nor cls in its definition.
@staticmethod
def display_all():
for e in [Link]:
[Link]()
Static methods are called by the name of the class, like this:
Employee.display_all()
[>] Class Attributes & Class Methods -> [Link]
More info : [Link] 66
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
COMPOSITION
Composition is a powerful concept of object-oriented programming that enables
the programmer to represent the part-of relationship between classes. Which
means a class is a part of another class. Because computer programs consist of
multiple classes to represent different entities that interact with each other.
Many types of relationships between classes can be established and composition
is one of them. The Composition concept will enable code-reuse of other
classes.
For example, if we have two classes to represent Employee and Client and both
need to have details about address. It is suitable to build an Address class
that will hold all the address details and this class can be used in other
classes also.
class Address:
def __init__(self, country, city, area, street, house, long, lat):
[Link] = country
[Link] = city
[Link] = area
[Link] = street
[Link] = house
[Link] = long
[Link] = lat
def display(self):
print([Link], [Link])
class Employee:
def __init__(self, name, age, phone, salary, country, city, area, street,
house, long, lat):
[Link] = name
[Link] = age
[Link] = phone
[Link] = salary
[Link] = Address(country, city, area, street, house, long, lat)
def display(self):
More info : [Link] 67
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
print([Link], [Link], [Link], [Link])
[Link]()
class Client:
def __init__(self, name, age, phone, email, country, city, area, street,
house, long, lat):
[Link] = name
[Link] = age
[Link] = phone
[Link] = email
[Link] = Address(country, city, area, street, house, long, lat)
def display(self):
print([Link], [Link], [Link], [Link])
[Link]()
ahmed = Client('Ahmed', 20, '0790111111', 'ahmed@[Link]',
'Iraq', 'Baghdad', 'Rusafa', 11, 20, 45.656, 48.765)
[Link]()
ali = Employee('Ali', 30, '0790111112', 800, 'Iraq',
'Baghdad', 'Karkh', 15, 24, 41.666, 56.656)
[Link]()
The address Object in the Client class depends on ahmed Object, meaning when
the scope of ahmed object ends and the object deleted from memory, the address
object will also be deleted.
Similarly for the address object in the Employee class, it depends on ali
object. It will be deleted when ali’s scope ends.
[>] Composition -> [Link]
More info : [Link] 68
Book Updated : Jun 30, 2022 work in progress
Notes on Python
By Saif Bashar
CONTENTS
INTRO 3
DATA TYPES 5
NUMBERS 7
BUILT-IN FUNCTIONS 9
[ LISTS ] 12
" STRINGS " 16
( TUPLES ) 21
{ 0 : DICTIONARIES } 22
{ SETS } 24
CONDITIONALS 26
LOOPS 30
COMPREHENSIONS 35
USER DEFINED FUNCTIONS 38
EXCEPTIONS 53
FILES 56
CLASSES & OBJECTS 59
COMPOSITION 67
CONTENTS 69
More info : [Link] 69
Book Updated : Jun 30, 2022 work in progress