Python Basics

Alireza Afzal Aghaei

Beautiful is better than ugly

Explicit is better than implicit

Simple is better than complex

Complex is better than complicated

Table of contents

  • Introduction
    • What is Python?
    • Implementations
    • Packages & Modules
  • Syntax
    • Variables, Data Types & Operators
    • Conditional Statements & Loops
    • Functions
    • Advanced Topics
  • Packages
    • Built-in packages
    • Third-party packages

Introduction

What is Python?

  • An interpreted, high-level, general-purpose programming language

  • Dynamic type

  • Garbage collection

    • Reference counting

  • It supports object-oriented and functional programming

Implementaions

  • CPython

    • Python 2 vs Python 3

  • PyPy

    • Just-in-time compilation

  • MicroPython

    • Python for  Microcontrollers

  • IronPython

    • Python for .NET Framework

  • Jython

    • Compile Python to Java ByteCode

IDEs

  • IDLE

  • Notepad, nano, vi, vim, etc.

  • Visual Studio Code, Sublime Text, Atom

  • Thonny

  • Pycharm, Spyder

  • Jupyter Notebook

  • And more...

Packages & Modules

  • You can do anything using python modules!
  • Built-in packages
    • Common utilities
    • Pre-installed
  • Third-party packages
    • Python Package Index (PyPI)

Syntax

Basic Syntax

  • Comments
    • Use the hash character \(\#\) symbol for one-line comments
    • For multi-line comment, use docstrings: """ or '''
  • Indentation
    •  Delimit control flow blocks
    • They are equivalent to braces in the C programing language
    • Four spaces are recommended
    • Do NOT mix spaces and tabs

Data Types

  • Text Type

    • str

  • Numeric Types

    • int, float, complex

  • Boolean Type

    • bool

  • Void Type

    • None

a = "Hello"        # str
b = 'Hello'        # str
c = str(10)        # str
d = 10             # int
e = int(3.1)       # int
f = 3.14           # float
g = float('1.4')   # float
h = 2 + 3j         # complex
i = complex(2,3)   # complex
j = True           # bool
k = False          # bool
l = bool(1)        # bool
m = None           # NoneType

Data Types

  • Sequence Types

    • list, tuple, range

  • Mapping Type

    • dict

  • Set Types

    • set, frozenset

  • Binary Types

    • bytes, bytearray

a = [-1, "Text"]              # list
b = list([-1, 'Text'])        # list
c = (-1, "Text")              # tuple
d = tuple([-1, "Text"])       # tuple
e = range(1, 100, 2)          # range
f = {'e':2.71, 'pi': 3.14}    # dict
g = dict(name='ali', age=25)  # dict
h = {1,2,3,2}                 # set
i = set([1,2,3,2])            # set
>> 'hello ali'.split()
['hello', 'ali']

>> 'Hello ali'.replace('Hello', 'Bye')
'Bye ali'

>> '-'.join(['a', 'b', 'c'])
'a-b-c'

>> 'Hello'.upper()
'HELLO'

>> """This is 
a multi-line
text"""
'This is \na multi-line\ntext'

>> a = "Hello, World!"
>> a[0]
'H'
>> a[::-1]
'!dlroW ,olleH'

Strings

>> name = 'ali'
>> 'Hello' + ' ' + name
'Hello ali'

>> "Hello %s" % name
'Hello ali'

>> 'Hello {}'.format(name)
'Hello ali'

>> f'Hello {name}'
'Hello ali'

Strings

  • Python supports various string formatting styles
    • Old style (% operator)
    • New style (str.format)
    • f-strings
    • Template strings
  • More details: pyformat.info

Strings

Method Description
capitalize() Converts the first character to upper case
count() Returns the number of times a specified value occurs in a string
endswith() Returns true if the string ends with the specified value
find() Searches the string for a specified value and returns the position of where it was found
format() Formats specified values in a string
index() Searches the string for a specified value and returns the position of where it was found
join() Converts the elements of an iterable into a string
lower() Converts a string into lower case
replace() Returns a string where a specified value is replaced with a specified value
split() Splits the string at the specified separator, and returns a list

Compound Data Types

Mutable Ordered Duplicate Indexing Slicing
List
Tuple
Set
Dict -

Lists

>> thislist = ['🍎', '🍓', '🍐', '🍎', '🍎', '🍓']

>> len(thislist)
6

>> thislist[0]
'🍎'

>> thislist[1:3]
['🍓', '🍐']

>> thislist[-1]
'🍓'

>> thislist.append('🍑')

>> thislist
['🍎', '🍓', '🍐', '🍎', '🍎', '🍓', '🍑']

Lists

Method Description
append() Adds an element at the end of the list
count() Returns the number of elements with the specified value
extend() Add the elements of a list (or any iterable), to the end of the current list
index() Returns the index of the first element with the specified value
insert() Adds an element at the specified position
pop() Removes the element at the specified position
remove() Removes the first item with the specified value
reverse() Reverses the order of the list
sort() Sorts the list

An Important Question

>> precedence = ['🥚', '🐔']

>> precedence.sort()

>> precedence

['🐔', '🥚']

Which Came First, the Chicken or the Egg?

List/Tuple Unpacking

>> a, b, c = ['🍎', '🍓', '🍐']
>> a
'🍎'
>> b
'🍓'
>> c
'🍐'

>> a, *b, c = ['🍎', '🍑', '🍓', '🍐']
>> b
['🍑', '🍓']

>> a, b = ['🍐', '🍎']
>> a, b = b, a # swap variables
>> a
'🍎'
>> b
'🍐'

Sets

>> first_set = {'🍎', '🍓', '🍐', '🍎', '🍎', '🍓'}

>> first_set
{'🍎', '🍐', '🍓'}

>> second_set = set(['🍌', '🍆', '🍓'])

>> third_set = second_set | first_set  # union

>> third_set
{'🍆', '🍌', '🍎', '🍐', '🍓'}

>> second_set & first_set
{'🍓'}

>> second_set < third_set 
True

Sets

Method Description
add() Adds an element to the set
difference() Returns a set containing the difference between two or more sets
discard() Remove the specified item
intersection() Returns a set, that is the intersection of two or more sets
isdisjoint() Returns whether two sets have a intersection or not
issubset() Returns whether another set contains this set or not
issuperset() Returns whether this set contains another set or not
symmetric_difference() Returns a set with the symmetric differences of two sets
union() Return a set containing the union of sets

Dictionaries

>> dict1 = {'🍎': 5, '🍓': 3, '🍐':0}

>> dict1['🍓']
3

>> dict1['🍓'] = dict1['🍓'] - 1

>> del dict1['🍓']

>> car = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964,
  "year": 2020
}
>> car
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}

Hashable

>> tuple_a = (1, 2, 3)
>> hash(tuple_a)
2528502973977326415

>> tuple_b = (2, 3, 4)
>> hash(tuple_b)
3789705017596477050

>> tuple_c = (1, 2, 3)
>> hash(tuple_c)
2528502973977326415

>> id(a) == id(c)
False # different objects.

>> hash(tuple_a == hash(tuple_c)
True # same value.

>> dict_a = {}
>> dict_a[tuple_a] = 'hiahia'
>> dict_a[tuple_c]
'hiahia'
>> a = [1,2,3]

>> hash(a)

TypeError: unhashable type: 'list'
    
>> b = {'a':1, 'b': 10}

>> hash(b)

TypeError: unhashable type: 'dict'
    
    
>> c = 123

>> hash(c)
123

>> d = 3.14

>> hash(d)
322818021289917443
  • An object is hashable if it has a hash value which never changes during its lifetime

Input & Output

pi = 3.14
r = float(input('Enter circle radius: '))
area = pi * r ** 2
print('The area of the cirle = %.2f' % area)
  • Prompt a string using the input function

  • Output the desired variable using the print function

Operators

Python divides the operators into the following groups:

  • Arithmetic operators

  • Assignment operators

  • Comparison operators

  • Logical operators

  • Identity operators

  • Membership operators

  • Bitwise operators

Arithmetic Operators

Operator Name Example
+ Addition x + y
- Subtraction x - y
* Multiplication x * y
/ Division x / y
% Modulus x % y
** Exponentiation x ** y
// Floor division x // y

Assignment Operators

Operator Example Same As
= x = 5 x = 5
:= x := 5 x = 5
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
/= x /= 3 x = x / 3
%= x %= 3 x = x % 3
//= x //= 3 x = x // 3
**= x **=2 x = x ** 2

Comparison Operators

Operator Name Example
== Equal x == y
!= Not equal x != y
> Greater than x > y
< Less than x < y
>= Greater than or equal to x >= y
<= Less than or equal to x <= y

Logical Operators

Operator Description Example
and  Returns True if both statements are true x < 5 and  x < 10
or Returns True if one of the statements is true x < 5 or x < 4
not Reverse the result, returns False if the result is true not(x < 5 and x < 10)

Identity Operators

Operator Description Example
is  Returns True if both variables are the same object x is y
is not Returns True if both variables are not the same object x is not y

Membership Operators

Operator Description Example
in  Returns True if a sequence with the specified value is present in the object x in y
not in Returns True if a sequence with the specified value is not present in the object x not in y

Conditional Statements

  • If statement

 

 

 

 

 

  • Ternary Operators
a = 200
b = 33
if b > a:
  print("b is greater than a")
elif a == b:
  print("a and b are equal")
else:
  print("a is greater than b")
print("Positive" if a > 0 else "Negative")
print("A" if a > b else "=" if a == b else "B")

Loops

  • While Loop
i = 0
while True:
    i += 1
    if i == 3:
        continue
    
    if i == 6:
        break
    print(i)
    
    
# 1  
# 2
# 4
# 5
i = 0
while i < 5:
    print(i**2)
    i += 1
else:
    print('done')
    
    
    
# 0
# 1
# 4
# 9
# 16
# done

Walrus Operator

string = "Lorem ipsum dolor sit amet"
if (n := len(string)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")
while (x := input('Enter a number: ')) != '0':
    print('Blah Blah Blah')
  • Assign values to variables as part of a larger expression

Loops

  • For loop

 

 

 

 

  • List comprehension
fruits = ["apple", "banana", "cherry"]

for x in fruits:
  print(x)
  
for i in range(6):
  print(i)
y = [x**2 for x in range(10)]
z = [x for x in range(10) if x % 2 == 0]
z = [x if x % 5!= 0 else 'HOP' for x in range(1, 11)]

Loops

  • Nested for loop

 

 

 

 

  • List comprehension
adj = ["red", "big", "tasty"]
fruits = ["apple", "banana", "cherry"]

for x in adj:
  for y in fruits:
    print(x, y)
z = [x**y for x in range(5) for y in range(2, 5)]

Functions

  • Functions are first-class objects
    • Can be used or passed as arguments.
  • Properties of first-class functions:
    • A function is an instance of the Object type.
    • You can store the function in a variable.
    • You can pass the function as a parameter to another function.
    • You can return the function from a function.
    • You can store them in data structures such as hash tables, lists, …

 

Functions

  • Functions

 

 

 

 

 

  • Anonymous functions
def f(x, y):
  return x**2 + y ** 0.5

print(f(1, 2))

print(f(x = 1, y = 2))

print(f(1, y = 2))
y = lambda x: x**2

Functions

  • Default parameters
def my_function(country = "Iran"):
  print("I am from " + country)

my_function("Norway")  # I am from Norway
my_function() # I am from Iran
  • Function Annotations
def area(radius: float) -> float:
    return 3.14 * radius ** 2

Functions

  • Arbitrary arguments
def prod(*numbers):
    r = 1
    for number in numbers:
        r *= number
    return r
  
print(prod(1, 2, 3, 4)) # 24
  • Arbitrary keyword arguments
def print_price(**computers):
    for key in computers:
        print('{:4s} - {:.2f}'.format(key, computers[key]))
        
print_price(dell = 1299.50, asus = 1870.00, hp = 1990.50)

Functions

def func(a, b, *, c=10, **kwargs):
    # do something
    return 
def pow(x, *, y):
    return x**y

pow(3, y=2)
pow(x=3, y=2)
  • Keyword-Only parameters
  • Keyword-Only parameters

Built-in Functions

abs() complex() getattr() len() pow() str()
all() delattr() globals() list() print() sum()
any() dict() hasattr() locals() property() super()
ascii() dir() hash() map() range() tuple()
bin() divmod() help() max() repr() type()
bool() enumerate() hex() memoryview() reversed() vars()
bytearray() eval() id() min() round() zip()
bytes() exec() input() next() set()
callable() filter() int() object() setattr()
chr() float() isinstance() oct() slice()
classmethod() format() issubclass() open() sorted()
compile() frozenset() iter() ord() staticmethod()  

Built-in Functions

def f(x):
  return x ** 2

x = [1,2,3,4]

map(f, x) # a generator

fx = list(map(f, x))  # [1, 4, 9, 16]

even_numbers = list(filter(lambda x: x % 2 == 0, x))   # [2, 4]

minimum = min(x) #  1

rev = list(reversed(x))  # [4, 3, 2, 1]

names = ['ali', 'hasan', 'reza']
ages = [25, 22, 30]

pair= list(zip(names,ages)) # [('ali',25),('hasan',22),('reza',30)]

pair_dict = dict(pair)    # {'ali': 25, 'hasan': 22, 'reza': 30}

Exception Handling

def func1():
    try:
        return 1
    finally:
        return 2

def func2():
    try:
        return 1
    except:
        return 2
    finally:
        return 3

func1(),func2() # 2, 3
x = 0
try:
    y = x / 0
except NameError as ex:
    print('x is not defined. Error:', ex)
except ZeroDivisionError:
    print('division by zero!')
else:
    print('code ran successfully')
finally:
    print('will run everytime')
    
    
# division by zero is not allowed
# will run everytime

Exceptions

Exception Exception Exception
AssertionError NameError SystemError
AttributeError NotImplementedError SystemExit
EOFError OSError TypeError
FloatingPointError OverflowError UnboundLocalError
GeneratorExit ReferenceError UnicodeError
ImportError RuntimeError UnicodeEncodeError
IndexError StopIteration UnicodeDecodeError
KeyError SyntaxError UnicodeTranslateError
KeyboardInterrupt IndentationError ValueError
MemoryError TabError ZeroDivisionError

Raise Exceptions

def fast_prime_check(n):
    raise NotImplementedError('This method has not been implemented, yet.')
    
    
def circle_area(radius):
    assert radius > 0, ValueError('Radius must be positive.')
    return 3.14 * radius ** 2

Files

file = open("demofile.txt", mode = 'r')
data = file.read()
file.close() # NEVER FORGET THIS


# Automatically close the file:
with open("demofile.txt", mode = 'r') as file:
  data = file.read()
  

# Create new files
with open("demofile.txt", mode = 'w') as file:
  file.write("Hello, World!")
  
  
# Append text to existing files
with open("demofile.txt", mode = 'a') as file:
  file.write("New Line.")

Iterators

  • An iterator is an object that contains a countable number of values.

mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)

print(next(myit))
print(next(myit))
print(next(myit))
  • Actually, for loops iterate over iterators
for x in mytuple:
  print(x)

Generators

  • Generator functions are a special kind of function that return a lazy iterator
  • They do not store their contents in memory.

def infinite_sequence():
    x = 0
    while True:
        yield 2 * x + 1
        x += 1

for x in infinite_sequence():
    print(x)
    if x > 20:
        break

Decorators

def hello_decorator(func):
    def inner1(*args, **kwargs):
        print("before Execution")                 
        returned_value = func(*args, **kwargs)
        print("after Execution")
        return returned_value
    return inner1
 
 
@hello_decorator
def sum_two_numbers(a, b):
    print("Inside the function")
    return a + b
 
a, b = 1, 2
 
print("Sum =", sum_two_numbers(a, b))

# before Execution
# Inside the function
# after Execution
# Sum = 3

Classes

class Animal:
    def _init_(self, name):
        self.name = name

    def make_sound(self):
        raise NotImplementedError

    def get_greet_message(self):
        return f'Hello {self.name}'
      
    def __del__(self):
        print(f'Bye {self.name}')



class Dog(Animal):
    def make_sound(self):
        print('woof, woof.')

        
class Cat(Animal):
    def make_sound(self):
        print('Meow, Meow.')

Classes

>>dog = Dog('Lucy')

>>dog.get_greet_message()
>>'Hello Lucy'

>>dog.make_sound()
woof, woof.

>>del dog
Bye Lucy

Match - Case

def http_status(status):
    match status:
        case 400:
            return "Bad request"
        case 401:
            return "Unauthorized"
        case 403:
            return "Forbidden"
        case 404:
            return "Not found"

Packages

Built-in Packages

  1. math
  2. time
  3. random
  4. tkinter
  5. re
  6. collections

  1. itertools
  2. functools
  3. multiprocessing
  4. zipfile
  5. sqlite
  6. http

Built-in Packages

import math
a = math.sin(math.pi)

from math import sin, pi
b = sin(pi)

from math import *
c = cos(2 * pi)

import math as m
c = m.cos(2 * m.pi)

There are many ways to import packages and functions inside them

Built-in Packages

import time
import random

print(time.time()) # unix time

random.seed(time.time())

print(random.random()) # random float between 0 and 1
  • Time: time related functions
>> import re

>> re.match('\w+@\w+\.\w{2,4}', 'alirezaafzalaghaei@gmail.com')
<re.Match object; span=(0, 28), match='alirezaafzalaghaei@gmail.com'>
  • Re: Regular Expressions

Built-in Packages

import sqlite3

try:
    sqliteConnection = sqlite3.connect('database.db')
    cursor = sqliteConnection.cursor()

    query = "SELECT sqlite_version();"
    cursor.execute(sqlite_select_Query)    
    record = cursor.fetchall()
    
    cursor.close()

except sqlite3.Error as error:
    print("Error while connecting to sqlite", error)
    
finally:
    if sqliteConnection:
        sqliteConnection.close()        
  • Sqlite: A simple Database!
  • Install third-party packages for better engines.

Built-in Packages

from multiprocessing import Pool

def f(x):
    return x**2

with Pool(4) as pool:
    res = pool.map(f, range(10))

    print(res)
  • Multiprocessing: Write parallel algorithms
import zipfile

with zipfile.ZipFile("hello.zip") as archive:
     archive.printdir()
  • ZipFile: Manipulate archives!

Built-in Packages

from functools import reduce
import operator

prod = lambda *x: reduce(operator.mul, x)

prod(1,2,3) # 6
  • Functools: Functional programming utilities
import random
from collections import Counter

def random_DNA(length=int()):        
  letters="CGTA"
  return''.join(random.choices(letters, k=length))

dna = random_DNA(20)            # AGTTTCACTGGATCCAATTG
counts = Counter(dna)
print(counts)                   # Counter({'T': 7, 'A': 5, 'G': 4, 'C': 4})
print(counts.most_common(2))    # [('T', 7), ('A', 5)]
  • Collections: Container Datatypes

Third-party Packages

  1. numpy
  2. scipy
  3. pandas
  4. matplotlib
  5. scikit-learn
  6. requests

$ pip install package_name

Install them using the pip command:

  1. BeautifulSoup
  2. opencv
  3. tensorflow
  4. Djnago
  5. PyQt
  6. networkx

Third-party Packages

# Terminal:
# $ pip install requests BeautifulSoup4
# $ python

import requests
from bs4 import BeautifulSoup


url = "https://varzesh3.com/"

response = requests.get(url).content.decode('utf8')

soup = BeautifulSoup(response)

next_games = soup.select("div.league.football div.fixture-result-match")
  • Requests: GET/POST HTTP requests
  • BeautifulSoup : Parse HTML result

Third-party Packages

# Terminal:
# $ pip install Selenium
# $ python

from selenium import webdriver

chrome = webdriver.Chrome()
chrome.get("https://maktabkhooneh.org")

user = {'email': 'a@b.cc','password': 'BlahBlahBlah'}
email.send_keys(user['email'])
password.send_keys(user['password'])
submit.click()
  • Simulate web browsing!
  • Useful for AJAX-based websites

Third-party Packages

# Terminal:
# $ pip install opencv-python
# $ python

import cv2

img = cv2.imread('dumb.jpg')

dst = cv2.resize(img, (224, 224))

cv2.imshow('img', dst)
  • OpenCV: Open Source Computer Vision
  • Manipulate images easily
  • Similar packages: scikit-image, pillow, etc.

Third-party Packages

# Terminal:
# $ pip install flask
# $ python

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
  • Flask: Build Websites, Serve HTTP requests!
  • Alternatives: Django, Sanic, bottle, etc.

Third-party Packages

# Terminal:
# $ pip install pyqt5
# $ python

from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
 
class Window(QMainWindow):
   def __init__(self):
       super().__init__()
 
       self.setGeometry(300, 300, 600, 400)
       self.setWindowTitle("PyQt5 window")
       self.show()
 
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
  • PyQT
  • Alternatives: kivy, wxPython, etc.

Third-party Packages

# Terminal:
# $ pip install networkx
# $ python

import networkx as nx


g = nx.Graph()
g.add_edge(131,673,weight=673)
g.add_edge(131,201,weight=201)
g.add_edge(673,96,weight=96)
g.add_edge(201,96,weight=96)

nx.shortest_path(g, source=131, target=96, weight='weight')
  • Networkx: Create complex networks and graphs

Third-party Packages

# Terminal:
# $ pip install numpy
# $ python

import numpy as np

A = np.random.random(size=(3, 4)) # random matrix of the shape 2x4
B = np.eye(4) # Identity Matrix

C = A @ B  # Matrix Multiplication

D = C.reshape(-1, 6)  # reshaped 6x6 matrix
  • Numpy: Linear Algebra package for python

Third-party Packages

# Terminal:
# $ pip install matplotlib
# $ python

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2 * np.pi, 10)
y = np.sin(x)

plt.plot(x, y)
  • Matplotlib: visualize data

Python Basics

By Alireza Afzal Aghaei

Python Basics

  • 641