Comprehensive Python Documentation

Complete Python Guide

From print("Hello World") to metaclasses and asynchronous programming, this documentation covers everything you need to master Python — practical examples, deep explanations, and best practices.

1 Introduction to Python

What is Python and why should you learn it?

Python is a high-level, interpreted, and multi-paradigm programming language created by Guido van Rossum in 1991. The philosophical design of Python focuses on code readability and simple syntax — so much so that Python code resembles English pseudocode.

Key Features

  • Clean and readable syntax: Using indentation instead of braces to define blocks
  • Dynamic typing: No need to define variable types (though Type Hints are available)
  • Automatic memory management: Built-in Garbage Collection
  • Rich standard library: More than 200 built-in modules
  • Multi-paradigm: Support for OOP, Functional, and Procedural
  • Embeddable: C/C++ code can be used in Python

Main Applications

Domain Key Libraries Example
Web Development Django, Flask, FastAPI Instagram, Pinterest
Data Science Pandas, NumPy, Matplotlib Financial data analysis
Artificial Intelligence TensorFlow, PyTorch, scikit-learn ChatGPT, AlphaGo
Automation Selenium, Requests, BeautifulSoup Web scraping, Telegram bot
DevOps Ansible, Docker SDK Infrastructure management
Note: Python 3.x is the current version. Python 2 reached end-of-life in January 2020. Always use Python 3.8+.

2 Installation and Setup

Python on Windows, Linux and macOS

Ubuntu/Debian.

bash
sudo apt update
bash
sudo apt install python3 python3-pip python3-venv

Fedora/RHEL.

bash
sudo dnf install python3 python3-pip

Arch Linux.

bash
sudo pacman -S python python-pip

Check.

bash
python3 --version
bash
pip3 --version

Creating a Virtual Environment

Create virtual environment.

bash
python3 -m venv myproject_env

Activation (Linux/macOS)

bash
source myproject_env/bin/activate

Activation (Windows)

bash
myproject_env\Scripts\activate

Install packages.

bash
pip install numpy pandas requests

Save dependencies.

bash
pip freeze > requirements.txt

Install from file.

bash
pip install -r requirements.txt

Deactivation.

bash
deactivate
Why virtual environment? Every Python project should have its own virtual environment to prevent conflicts between different library versions. This is one of the best practices for Python development.

3 Basic Syntax

Basic rules for writing Python code

First Program

This is a single-line comment.

Python
"""This is a multi-line comment"""
Python
print("Helloor!")

Output: Hello, World!

Print multiple values.

Python
print("Name:", "", "Age:", 25)

Using sep and end.

Python
print("A", "B", "C", sep="-", end="!\n")

Output: A-B-C!

Indentation

In Python, indentation is mandatory and replaces braces {}. The standard is to use 4 spaces (never Tab!).

Python
if True: print("This is correct") if True: print("Nested indentation") print("Outside condition")
Warning: Never mix Tab and Space! This is one of the most common beginner mistakes. In VS Code, configure Tab to convert to 4 spaces.

4 Variables and Data Types

Storing and managing data in Python

Basic Data Types

Type Example Description Mutable?
int 42, -7, 1_000_000 Integers (unlimited size) ❌
float 3.14, -0.5, 2.5e10 Floating point numbers (IEEE 754 double-precision) ❌
complex 3+4j Complex numbers ❌
str "hello", 'hi' Unicode strings ❌
bool True, False Boolean value ❌
NoneType None No value (null) ❌

Variable Definition

Simple definition.

Python
name = ""
Python
age = 25
Python
pi = 3.14159
Python
is_active = True

Multiple variables at once.

Python
x, y, z = 1, 2, 3

Swapping values.

Python
a, b = 10, 20
Python
a, b = b, a

A=20, b=10.

Unpacking.

Python
coords = (10, 20, 30)
Python
x, y, z = coords

Using _ for values we don't need.

Python
first, _, third = (1, 2, 3)

Extended unpacking (Python 3+)

Python
first, *rest = [1, 2, 3, 4, 5]

First=1, rest=[2,3,4,5].

Type checking.

Python
print(type(name))

<class 'str'>.

Python
print(isinstance(age, int))

True.

Type Hints

Python
from typing import List, Dict, Optional, Union

Function with Type Hints.

Python
def greet(name: str, age: int) -> str: return f"Hello {name}And {age} "

Optional - Value can be None.

Python
def find_user(user_id: int) -> Optional[Dict[str, str]]: pass

Union - Multiple possible types.

Python
def process(data: Union[str, int]) -> str: return str(data)

List Type.

Python
numbers: List[int] = [1, 2, 3]

5 Operators

All operators available in Python

Arithmetic Operators

Operator Name Example Result
+Addition5 + 38
-Subtraction5 - 32
*Multiplication5 * 315
/Division5 / 22.5
//Floor Division5 // 22
%Modulus5 % 21
**Power2 ** 38

Comparison Operators

Python
x = 10
Python
y = 20
Python
print(x == y)

False - Equality.

Python
print(x != y)

True - Inequality.

Python
print(x > y)

False - Greater than.

Python
print(x < y)

True - Less than.

Python
print(x >= 10)

True - Greater than or equal.

Python
print(x <= 10)

True - Less than or equal.

Is - Check Andor Object.

Python
a = [1, 2, 3]
Python
b = a
Python
print(a is b)

True.

Python
print(a is not [1, 2, 3])

True.

In - Check Membership.

Python
print(2 in a)

True.

Python
print("h" in "hello")

True.

Logical Operators

Python
age = 25 has_license = True

And - And True With.

Python
if age >= 18 and has_license: print("You can drive")

Or - At least one is True With.

Python
if age < 13 or age > 65: print("You have a discount")

Not - Reverse.

Python
if not has_license: print("First get a license")

Short-circuit evaluation.

Python
result = 0 or "default" result = 5 and "value" result = not 0

Bitwise Operators

Python
a = 0b1010

10 In.

Python
b = 0b1100

12 In.

Python
print(a & b)

AND: 0b1000 = 8.

Python
print(a | b)

OR: 0b1110 = 14.

Python
print(a ^ b)

XOR: 0b0110 = 6.

Python
print(~a)

NOT: -11.

Python
print(a << 1)

Shift left: 20.

Python
print(a >> 1)

Shift right: 5.

Assignment Operators

Operator Equivalent to Description
+=x = x + yAdd and assign
-=x = x - ySubtract and assign
*=x = x * yMultiply and assign
/=x = x / yDivide and assign
//=x = x // yFloor divide and assign
%=x = x % yModulus and assign
**=x = x ** yPower and assign
&=x = x & yBitwise AND and assign
|=x = x | yBitwise OR and assign
^=x = x ^ yBitwise XOR and assign
<<=x = x << yShift left and assign
>>=x = x >> yShift right and assign
:=walrusAssignment expression (Python 3.8+)

Walrus operator (:=); Assignment inside condition.

Python
if (n := len([1, 2, 3])) > 2: print(f"List {n} ")

Usage in while.

Python
while (line := input("Enter: ")) != "quit": print(f"You entered: {line}")

6 Conditional if-else

Controlling program flow with conditions

Basic Structure

Python
age = 25
Python
if age < 13: print("Child") elif age < 20: print("Teenager") elif age < 65: print("Adult") else: print("Senior")

One-line condition (Ternary).

Python
status = "Adult" if age >= 18 else "Minor"

Nested conditions.

Python
if age >= 18: if has_license: print("You can drive") else: print("First get a license") else: print("You are still too young")

Truthy and Falsy Values

In Python, the following values are considered False:

  • False
  • None
  • 0 (
  • 0.0 (Float
  • "" (Empty
  • [] (List
  • {} (Dictionary
  • set() (Set
  • () (Tuple

All other values are True.

Python
name = "" items = [1, 2]

Using truthiness.

Python
if name: print(f"Hello {name}")
Python
if items: print(f"{len(items)} items available")

Check None.

Python
result = None if result is None: print("No result found")

From any all.

Python
numbers = [1, 2, 3, 0] print(any(numbers)) print(all(numbers))

7 Loops

Repeating operations with for and while

for Loop

Loop over list.

Python
fruits = ["", "And", ""] for fruit in fruits: print(fruit)

Using range.

Python
for i in range(5): print(i)
Python
for i in range(2, 8): print(i)
Python
for i in range(0, 10, 2): print(i)

Enumerate - Index and value simultaneously.

Python
for index, fruit in enumerate(fruits): print(f"{index}: {fruit}")

Zip - Combine multiple iterables.

Python
names = ["", ""] ages = [25, 30] for name, age in zip(names, ages): print(f"{name} {age} ")

Reversed.

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

Sorted.

Python
numbers = [3, 1, 4, 1, 5] for num in sorted(numbers): print(num)

while Loop

Python
count = 0 while count < 5: print(count) count += 1

While else.

Python
while count < 10: print(count) count += 1 else: print("Loop completed")

Infinite loop with exit condition.

Python
while True: user_input = input("Enter a number (q to exit): ") if user_input == "q": break try: number = int(user_input) print(f"Square: {number ** 2}") except ValueError: print("Please enter a valid number")

break, continue, pass

Break - Exit loop.

Python
for i in range(10): if i == 5: break print(i)

Continue - Skip current iteration.

Python
for i in range(10): if i % 2 == 0: continue print(i)

Pass - Does nothing (placeholder).

Python
for i in range(5): pass

Else for Loop.

Python
for i in range(5): if i == 10: break else: print("No break occurred")

8 Comprehension

Building data structures concisely and efficiently

List Comprehension

Traditional method.

Python
squares = [] for x in range(10): squares.append(x ** 2)

List Comprehension.

Python
squares = [x ** 2 for x in range(10)]

With condition.

Python
evens = [x for x in range(20) if x % 2 == 0]

With if-else.

Python
labels = ["even" if x % 2 == 0 else "odd" for x in range(10)]

Nested.

Python
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]

Flatten list.

Python
nested = [[1, 2], [3, 4], [5, 6]] flat = [x for sublist in nested for x in sublist]

Dictionary Comprehension

Python
names = ["", "", ""]

Build dictionary.

Python
name_lengths = {name: len(name) for name in names}

With condition.

Python
long_names = {name: len(name) for name in names if len(name) > 3}

Reverse dictionary.

Python
original = {"a": 1, "b": 2, "c": 3} reversed_dict = {v: k for k, v in original.items()}

Set Comprehension

Python
numbers = [1, 2, 2, 3, 3, 3, 4]

Set Comprehension.

Python
unique_squares = {x ** 2 for x in numbers}

Generator Expression.

Python
sum_of_squares = sum(x ** 2 for x in range(1000000))
Warning: Do not overuse nested comprehensions. If code loses readability, use regular loops.

9 Match-Case (Python 3.10+)

Pattern Matching in Python

Simple Pattern Matching.

Python
def http_status(status): match status: case 200: return "OK" case 404: return "Not Found" case 500: return "Server Error" case _: return "Unknown status"

Pattern Matching with OR.

Python
match status: case 200 | 201: print("Success") case 400 | 401 | 403 | 404: print("Client Error")

Pattern Matching on Lists.

Python
match point: case [0, 0]: print("Origin") case [x, 0]: print(f"on x-axis at {x}") case [0, y]: print(f"on y-axis at {y}") case [x, y]: print(f"point ({x}, {y})") case _: print("Invalid format")

Pattern Matching on Dictionaries.

Python
match user: case {"name": str(name), "age": int(age)} if age >= 18: print(f"{name} is an adult") case {"name": name}: print(f"Name: {name}") case _: print("Invalid data")

10 Lists

Sequential and mutable data structure

Creation and Access

List.

Python
fruits = ["", "And", "", "And"]
Python
numbers = list(range(5))

[0, 1, 2, 3, 4].

Python
empty = []

List.

Python
mixed = [1, "hello", 3.14, True]

And.

Access Elements.

Python
print(fruits[0])

"" - First element.

Python
print(fruits[-1])

"And" - Last element.

Python
print(fruits[1:3])

["And", ""] - Slice.

Python
print(fruits[:2])

["", "And"] - From beginning.

Python
print(fruits[2:])

["", "And"] - To end.

Python
print(fruits[::2])

["", ""] - Every 2nd one.

Python
print(fruits[::-1])

Reverse.

Check existence.

Python
print("" in fruits)

True.

Python
print(len(fruits))

4.

Python
print(fruits.index("And"))

1.

Python
print(fruits.count(""))

1.

List Methods

Method Description Example
append(x)Add to endlst.append(5)
extend(iter)Add multiple elementslst.extend([1,2])
insert(i, x)Insert at position ilst.insert(0, "first")
remove(x)Remove first xlst.remove("apple")
pop([i])Remove and returnlst.pop() or lst.pop(0)
clear()Clear listlst.clear()
index(x)Position of first xlst.index("a")
count(x)Count of xlst.count(1)
sort()Sort in-placelst.sort(reverse=True)
reverse()Reverse in-placelst.reverse()
copy()Shallow copynew = lst.copy()
Python
numbers = [3, 1, 4, 1, 5, 9, 2, 6]

Sorting.

Python
numbers.sort() numbers.sort(reverse=True)

Sorting with key.

Python
words = ["banana", "pie", "Washington"] words.sort(key=len)

Sorted() - new list.

Python
new_sorted = sorted(numbers, reverse=True)

Copying; Shallow copy.

Python
shallow = numbers.copy() shallow = numbers[:] shallow = list(numbers)

Deep copy (for nested lists).

Python
import copy nested = [[1, 2], [3, 4]] deep = copy.deepcopy(nested)
Note: sort() sorts the list in-place and None ‌sorted() creates a new list.

11 Tuples

Sequential and immutable data structure

Tuple.

Python
point = (3, 4) single = (5,) empty = () coords = 1, 2, 3

Access similar to list.

Python
print(point[0]) print(point[-1]) print(point[1:])

Unpacking.

Python
x, y = point a, b, c = coords

Tuple as dictionary key.

Python
locations = { (0, 0): "Origin", (1, 0): "East", (0, 1): "North" }

Named Tuple.

Python
from collections import namedtuple
Python
Point = namedtuple("Point", ["x", "y"]) p = Point(3, 4) print(p.x, p.y) print(p[0])

Nested tuples.

Python
matrix = ( (1, 2, 3), (4, 5, 6), (7, 8, 9) ) print(matrix[1][1])
When to use tuples: When data is fixed (like coordinates, configuration settings), or you want to prevent accidental changes, or need a hashable type (dictionary key, set member).

12 Dictionaries

Key-value data structure

Creation and Access

Dictionary.

Python
person = { "name": "", "age": 25, "city": "" }

Or dict().

Python
person2 = dict(name="", age=30)

Access.

Python
print(person["name"]) print(person.get("age")) print(person.get("job", "N/A"))

/‌And.

Python
person["email"] = "ali@example.com" person.update({"phone": "0912...", "age": 26})

Delete.

Python
del person["city"] email = person.pop("email") last = person.popitem()

Check.

Python
print("name" in person) print(len(person))

Iteration.

Python
for key in person: print(key)
Python
for key, value in person.items(): print(f"{key}: {value}")
Python
for value in person.values(): print(value)

Dictionary Methods

Method Description
keys()Return keys
values()Return values
items()Return (key, value) tuples
get(key, default)Safe access with default value
setdefault(key, default)Set if not exists
update(other)Update with another dictionary
pop(key)Remove key and return value
popitem()Remove and return last item
clear()Clear
copy()Shallow copy
fromkeys(keys, value)Build from list of keys

Advanced dictionaries

Defaultdict.

Python
from collections import defaultdict
Python
word_count = defaultdict(int) for word in ["apple", "banana", "apple"]: word_count[word] += 1 print(word_count)

Counter.

Python
from collections import Counter
Python
counts = Counter(["a", "b", "a", "c", "a"]) print(counts.most_common(2))

OrderedDict (Python 3.7+ dictordered Is.

Python
from collections import OrderedDict

Merge dictionaries (Python 3.9+).

Python
dict1 = {"a": 1, "b": 2} dict2 = {"b": 3, "c": 4} merged = dict1 | dict2

Dictionary unpacking.

Python
combined = {**dict1, **dict2}

Setdefault; Grouping with dictionary.

Python
groups = {} for item in [("A", 1), ("B", 2), ("A", 3)]: key, value = item groups.setdefault(key, []).append(value) print(groups)

13 Sets

Unordered data structure with unique members

Set.

Python
fruits = {"", "And", ""}
Python
numbers = set([1, 2, 2, 3, 3, 3])

{1, 2, 3}.

Python
empty = set()

{} empty dictionary makes‌From!

Set Operations.

Python
a = {1, 2, 3, 4}
Python
b = {3, 4, 5, 6}

Union.

Python
print(a | b)

{1, 2, 3, 4, 5, 6}.

Python
print(a.union(b))

Subscription.

Python
print(a & b)

{3, 4}.

Python
print(a.intersection(b))

Difference.

Python
print(a - b)

{1, 2}.

Python
print(a.difference(b))

Symmetric Difference.

Python
print(a ^ b)

{1, 2, 5, 6}.

Python
print(a.symmetric_difference(b))

Subset and Superset.

Python
print({1, 2} <= a)

True - Subset.

Python
print(a >= {1, 2})

True - Superset.

/Delete.

Python
fruits.add("And")
Python
fruits.remove("And")

KeyError If With.

Python
fruits.discard("And")

BadError.

Python
fruits.pop()

Delete.

Python
fruits.clear()

Frozenset - Immutable.

Python
immutable = frozenset([1, 2, 3])

Can be dictionary key or set member.

Practical use: Sets are very efficient for removing duplicates, membership testing (O(1)), and mathematical set operations.

14 Strings

Working with text in Python

Creation and Formatting

Python
name = ""
Python
age = 25

F-string (And Python 3.6+)

Python
message = f"Hello {name}And {age} "

Formatting Advanced.

Python
pi = 3.14159265359
Python
print(f"Pi = {pi:.2f}")

3.14.

Python
print(f"Pi = {pi:10.4f}")

3.1416.

Python
print(f"Number = {42:05d}")

00042.

Python
print(f"Binary = {42:b}")

101010.

Python
print(f"Hex = {255:x}")

Ff.

Strings.

Python
text = """This is a multi-line string"""

Raw string.

Python
path = r"C:\Users\Name\file.txt"

Bytes.

Python
data = b"hello"
Python
utf8 = "Hello".encode("utf-8")
Python
text2 = utf8.decode("utf-8")

String Methods

Method Description Example
upper()Uppercase"hello".upper() → "HELLO"
lower()Lowercase"HELLO".lower() → "hello"
title()First letter of each word"hello world".title() → "Hello World"
strip()Remove whitespace" hello ".strip() → "hello"
split(sep)Division"a,b,c".split(",") → ["a","b","c"]
join(iter)Join",".join(["a","b"]) → "a,b"
replace(old, new)Replacement"hello".replace("l","x") → "hexxo"
find(sub)Substring position"hello".find("l") → 2
startswith()Starts with"hello".startswith("he") → True
endswith()Ends with"hello.txt".endswith(".txt") → True
isdigit()Is it a number?"123".isdigit() → True
isalpha()Is it a letter?"abc".isalpha() → True
count(sub)Count occurrences"hello".count("l") → 2

String Slicing.

Python
text = "Hello, World!"
Python
print(text[0:5])

"Hello".

Python
print(text[7:])

"World!".

Python
print(text[::2])

"Hlo ol!".

Python
print(text[::-1])

"!dlroW ,olleH".

Content Check.

Python
print("123".isnumeric())

True.

Python
print("hello".islower())

True.

Python
print(" ".isspace())

True.

And.

Python
print(text.index("World"))

7.

Python
print(text.find("xyz"))

-1 (BadError)

Python
print(text.count("l"))

3.

Alignment.

Python
print("hello".center(20, "-"))

"-------hello--------".

Python
print("hello".ljust(10))

"hello ".

Python
print("42".zfill(5))

"00042".

Partition.

Python
print("key=value".partition("="))

('key', '=', 'value')

15 Functions

Defining and using functions in Python

Function Definition

Simple.

Python
def greet(name): """Greeting the user.""" return f"Hello {name}!"

Function with default value.

Python
def power(base, exponent=2): return base ** exponent
Python
print(power(3)) print(power(2, 3))

Args and kwargs.

Python
def flexible(*args, **kwargs): print("Positional:", args) print("Keyword:", kwargs)
Python
flexible(1, 2, 3, name="", age=25)

Unpacking during call.

Python
nums = [1, 2] power(*nums)
Python
params = {"base": 2, "exponent": 3} power(**params)

Keyword-only arguments (Python 3+).

Python
def safe_divide(a, b, *, strict=False): if strict and b == 0: raise ValueError("Division by zero") return a / b if b != 0 else None
Python
safe_divide(10, 2, strict=True)

Positional-only (Python 3.8+).

Python
def greet_pos(name, /, greeting="Hello"): return f"{greeting} {name}"
Python
greet_pos("") greet_pos("", greeting="And")

Docstrings

Python
def calculate_area(length, width): """Calculate rectangle area. Args: length (float): Rectangle length. width (float): Rectangle width. Returns: float: Calculated area. Raises: ValueError: If length or width is negative. Examples: >>> calculate_area(5, 3) 15.0 """ if length < 0 or width < 0: raise ValueError("Dimensions cannot be negative") return length * width

Access docstring.

Python
print(calculate_area.__doc__) print(calculate_area.__name__)

16 Lambda

Anonymous one-line functions

Definition lambda.

Python
square = lambda x: x ** 2 print(square(5))

Argument.

Python
add = lambda x, y: x + y print(add(3, 4))

With map.

Python
numbers = [1, 2, 3, 4, 5] squared = list(map(lambda x: x ** 2, numbers))

With filter.

Python
evens = list(filter(lambda x: x % 2 == 0, numbers))

With sorted.

Python
words = ["banana", "pie", "Washington"] sorted_by_length = sorted(words, key=lambda x: len(x))

With reduce.

Python
from functools import reduce product = reduce(lambda x, y: x * y, [1, 2, 3, 4])

Closure lambda.

Python
def make_multiplier(n): return lambda x: x * n
Python
double = make_multiplier(2) triple = make_multiplier(3) print(double(5)) print(triple(5))
Warning: Do not use lambda for complex operations. If lambda needs more than one expression, use def. PEP 8 recommends not assigning lambdas to variables.

17 Decorators

Changing function behavior without modifying code

Basic Decorator

Decorator.

Python
def my_decorator(func): def wrapper(*args, **kwargs): print("Before function") result = func(*args, **kwargs) print("After function") return result return wrapper
Python
@my_decorator def say_hello(): print("Hello!")
Python
say_hello()

Decorator with argument.

Python
def repeat(times): def decorator(func): def wrapper(*args, **kwargs): for _ in range(times): result = func(*args, **kwargs) return result return wrapper return decorator
Python
@repeat(3) def greet(name): print(f"Hello {name}")
Python
greet("")

Functools.wraps - preserve metadata.

Python
from functools import wraps
Python
def timer(func): @wraps(func) def wrapper(*args, **kwargs): import time start = time.time() result = func(*args, **kwargs) elapsed = time.time() - start print(f"{func.__name__} {elapsed:.4f} Seconds") return result return wrapper
Python
@timer def slow_function(): """This function is slow.""" import time time.sleep(1)
Python
slow_function() print(slow_function.__name__) print(slow_function.__doc__)

Class Decorators

@property.

Python
class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): return self._radius @radius.setter def radius(self, value): if value < 0: raise ValueError("Radius cannot be negative") self._radius = value @property def area(self): import math return math.pi * self._radius ** 2
Python
c = Circle(5) print(c.radius) c.radius = 10 print(c.area)

@staticmethod @classmethod.

Python
class DateUtil: @staticmethod def is_leap_year(year): return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) @classmethod def from_string(cls, date_str): year, month, day = map(int, date_str.split("-")) return cls(year, month, day)
Python
print(DateUtil.is_leap_year(2024))

18 Modules and Packages

Organizing code with modules

Import.

Python
import math print(math.pi) print(math.sqrt(16))

From import.

Python
from math import pi, sqrt print(pi)

Alias.

Python
import numpy as np import pandas as pd

Import all (not recommended‌And).

Python
from math import *

Import Package‌; from . import module; from .. import parent_module.

__all__ - import *; File __init__.py:; __all__ = ['func1', 'func2', 'Class1'].

If __name__ == "__main__":; Code that only runs when file is executed directly.

Python
if __name__ == "__main__": print("This file was executed directly")

Sys.path - import.

Python
import sys print(sys.path)

Add custom path; sys.path.append("/path/to/modules").

Importlib - Dynamic import.

Python
import importlib module = importlib.import_module("math") print(module.pi)

Package Structure

bash
mypackage/ __init__.py module1.py module2.py subpackage/ __init__.py module3.py

Usage:; import mypackage.module1; from mypackage.subpackage import module3.

19 Generators

Generating values lazily

Generator Function.

Python
def count_up_to(n): count = 1 while count <= n: yield count count += 1
Python
counter = count_up_to(5) print(next(counter)) print(next(counter))

Generator Expression.

Python
squares = (x ** 2 for x in range(1000000))

Fibonacci Generator.

Python
def fibonacci(n): a, b = 0, 1 for _ in range(n): yield a a, b = b, a + b
Python
for num in fibonacci(10): print(num)

Generator with send().

Python
def running_average(): total = 0 count = 0 average = None while True: term = yield average total += term count += 1 average = total / count
Python
avg = running_average() next(avg) print(avg.send(10)) print(avg.send(20)) print(avg.send(30))

Itertools.

Python
import itertools

Count - infinite counting.

Python
for i in itertools.count(10, 2): if i > 20: break print(i)

Cycle - infinite cycling.

Python
counter = 0 for item in itertools.cycle(["A", "B", "C"]): if counter >= 6: break print(item) counter += 1

Chain - Join iterator.

Python
for x in itertools.chain([1, 2], [3, 4], [5, 6]): print(x)

20 Classes and Objects

Fundamentals of object-oriented programming in Python

Class Definition

Python
class Dog: species = "Canis familiaris" def __init__(self, name, age): self.name = name self.age = age def description(self): return f"{self.name} is {self.age} years old" def speak(self, sound): return f"{self.name} says {sound}" def __str__(self): return f"Dog(name={self.name}, age={self.age})" def __repr__(self): return f"Dog('{self.name}', {self.age})"

Object.

Python
buddy = Dog("Buddy", 3) print(buddy.name) print(buddy.species) print(buddy.description()) print(buddy.speak("Woof Woof")) print(str(buddy)) print(repr(buddy))

Type checking.

Python
print(isinstance(buddy, Dog)) print(type(buddy))

Class Methods and Static Methods

Python
class Person: population = 0 def __init__(self, name): self.name = name Person.population += 1 @classmethod def get_population(cls): return cls.population @classmethod def create_anonymous(cls): return cls("Anonymous") @staticmethod def is_adult(age): return age >= 18
Python
p1 = Person("") p2 = Person("") print(Person.get_population()) print(Person.is_adult(20))
Python
anon = Person.create_anonymous() print(anon.name)

21 Inheritance

Inheriting from other classes

Base Class.

Python
class Animal: def __init__(self, name): self.name = name def speak(self): raise NotImplementedError("Subclass must implement") def introduce(self): return f"I am {self.name}"

Child Class.

Python
class Dog(Animal): def __init__(self, name, breed): super().__init__(name) self.breed = breed def speak(self): return f"{self.name} says Woof!" def fetch(self): return f"{self.name} is fetching"

Inheritance.

Python
class FlyingDog(Dog): def fly(self): return f"{self.name} is flying!"
Python
dog = Dog("Buddy", "Golden Retriever") print(dog.introduce()) print(dog.speak()) print(dog.fetch())

MRO - Method Resolution Order.

Python
print(Dog.__mro__)

Isinstance issubclass.

Python
print(isinstance(dog, Dog)) print(isinstance(dog, Animal)) print(issubclass(Dog, Animal))

Multiple Inheritance

Python
class Flyable: def fly(self): return "Flying!"
Python
class Swimmable: def swim(self): return "Swimming!"
Python
class Duck(Flyable, Swimmable): def quack(self): return "Quack!"
Python
duck = Duck() print(duck.fly()) print(duck.swim()) print(duck.quack())

MRO Inheritance.

Python
print(Duck.__mro__)

22 Encapsulation

Hiding data and controlling access

Python
class BankAccount: def __init__(self, owner, balance=0): self.owner = owner self.__balance = balance self._transaction_count = 0 @property def balance(self): return self.__balance @balance.setter def balance(self, value): if value < 0: raise ValueError("Balance cannot be negative") self.__balance = value def deposit(self, amount): if amount <= 0: raise ValueError("Amount must be positive") self.__balance += amount self._transaction_count += 1 def withdraw(self, amount): if amount > self.__balance: raise ValueError("Insufficient funds") self.__balance -= amount self._transaction_count += 1
Python
account = BankAccount("", 1000) account.deposit(500) account.withdraw(200) print(account.balance)

Name Mangling; __balance -> _BankAccount__balance; print(account.__balance) # Error!

Python
print(account._BankAccount__balance)

__slots__ - And attributes.

Python
class Point: __slots__ = ["x", "y"] def __init__(self, x, y): self.x = x self.y = y
Python
p = Point(1, 2)

23 Polymorphism

One interface, different implementations

Duck Typing.

Python
class Duck: def speak(self): return "Quack!" def move(self): return "Swimming"
Python
class Dog: def speak(self): return "Woof!" def move(self): return "Running"
Python
def animal_concert(animals): for animal in animals: print(animal.speak())
Python
animal_concert([Duck(), Dog()])

Abstract Base Classes.

Python
from abc import ABC, abstractmethod
Python
class Shape(ABC): @abstractmethod def area(self): pass @abstractmethod def perimeter(self): pass
Python
class Rectangle(Shape): def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def perimeter(self): return 2 * (self.width + self.height)

Shape = Shape() # Error! ‌Power ABC instantiate.

Python
rect = Rectangle(5, 3) print(rect.area()) print(rect.perimeter())

Protocols (Python 3.8+).

Python
from typing import Protocol
Python
class Drawable(Protocol): def draw(self) -> None: ...
Python
class Circle: def draw(self): print("Drawing circle")
Python
def render(item: Drawable): item.draw()
Python
render(Circle())

24 Magic Methods

Double underscore methods (__dunder__)

Method Operator/Function Description
__init__(self)Constructorinitialization
__new__(cls)Before __init__Create
__del__(self)Deletedestructor
__str__(self)str()User-friendly display
__repr__(self)repr()Detailed display
__eq__(self, other)==Equality
__ne__(self, other)!=Inequality
__lt__(self, other)<Less than
__le__(self, other)<=Less than or equal
__gt__(self, other)>Greater than
__ge__(self, other)>=Greater than or equal
__add__(self, other)+Addition
__sub__(self, other)-Subtraction
__mul__(self, other)*Multiplication
__truediv__(self, other)/Division
__len__(self)len()Length
__getitem__(self, key)obj[key]Access
__setitem__(self, key, val)obj[key] = valSet
__contains__(self, item)inMembership
__iter__(self)iter()iteration
__next__(self)next()Next iteration
__call__(self)obj()Call
__enter__ / __exit__withContext Manager
Python
class Vector: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"Vector({self.x}, {self.y})" def __repr__(self): return f"Vector({self.x!r}, {self.y!r})" def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __sub__(self, other): return Vector(self.x - other.x, self.y - other.y) def __mul__(self, scalar): return Vector(self.x * scalar, self.y * scalar) def __rmul__(self, scalar): return self * scalar def __eq__(self, other): return self.x == other.x and self.y == other.y def __len__(self): return int((self.x ** 2 + self.y ** 2) ** 0.5) def __getitem__(self, index): if index == 0: return self.x if index == 1: return self.y raise IndexError("Index out of range")
Python
v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) print(v2 - v1) print(v1 * 3) print(3 * v1) print(v1 == v2) print(len(v1)) print(v1[0])

25 Read and write File

Working with files in Python

File Modes

Mode Description
'r'Read (default)
'w'Write (overwrite)
'x'Exclusive creation (error if exists)
'a'Append to end
'b'Binary
't'Text (default)
'+'Read and write

Reading entire file.

Python
with open("data.txt", "r", encoding="utf-8") as f: content = f.read() print(content)

Reading line by line.

Python
with open("data.txt", "r", encoding="utf-8") as f: for line in f: print(line.strip())

Reading to list.

Python
with open("data.txt", "r", encoding="utf-8") as f: lines = f.readlines()

Reading part of a file.

Python
with open("data.txt", "r", encoding="utf-8") as f: chunk = f.read(1024)

File.

Python
with open("output.txt", "w", encoding="utf-8") as f: f.write("Hello or!\n") f.write("Second line\n")

Appending to file.

Python
with open("log.txt", "a", encoding="utf-8") as f: f.write("or\n")

Writing list of lines.

Python
lines = ["Line 1", "Line 2", "Line 3"] with open("lines.txt", "w", encoding="utf-8") as f: f.writelines(line + "\n" for line in lines)

File Binary.

Python
with open("image.png", "rb") as f: data = f.read()

Seek tell.

Python
with open("data.txt", "r", encoding="utf-8") as f: f.seek(10) pos = f.tell() data = f.read(20)

26 Context Managers

Managing resources with with

Context Manager with Class.

Python
class DatabaseConnection: def __init__(self, host): self.host = host self.connection = None def __enter__(self): print(f"Connecting to {self.host}...") self.connection = "connected" return self def __exit__(self, exc_type, exc_val, exc_tb): print("Closing connection...") self.connection = None return False def query(self, sql): return f"Result of: {sql}"
Python
with DatabaseConnection("localhost") as db: print(db.query("SELECT * FROM users"))

With contextlib.

Python
from contextlib import contextmanager
Python
@contextmanager def managed_resource(name): print(f"Acquiring {name}") resource = {"name": name} try: yield resource finally: print(f"Releasing {name}")
Python
with managed_resource("database") as res: print(f"Using {res['name']}")

Contextlib.suppress.

Python
from contextlib import suppress
Python
with suppress(FileNotFoundError): with open("nonexistent.txt") as f: print(f.read())

Contextlib.redirect_stdout.

Python
from contextlib import redirect_stdout import io
Python
f = io.StringIO() with redirect_stdout(f): print("This goes to StringIO") output = f.getvalue() print(output)

27 CSV and JSON

Working with common data formats

CSV

Python
import csv

Reading CSV.

Python
with open("data.csv", "r", encoding="utf-8") as f: reader = csv.reader(f) header = next(reader) for row in reader: print(row)

Reading as Dictionary.

Python
with open("data.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: print(row["name"], row["age"])

Writing CSV.

Python
data = [ ["name", "age", "city"], ["", "25", ""], ["", "30", ""] ]
Python
with open("output.csv", "w", encoding="utf-8", newline="") as f: writer = csv.writer(f) writer.writerows(data)

Writing from Dictionary.

Python
with open("output.csv", "w", encoding="utf-8", newline="") as f: fieldnames = ["name", "age", "city"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerow({"name": "", "age": "25", "city": ""})

JSON

Python
import json

Convert to JSON (serialize).

Python
data = { "name": "", "age": 25, "skills": ["Python", "Linux"], "active": True }
Python
json_str = json.dumps(data, ensure_ascii=False, indent=2) print(json_str)

Save to file.

Python
with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)

Reading JSON.

Python
with open("data.json", "r", encoding="utf-8") as f: loaded = json.load(f)

Parse from string.

Python
parsed = json.loads('{"name": "test", "value": 42}')

Custom JSON Encoder.

Python
class DateTimeEncoder(json.JSONEncoder): def default(self, obj): from datetime import datetime if isinstance(obj, datetime): return obj.isoformat() return super().default(obj)
Python
from datetime import datetime data = {"time": datetime.now()} json_str = json.dumps(data, cls=DateTimeEncoder)

28 Try-Except

Error handling in Python

Basic Structure.

Python
try: result = 10 / 0 except ZeroDivisionError: print("‌Power Division ")

Multiple except.

Python
try: num = int("abc") except ValueError: print("Value Name") except TypeError: print("Type Name")

Catching exception object.

Python
try: open("nonexistent.txt") except FileNotFoundError as e: print(f"Error: {e}") print(f"Filename: {e.filename}")

Multiple except.

Python
try: pass except (ValueError, TypeError) as e: print(f"Error: {e}")

Generic except (use with caution).

Python
try: risky_operation() except Exception as e: print(f"Unexpected error: {e}")

Else - if no exception occurs.

Python
try: result = 10 / 2 except ZeroDivisionError: print("Division by zero") else: print(f"Result: {result}")

Finally - always executes.

Python
try: f = open("file.txt") data = f.read() except FileNotFoundError: print("File not found") finally: print("Cleanup code here")

Raise - throw exception.

Python
def validate_age(age): if age < 0: raise ValueError("Age cannot be negative") if age > 150: raise ValueError("Age seems unrealistic") return age

Raise without argument - re-raise.

Python
try: pass except ValueError: print("Logging error...") raise

29 Custom Exceptions

Creating your own exceptions

Simple Exception.

Python
class ValidationError(Exception): """Raised when input validation fails.""" pass

Exception with custom message.

Python
class InsufficientFundsError(Exception): def __init__(self, balance, amount): self.balance = balance self.amount = amount super().__init__(f"Insufficient funds: balance={balance}, requested={amount}")

Exception Hierarchy.

Python
class AppError(Exception): """Base exception for our application.""" pass
Python
class DatabaseError(AppError): """Database related errors.""" pass
Python
class ConnectionError(DatabaseError): """Connection failed.""" pass
Python
class QueryError(DatabaseError): """Query execution failed.""" pass
Python
class BankAccount: def __init__(self, balance): self.balance = balance def withdraw(self, amount): if amount > self.balance: raise InsufficientFundsError(self.balance, amount) self.balance -= amount return self.balance

Exception Groups (Python 3.11+).

Python
def faulty(): raise ExceptionGroup("group", [ ValueError("invalid value"), TypeError("invalid type"), ValueError("another value error") ])
Python
try: faulty() except* ValueError as eg: for error in eg.exceptions: print(f"ValueError: {error}") except* TypeError as eg: for error in eg.exceptions: print(f"TypeError: {error}")

30 Finally and Else

Complementary parts of try-except

Complete try-except structure.

Python
try: print("Trying...") result = 10 / 2 except ZeroDivisionError: print("Caught ZeroDivisionError") else: print(f"Success! Result: {result}") finally: print("Always executes")

Else: only if no exception occurs; finally: always executes (even with return).

Finally with return.

Python
def demo(): try: return "try" finally: print("finally executes before return!")
Python
print(demo())

Suppress context manager.

Python
from contextlib import suppress
Python
with suppress(FileNotFoundError): open("missing.txt") print("Program continues...")

Assert - for debugging; assert condition, message; If condition is False, AssertionError; Disabled in -O (optimized) mode.

Python
x = 10 assert x > 0, "x must be positive"

31 Iterators

Iteration protocol in Python

Custom Iterator.

Python
class Countdown: def __init__(self, start): self.start = start def __iter__(self): return self def __next__(self): if self.start <= 0: raise StopIteration self.start -= 1 return self.start + 1
Python
for num in Countdown(5): print(num)

Separate Iterator.

Python
class Range: def __init__(self, start, end): self.start = start self.end = end def __iter__(self): return RangeIterator(self.start, self.end)
Python
class RangeIterator: def __init__(self, start, end): self.current = start self.end = end def __iter__(self): return self def __next__(self): if self.current >= self.end: raise StopIteration num = self.current self.current += 1 return num

Reversible Iterator.

Python
class ReversibleRange: def __init__(self, start, end): self.start = start self.end = end def __iter__(self): return iter(range(self.start, self.end)) def __reversed__(self): return iter(range(self.end - 1, self.start - 1, -1))
Python
r = ReversibleRange(1, 5) print(list(r)) print(list(reversed(r)))

32 Contextlib

Context Manager tools

Python
from contextlib import contextmanager, suppress, redirect_stdout import os

@contextmanager.

Python
@contextmanager def temporary_directory(path): os.makedirs(path, exist_ok=True) try: yield path finally: os.rmdir(path)
Python
with temporary_directory("/tmp/test_dir") as path: print(f"Working in {path}")

Suppress.

Python
with suppress(FileNotFoundError, PermissionError): os.remove("nonexistent_file.txt")

Redirect_stdout.

Python
import io f = io.StringIO() with redirect_stdout(f): print("Hello") print("World") print(f.getvalue())

ExitStack.

Python
from contextlib import ExitStack
Python
with ExitStack() as stack: files = [ stack.enter_context(open(fname)) for fname in ["a.txt", "b.txt", "c.txt"] ]

Contextlib.closing.

Python
from contextlib import closing from urllib.request import urlopen
Python
with closing(urlopen("https://example.com")) as page: for line in page: print(line)

33 Metaclasses

Classes that create classes

Type(name, bases, namespace); type itself is a metaclass.

Custom Metaclass.

Python
class SingletonMeta(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls]
Python
class Database(metaclass=SingletonMeta): def __init__(self): print("Initializing database...")
Python
db1 = Database() db2 = Database() print(db1 is db2)

Metaclass for validation.

Python
class InterfaceMeta(type): def __new__(mcs, name, bases, namespace): if "process" not in namespace: raise TypeError(f"{name} must implement process()") return super().__new__(mcs, name, bases, namespace)
Python
class Processor(metaclass=InterfaceMeta): def process(self, data): return data.upper()

Class BadProcessor(metaclass=InterfaceMeta):; pass # TypeError!

__init_subclass__ (Python 3.6+).

Python
class BasePlugin: def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) print(f"Plugin registered: {cls.__name__}")
Python
class EmailPlugin(BasePlugin): pass

34 Async/Await

Asynchronous programming in Python

Python
import asyncio

Simple coroutine.

Python
async def say_hello(): print("Hello") await asyncio.sleep(1) print("World")

Asyncio.run(say_hello()).

Coroutine.

Python
async def task(name, delay): print(f"Task {name} starting") await asyncio.sleep(delay) print(f"Task {name} done") return f"Result {name}"
Python
async def main(): results = await asyncio.gather( task("A", 2), task("B", 1), task("C", 3) ) print(results) task1 = asyncio.create_task(task("D", 1)) task2 = asyncio.create_task(task("E", 1)) await task1 await task2 for coro in asyncio.as_completed([ task("F", 3), task("G", 1), task("H", 2) ]): result = await coro print(f"Completed: {result}")

Asyncio.run(main()).

Async Context Manager.

Python
class AsyncDatabase: async def __aenter__(self): print("Connecting...") await asyncio.sleep(0.1) return self async def __aexit__(self, exc_type, exc, tb): print("Disconnecting...") await asyncio.sleep(0.1) async def query(self, sql): await asyncio.sleep(0.1) return ["result1", "result2"]

Async with AsyncDatabase() as db:; results = await db.query("SELECT * FROM users").

Async Iterator.

Python
class AsyncRange: def __init__(self, n): self.n = n self.i = 0 def __aiter__(self): return self async def __anext__(self): if self.i >= self.n: raise StopAsyncIteration await asyncio.sleep(0.01) value = self.i self.i += 1 return value

Async for i in AsyncRange(5):; print(i).

35 Type Hints Advanced

Python type system

Python
from typing import ( List, Dict, Set, Tuple, Optional, Union, Callable, Iterable, Iterator, Generator, Any, TypeVar, Generic, Protocol )

Basic types.

Python
def process(items: List[int]) -> Dict[str, int]: return {str(item): item for item in items}

Optional.

Python
def find(items: List[str], target: str) -> Optional[int]: try: return items.index(target) except ValueError: return None

Union.

Python
def parse(value: Union[str, int]) -> int: return int(value)

Python 3.10+ syntax; def parse(value: str | int) -> int:

Callable.

Python
def apply(func: Callable[[int], bool], items: List[int]) -> List[int]: return [x for x in items if func(x)]

TypeVar.

Python
T = TypeVar('T')
Python
def first(items: List[T]) -> Optional[T]: return items[0] if items else None

Generic.

Python
class Stack(Generic[T]): def __init__(self) -> None: self._items: List[T] = [] def push(self, item: T) -> None: self._items.append(item) def pop(self) -> T: return self._items.pop()

Protocol.

Python
class Drawable(Protocol): def draw(self) -> None: ...
Python
def render(item: Drawable) -> None: item.draw()from typing import TypedDict
Python
class Movie(TypedDict): name: str year: int rating: float
Python
movie: Movie = {"name": "Inception", "year": 2010, "rating": 8.8}

36 os and sys

Interacting with the operating system

Python
import os import sys

Os - paths and files.

Python
print(os.getcwd()) os.chdir("/tmp") print(os.listdir("."))

/Delete And.

Python
os.makedirs("path/to/dir", exist_ok=True) os.rmdir("empty_dir")
Python
path = os.path.join("folder", "file.txt") print(os.path.exists(path)) print(os.path.isfile(path)) print(os.path.isdir(path)) print(os.path.basename(path)) print(os.path.dirname(path)) print(os.path.splitext(path))

Pathlib (recommended).

Python
from pathlib import Path
Python
p = Path("/home/user/documents") print(p.name) print(p.parent) print(p.suffix) print(p.exists()) print(p.is_file()) print(p.is_dir())
Python
new_path = p / "file.txt" print(new_path)

Sys.

Python
print(sys.argv) print(sys.path) print(sys.version) print(sys.platform)

Exit program; sys.exit(0) # And; sys.exit(1) # Error.

Stdin, stdout, stderr; sys.stdin.read(); sys.stdout.write("Hello\n"); sys.stderr.write("Error!\n").

37 datetime

Working with dates and times

Python
from datetime import datetime, date, time, timedelta, timezone import time as time_module

Current date and time.

Python
now = datetime.now() print(now)

Manual creation.

Python
d = date(2024, 1, 15) t = time(10, 30, 0) dt = datetime(2024, 1, 15, 10, 30, 0)

Formatting.

Python
print(now.strftime("%Y-%m-%d %H:%M:%S")) print(now.strftime("%A, %B %d, %Y"))

Parsing.

Python
parsed = datetime.strptime("2024-01-15", "%Y-%m-%d")

Timedelta.

Python
future = now + timedelta(days=7, hours=3) past = now - timedelta(weeks=1) diff = future - now print(diff.days)

Timezone.

Python
utc = datetime.now(timezone.utc) print(utc)

Timezone.

Python
from datetime import timedelta iran_tz = timezone(timedelta(hours=3, minutes=30)) tehran_time = datetime.now(iran_tz)

Zoneinfo (Python 3.9+).

Python
from zoneinfo import ZoneInfo tehran = datetime.now(ZoneInfo("Asia/Tehran"))

Timestamp.

Python
ts = now.timestamp() print(ts)

Timestamp.

Python
from_ts = datetime.fromtimestamp(ts)

Sleep; time_module.sleep(2) # 2 Seconds.

Performance counter.

Python
start = time_module.perf_counter() end = time_module.perf_counter() print(f"Elapsed: {end - start:.4f}s")

38 Regular Expressions (Regex)

Pattern matching with the re module

Python
import re

Main methods.

Python
text = "My email is test@example.com and phone is 0912-345-6789"

Search - First match.

Python
match = re.search(r"\w+@\w+\.\w+", text) if match: print(match.group()) print(match.start()) print(match.end()) print(match.span())

Match - Match at beginning of string.

Python
m = re.match(r"My", text) m = re.match(r"email", text)

Findall - All matches.

Python
emails = re.findall(r"\w+@\w+\.\w+", text)

Finditer - iterator of Match objects.

Python
for match in re.finditer(r"\d+", text): print(match.group())

Sub - Replacement.

Python
new_text = re.sub(r"\d", "*", text) new_text, count = re.subn(r"\d", "*", text)

Split - Split with regex.

Python
parts = re.split(r"\s+and\s+", text)

Groups.

Python
pattern = r"(\w+)@(\w+)\.(\w+)" match = re.search(pattern, text) print(match.group(0)) print(match.group(1)) print(match.group(2)) print(match.group(3))

Named groups.

Python
pattern = r"(?P<user>\w+)@(?P<domain>\w+)\.(?P<tld>\w+)" match = re.search(pattern, text) print(match.group("user")) print(match.groupdict())

Compile - for repeated use.

Python
email_pattern = re.compile(r"\w+@\w+\.\w+") matches = email_pattern.findall(text)

Flags.

Python
re.search(r"hello", "HELLO", re.IGNORECASE) re.search(r"^hello", "hello\nworld", re.MULTILINE) re.search(r"hello.world", "hello\nworld", re.DOTALL)

Regex Character Table

Pattern Description
.Any character (except newline)
\dDigit (0-9)
\DNon-digit
\wWord character (a-z, A-Z, 0-9, _)
\WNon-word
\sWhitespace
\SNon-whitespace
^Start of string
$End of string
*Zero or more
+One or more
?Zero or one
{n}Exactly n times
{n,m}Between n and m times
[]Character class
|OR
()Group
(?:)Non-capturing group
(?=)positive lookahead
(?!)negative lookahead

39 Collections

Specialized data structures

Python
from collections import ( Counter, defaultdict, OrderedDict, deque, namedtuple, ChainMap )

Counter.

Python
words = ["apple", "banana", "apple", "cherry", "banana", "apple"] count = Counter(words) print(count) print(count.most_common(2)) print(count["apple"]) print(count["orange"])

Defaultdict.

Python
d = defaultdict(list) d["fruits"].append("apple") d["fruits"].append("banana") print(dict(d))

Deque - double-ended queue.

Python
dq = deque([1, 2, 3]) dq.append(4) dq.appendleft(0) dq.pop() dq.popleft() dq.rotate(1) print(dq)

Namedtuple.

Python
Point = namedtuple("Point", ["x", "y"]) p = Point(3, 4) print(p.x, p.y) print(p._asdict())

ChainMap.

Python
defaults = {"theme": "light", "lang": "en"} user_prefs = {"theme": "dark"} combined = ChainMap(user_prefs, defaults) print(combined["theme"]) print(combined["lang"])

OrderedDict (Python 3.7+ dict is ordered).

Python
od = OrderedDict() od["a"] = 1 od["b"] = 2 od.move_to_end("a") print(list(od.keys()))

40 Itertools

Iterator tools

Python
import itertools

Count - infinite counting.

Python
for i in itertools.count(10, 2): if i > 20: break print(i)

Cycle - infinite cycling.

Python
counter = 0 for item in itertools.cycle(["A", "B", "C"]): if counter >= 6: break print(item, end=" ") counter += 1

Repeat.

Python
print(list(itertools.repeat("A", 3)))

Chain.

Python
print(list(itertools.chain([1, 2], [3, 4], [5, 6])))

Compress.

Python
selectors = [True, False, True] print(list(itertools.compress(["A", "B", "C"], selectors)))

Dropwhile / takewhile.

Python
data = [1, 2, 3, 4, 5] print(list(itertools.dropwhile(lambda x: x < 3, data))) print(list(itertools.takewhile(lambda x: x < 3, data)))

Groupby.

Python
data = ["apple", "apricot", "banana", "blueberry", "cherry"] for letter, group in itertools.groupby(data, key=lambda x: x[0]): print(f"{letter}: {list(group)}")

Permutations.

Python
print(list(itertools.permutations([1, 2, 3], 2)))

Combinations.

Python
print(list(itertools.combinations([1, 2, 3, 4], 2)))

Product - Cartesian product.

Python
print(list(itertools.product([1, 2], ["A", "B"])))

Accumulate.

Python
print(list(itertools.accumulate([1, 2, 3, 4, 5]))) print(list(itertools.accumulate([1, 2, 3, 4], lambda x, y: x * y)))

41 unittest

Unit testing with the unittest module

Python
import unittest

Function we are testing.

Python
def add(a, b): return a + b
Python
def divide(a, b): if b == 0: raise ValueError("Cannot divide by zero") return a / b

Test class.

Python
class TestMathOperations(unittest.TestCase): def setUp(self): self.numbers = [1, 2, 3, 4, 5] def tearDown(self): pass @classmethod def setUpClass(cls): print("Setting up test class...") @classmethod def tearDownClass(cls): print("Tearing down test class...") def test_add_positive_numbers(self): self.assertEqual(add(2, 3), 5) def test_add_negative_numbers(self): self.assertEqual(add(-2, -3), -5) def test_add_zero(self): self.assertEqual(add(0, 5), 5) def test_divide_by_zero(self): with self.assertRaises(ValueError): divide(10, 0) def test_list_contains(self): self.assertIn(3, self.numbers) self.assertNotIn(10, self.numbers) def test_is_instance(self): self.assertIsInstance("hello", str) self.assertTrue(5 > 3) self.assertFalse(3 > 5) def test_almost_equal(self): self.assertAlmostEqual(0.1 + 0.2, 0.3, places=7)

If __name__ == "__main__":; unittest.main().

Command line; python -m unittest test_module; python -m unittest test_module.TestClass; python -m unittest test_module.TestClass.test_method; python -m unittest discover -s tests -p "test_*.py".

assert methods

Method Check
assertEqual(a, b)a == b
assertNotEqual(a, b)a != b
assertTrue(x)bool(x) is True
assertFalse(x)bool(x) is False
assertIs(a, b)a is b
assertIsNone(x)x is None
assertIn(a, b)a in b
assertIsInstance(a, b)isinstance(a, b)
assertRaises(exc)exception
assertAlmostEqual(a, b)Approximately
assertGreater(a, b)a > b
assertLess(a, b)a < b
assertRegex(s, r)regex match

42 pytest

Modern Python testing framework

Pip install pytest.

Simple test - no class!

Python
def add(a, b): return a + b
Python
def test_add(): assert add(2, 3) == 5
Python
def test_add_negative(): assert add(-1, -1) == -2

Fixture.

Python
import pytest
Python
@pytest.fixture def sample_data(): return [1, 2, 3, 4, 5]
Python
def test_sum(sample_data): assert sum(sample_data) == 15

Fixture with scope.

Python
@pytest.fixture(scope="module") def database(): db = create_db() yield db db.cleanup()

Parametrize.

Python
@pytest.mark.parametrize("a,b,expected", [ (1, 2, 3), (0, 0, 0), (-1, 1, 0), (100, 200, 300) ]) def test_add_parametrized(a, b, expected): assert add(a, b) == expected

Skip.

Python
@pytest.mark.skip(reason="not implemented yet") def test_new_feature(): pass

Skipif.

Python
@pytest.mark.skipif(sys.platform == "win32", reason="Windows not supported") def test_unix_feature(): pass

Xfail.

Python
@pytest.mark.xfail(reason="known bug") def test_bug(): assert 1 / 0

Raises.

Python
def test_raises(): with pytest.raises(ZeroDivisionError): 1 / 0

Approx.

Python
def test_float(): assert 0.1 + 0.2 == pytest.approx(0.3)

Monkeypatch.

Python
def test_get_data(monkeypatch): def mock_get(url): return {"data": "mocked"} monkeypatch.setattr("requests.get", mock_get)

Capsys.

Python
def test_output(capsys): print("hello") captured = capsys.readouterr() assert captured.out == "hello\n"

Tmp_path.

Python
def test_file(tmp_path): file = tmp_path / "test.txt" file.write_text("hello") assert file.read_text() == "hello"
Running pytest:
  • pytest - Execution‌
  • pytest -v - verbose
  • pytest -k "test_name" - Filter by name
  • pytest -x - Stop on first error
  • pytest --tb=short - Short traceback
  • pytest -s - Show print statements
  • pytest --cov=module - coverage (requires pytest-cov)

43 Debugging Techniques

Python debugging tools and techniques

Pdb - Python Debugger.

Python
import pdb
Python
def buggy_function(x): y = x + 10 pdb.set_trace() z = y * 2 return z

Python 3.7+ breakpoint(); breakpoint() # Equivalent to pdb.set_trace().

Pdb commands:; n (next) - Next line; s (step) - Step into function; c (continue) - Continue; q (quit) - Exit; p variable - Print variable; l (list) - Show code; b line (break) - breakpoint; r (return) - Until return.

Logging.

Python
import logging
Python
logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__)
Python
logger.debug("Debug message") logger.info("Info message") logger.warning("Warning message") logger.error("Error message") logger.critical("Critical message")

Traceback.

Python
import traceback
Python
try: 1 / 0 except Exception: traceback.print_exc() tb = traceback.format_exc() print(tb)

Inspect.

Python
import inspect
Python
def my_function(a, b, c=10): pass
Python
print(inspect.signature(my_function)) print(inspect.getsource(my_function))

Timeit.

Python
import timeit
Python
print(timeit.timeit("sum(range(100))", number=10000)) print(timeit.repeat("sum(range(100))", repeat=3, number=10000))

CProfile.

Python
import cProfile import pstats
Python
def slow_function(): return sum(i * i for i in range(100000))
Python
profiler = cProfile.Profile() profiler.enable() slow_function() profiler.disable()
Python
stats = pstats.Stats(profiler) stats.sort_stats("cumulative") stats.print_stats(10)

44 Performance Tips

Optimizing Python code

1. Using built-ins; Bad.

Python
result = [] for i in range(1000): result.append(i * 2)

Good.

Python
result = [2 * i for i in range(1000)] result = list(map(lambda x: x * 2, range(1000)))

2. set/dict for search; Bad - O(n).

Python
if item in list(items): pass

Good - O(1).

Python
item_set = set(items) if item in item_set: pass

3. join instead of + for strings; Bad.

Python
result = "" for s in strings: result += s

Good.

Python
result = "".join(strings)

4. Generator for large data; Bad - or.

Python
result = [process(x) for x in huge_list]

Good -.

Python
result = (process(x) for x in huge_list)

5. Local variables are faster; Bad.

Python
def slow(): for i in range(1000000): math.sqrt(i)

Good.

Python
def fast(): sqrt = math.sqrt for i in range(1000000): sqrt(i)

6. __slots__ for memory reduction.

Python
class Point: __slots__ = ["x", "y"] def __init__(self, x, y): self.x = x self.y = y

7. functools.lru_cache.

Python
from functools import lru_cache
Python
@lru_cache(maxsize=128) def fibonacci(n): if n < 2: return n return fibonacci(n - 1) + fibonacci(n - 2)

8. multiprocessing for CPU-bound.

Python
from multiprocessing import Pool
Python
def square(x): return x * x
Python
with Pool() as pool: results = pool.map(square, range(1000))

9. threading for I/O-bound.

Python
from concurrent.futures import ThreadPoolExecutor
Python
def fetch_url(url): import requests return requests.get(url).status_code
Python
urls = ["https://example.com", "https://google.com"] with ThreadPoolExecutor(max_workers=5) as executor: results = list(executor.map(fetch_url, urls))

45 Profiling

Analyzing code performance

CProfile.

Python
import cProfile import pstats import io
Python
def heavy_computation(): total = 0 for i in range(100000): total += i ** 2 return total
Python
pr = cProfile.Profile() pr.enable() heavy_computation() pr.disable()
Python
s = io.StringIO() ps = pstats.Stats(pr, stream=s).sort_stats("cumulative") ps.print_stats(10) print(s.getvalue())

Line_profiler (pip install line_profiler); @profile; def my_function():; pass; kernprof -l -v script.py.

Memory_profiler (pip install memory_profiler); from memory_profiler import profile; @profile; def my_function():; pass; python -m memory_profiler script.py.

Timeit.

Python
import timeit

Single line.

Python
print(timeit.timeit("[x**2 for x in range(1000)]", number=100))

Multiple lines.

Python
setup = "import random; data = [random.random() for _ in range(1000)]" stmt = "sorted(data)" print(timeit.timeit(stmt, setup=setup, number=100))

Perf_counter.

Python
import time
Python
start = time.perf_counter() end = time.perf_counter() print(f"Elapsed: {end - start:.6f} seconds")

Dis - bytecode.

Python
import dis
Python
def example(): x = [1, 2, 3] return sum(x)
Python
dis.dis(example)

46 Memory Management

Understanding and optimizing memory usage

Sys.getsizeof.

Python
import sys
Python
print(sys.getsizeof(0)) print(sys.getsizeof("")) print(sys.getsizeof([])) print(sys.getsizeof({}))

Gc - garbage collector.

Python
import gc

Enable/disable; gc.disable(); gc.enable().

Force collection.

Python
gc.collect()

Collectable objects.

Python
print(gc.garbage)

Weakref - weak reference.

Python
import weakref
Python
class MyClass: pass
Python
obj = MyClass() ref = weakref.ref(obj) print(ref())
Python
del obj print(ref())

WeakKeyDictionary / WeakValueDictionary; For cache without preventing garbage collection.

__del__ and destructor.

Python
class Resource: def __init__(self): print("Resource acquired") def __del__(self): print("Resource released")

Context Manager better than __del__.

Python
class BetterResource: def __enter__(self): print("Resource acquired") return self def __exit__(self, *args): print("Resource released")

With BetterResource() as r:; pass.

Tracemalloc.

Python
import tracemalloc
Python
tracemalloc.start() current, peak = tracemalloc.get_traced_memory() print(f"Current: {current / 1024 / 1024:.2f} MB") print(f"Peak: {peak / 1024 / 1024:.2f} MB") tracemalloc.stop()