Introduction to the Python Cheat Sheet

If you’re looking for the most practical Python cheat sheet, you’ve come to the right place. Python is one of the world’s most popular programming languages — loved by beginners for its simplicity and trusted by professionals for its power in web development, data science, artificial intelligence, machine learning, and automation. This Python cheat sheet by Solviyo is your complete reference, covering everything from basic syntax and variables to advanced topics like object-oriented programming, decorators, generators, async, and modules. You can read it online or download the PDF for offline use.

Whether you are a student learning Python for the first time, a developer brushing up for a coding interview, or a data scientist needing a quick reference for daily work, this Python quick reference guide is structured to save you time. It includes ready-to-use examples, copyable code snippets, best practices, and performance notes — all organized into clear sections. Each topic is explained in plain language with practical tips so you can quickly learn Python, revise concepts, or debug faster.

Some of the most searched topics like Python functions, loops, conditionals, data types, string methods, list comprehensions, dictionaries, sets, and classes are covered with examples and tables. Advanced users will find dedicated sections on Python decorators, dataclasses, enums, pattern matching (PEP 634), virtual environments, and dependency management. We also include insights into when to use specific data structures and the subtle differences between class methods, static methods, and instance methods.

For developers preparing for interviews, this page doubles as a Python interview preparation cheat sheet, giving you all the essential Python syntax and tricks in one place. If you prefer offline reading, you can download the Python cheat sheet PDF version for free and keep it handy on your desktop or mobile device. Bookmark this guide now — it’s your ultimate Python quick reference.

Hello Python

Installing

Install Python from the OS package manager or python.org. Example commands:

# Install via apt (Linux)
sudo apt install python3

# macOS (Homebrew)
brew install python

# Windows (winget)
winget install Python.Python.3

# verify with
python3 --version

Running Scripts

Save code as hello.py and run it from the shell:

# hello.py
print("Hello from Solviyo!")

# Run:
python3 hello.py

REPL (Interactive Mode)

Quickly test lines of code in the REPL (use Ctrl+D to exit):

python3
>>> # type expressions and press Enter
>>> 2 + 3
5
>>> print("REPL test - Solviyo")
REPL test - Solviyo

Comments & Documentation

Inline Comments

Use # for single-line comments and short notes. Put explanatory comments where helpful.

# add two numbers
result = 5 + 3

Docstrings

Use triple-quoted strings for function/class/module documentation. Docstrings are accessible via .__doc__ or help().

def greet(name: str) -> str:
    """Return a greeting.

    Example:
        >>> greet("Solviyo")
        'Hello, Solviyo!'
    """
    return f"Hello, {name}"

Typing Annotations

Type hints clarify intent and help tooling (linters, autocomplete). They are not enforced at runtime by default.

def add(x: int, y: int) -> int:
    """Add two integers (used in Solviyo examples)."""
    return x + y

# Example
result: int = add(2, 3)
Note: Type hints improve readability and work with tools like mypy, IDEs, and language servers.

Variables & Data Types

Python variables don’t need explicit declaration — they’re created when you assign a value.

# Solviyo example variables
x = 42          # int
pi = 3.14159    # float
name = "Solviyo" # string
is_active = True # boolean
nothing = None   # special "no value"

Type Casting

Convert between types using built-in functions:

x = int("5")       # string → int
y = float(10)      # int → float
z = str(99)        # int → string
flag = bool(0)     # → False
check = bool(123)  # → True
Note: Use type() to check the data type: type(name).

Operators

Arithmetic Operators

a, b = 7, 3
print(a + b)  # 10 (addition)
print(a - b)  # 4  (subtraction)
print(a * b)  # 21 (multiplication)
print(a / b)  # 2.333... (division)
print(a // b) # 2  (floor division)
print(a % b)  # 1  (modulus)
print(a ** b) # 343 (exponentiation)

Comparison Operators

a, b = 5, 10
print(a == b)  # False
print(a != b)  # True
print(a > b)   # False
print(a < b)   # True
print(a >= 5)  # True
print(b <= 10) # True

Logical Operators

x, y = True, False
print(x and y) # False
print(x or y)  # True
print(not x)   # False

Bitwise Operators

Operate on the binary representation of integers.

a, b = 6, 3  # (110, 011 in binary)
print(a & b)  # 2  (AND)
print(a | b)  # 7  (OR)
print(a ^ b)  # 5  (XOR)
print(~a)     # -7 (NOT)
print(a << 1) # 12 (left shift)
print(a >> 1) # 3  (right shift)

Membership Operators

text = "Solviyo"
print("S" in text)   # True
print("z" not in text) # True

Identity Operators

Check if two variables point to the same object in memory.

x = [1, 2, 3]
y = x
z = [1, 2, 3]

print(x is y)      # True (same object)
print(x is z)      # False (same value, different object)
print(x is not z)  # True

Input & Output

Python provides simple but powerful ways to interact with users and display results.

Printing Output

# Basic printing
print("Hello Solviyo")

# Print multiple values (separated by space by default)
print("Pi =", 3.14159)

# Customize separator and end
print("A", "B", "C", sep="-", end="*")
# Output: A-B-C*

User Input

input() reads a line from standard input and always returns a string.

name = input("Enter your name: ")
print("Welcome,", name)

age = int(input("Enter your age: "))
print("Next year you'll be", age + 1)

Formatted Strings

MethodExampleOutput
f-string (recommended)f"Hello {name}"Hello Solviyo
str.format()"Pi is {:.2f}".format(3.14159)Pi is 3.14
Old style"%s is %d" % ("Age", 25)Age is 25
name = "Solviyo"
score = 95
print(f"{name} scored {score}/100")

File Redirection (Shell)

You can redirect program output to a file or read input from a file in the shell:

CommandDescription
python3 prog.py > out.txtRedirect program output to out.txt
python3 prog.py < in.txtUse in.txt as input for the program
python3 prog.py > out.txt 2>&1Redirect both output and errors to out.txt

Strings

Slicing

text = "Solviyo"
print(text[0])     # S (first character)
print(text[-1])    # o (last character)
print(text[0:4])   # Solv
print(text[:4])    # Solv
print(text[4:])    # iyo
print(text[::2])   # Slv (every 2nd char)

Common Methods

MethodExampleOutput
.lower()"Solviyo".lower()solviyo
.upper()"solviyo".upper()SOLVIYO
.strip()" hi ".strip()hi
.replace()"abc".replace("a","z")zbc
.split()"a,b,c".split(",")['a','b','c']
.join()"-".join(["a","b"])a-b

f-Strings

name = "Solviyo"
score = 99
print(f"{name} scored {score}/100")

pi = 3.14159
print(f"Pi rounded: {pi:.2f}")

Regex Basics

Python’s re module enables pattern matching.

import re

text = "Solviyo has 2 cats and 3 dogs"
nums = re.findall(r"\d+", text)  # find all numbers
print(nums)  # ['2', '3']

if re.search(r"cats", text):
    print("Found 'cats'!")

Lists

Creation & Slicing

items = [1, 2, 3, "Solviyo", True]
print(items[0])     # 1
print(items[-1])    # True
print(items[1:4])   # [2, 3, 'Solviyo']

Common Methods

MethodExampleEffect
.append()nums.append(4)Adds element at end
.extend()nums.extend([5,6])Adds multiple elements
.insert()nums.insert(1, 99)Insert at index
.remove()nums.remove(99)Remove first match
.pop()nums.pop()Remove & return last element
.sort()nums.sort()Sort in place
.reverse()nums.reverse()Reverse in place

List Comprehensions

# Squares from 0 to 9
squares = [x**2 for x in range(10)]
print(squares)

# Filter even numbers
evens = [x for x in range(10) if x % 2 == 0]
print(evens)

Tuples

Tuples are like lists, but immutable — once created, they cannot be changed. This makes them faster and safe for fixed collections.

Immutability

t = (1, 2, 3)
print(t[0])       # 1
# t[0] = 99       # ❌ Error: 'tuple' object does not support item assignment

Packing & Unpacking

# Packing
point = (10, 20)

# Unpacking
x, y = point
print(x, y)  # 10 20

# Extended unpacking
a, *b = (1, 2, 3, 4)
print(a)  # 1
print(b)  # [2, 3, 4]

Named Tuples

For better readability, use namedtuple (from collections).

from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)

print(p.x, p.y)      # 10 20
print(p[0], p[1])    # still works like a tuple

Sets

Sets store unique values. Order is not guaranteed, and duplicates are automatically removed.

Creation

numbers = {1, 2, 3, 3, 2}
print(numbers)  # {1, 2, 3}

empty = set()   # correct way to make empty set

Set Operations

OperationExampleResult
Union{1,2} | {2,3}{1,2,3}
Intersection{1,2} & {2,3}{2}
Difference{1,2} - {2,3}{1}
Symmetric Difference{1,2} ^ {2,3}{1,3}

Frozen Sets

frozenset is an immutable set — useful as dictionary keys or when you want fixed unique values.

fs = frozenset([1, 2, 2, 3])
print(fs)        # frozenset({1, 2, 3})
# fs.add(4)      # ❌ Error: can't modify frozenset

Dictionaries

Dictionaries store data as key–value pairs. Keys must be unique and immutable (like strings, numbers, tuples), while values can be anything.

Creation

# Literal
user = {"name": "Alice", "age": 25}

# Constructor
data = dict(x=10, y=20)

print(user["name"])  # Alice

Common Methods

MethodExampleResult
.keys()user.keys()dict_keys(['name','age'])
.values()user.values()dict_values(['Alice',25])
.items()user.items()dict_items([('name','Alice'),('age',25)])
.get()user.get("name")Alice
.update()user.update({"age": 26}){'name':'Alice','age':26}
.pop()user.pop("age")25 (removes key)

Dict Comprehensions

# Square numbers into dict
squares = {x: x**2 for x in range(5)}
print(squares)  # {0:0, 1:1, 2:4, 3:9, 4:16}

Nested Dictionaries

users = {
    "alice": {"age": 25, "role": "admin"},
    "bob": {"age": 30, "role": "editor"}
}

print(users["alice"]["role"])  # admin

Data Structure Comparisons

Python gives us multiple built-in containers. Each has its strengths — choosing the right one can make your code faster and cleaner.

StructureKey PropertiesPerformance NotesBest Use Cases
ListOrdered, mutable, allows duplicatesFast append & iteration, slower lookups (O(n))General sequences, dynamic collections
TupleOrdered, immutableLighter & faster than lists, hashable (usable as dict keys)Fixed data, function returns, safe read-only data
SetUnordered, unique valuesFast membership checks (O(1)), no duplicatesRemoving duplicates, fast lookups, math-like operations
DictKey–value mapping, keys uniqueFast key lookups & updates (O(1))Configurations, mappings, JSON-like data
👉 Rule of thumb: - Use lists when order matters. - Use tuples when data must not change. - Use sets for uniqueness or quick membership tests. - Use dictionaries for labeled, structured data.

Conditionals

Conditionals let your code make decisions. Python uses if, elif, and else blocks, indented consistently.

x = 10

if x > 0:
    print("Positive")
elif x == 0:
    print("Zero")
else:
    print("Negative")

Ternary Operator

For short decisions, Python has a one-liner form:

age = 20
status = "Adult" if age >= 18 else "Minor"
print(status)  # Adult
Tip: Don’t overuse ternary operators — they’re best when expressions are short and readable.

Loops

Loops let you repeat code. Python has two main loop types: for and while.

for loop

Iterates directly over a sequence (no need for indexes unless you want them).

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

while loop

Runs as long as a condition is True.

count = 3
while count > 0:
    print(count)
    count -= 1
# prints: 3, 2, 1

range()

The range() function is commonly used with for loops to generate numbers.

for i in range(2, 10, 2):  # start=2, stop=10, step=2
    print(i)
# Output: 2, 4, 6, 8
👉 Use for when looping over items, 👉 Use while when looping until a condition is met.

Loop Utilities

Python adds helpers that make looping cleaner and more expressive.

enumerate()

Gives both index and value when looping through a sequence.

names = ["Alice", "Bob", "Charlie"]

for idx, name in enumerate(names, start=1):
    print(idx, name)
# 1 Alice
# 2 Bob
# 3 Charlie

zip()

Combines multiple sequences element by element.

scores = [90, 85, 78]
for name, score in zip(names, scores):
    print(f"{name}: {score}")
# Alice: 90
# Bob: 85
# Charlie: 78

any() and all()

Check conditions across sequences.

nums = [2, 4, 6, 8]

print(any(n % 2 != 0 for n in nums))  # False
print(all(n % 2 == 0 for n in nums))  # True

Loop Control

Special keywords change how loops behave.

for i in range(5):
    if i == 2:
        continue   # skip iteration
    if i == 4:
        break      # exit loop
    print(i)
else:
    print("Loop finished without break")
KeywordMeaning
breakExit the loop immediately
continueSkip the rest of the current iteration
elseRuns only if loop wasn’t broken out of

Pattern Matching (PEP 634)

Python 3.10 introduced match/case for structural pattern matching, similar to switch statements in other languages but more powerful.

def handle_point(pt):
    match pt:
        case (0, 0):
            return "Origin"
        case (x, 0):
            return f"X-axis at {x}"
        case (0, y):
            return f"Y-axis at {y}"
        case (x, y):
            return f"Point ({x}, {y})"
        case _:
            return "Unknown"

print(handle_point((0, 0)))   # Origin
print(handle_point((5, 0)))   # X-axis at 5
👉 match/case works with numbers, strings, sequences, and even classes. 👉 Always include case _: as a fallback.

Defining Functions

Functions let you group reusable logic. Use def followed by a name, parameters, and an optional return statement.

def greet(name):
    return f"Hello, {name}!"

print(greet("Solviyo"))  # Hello, Solviyo!

Arguments

Python functions are flexible in how they accept arguments. Here’s a quick overview:

TypeExampleNotes
Positionalpower(2, 3)Order matters
Keywordpower(base=2, exp=3)Order doesn’t matter
Defaultdef f(x=10)Value used if no argument passed
*argsdef f(*nums)Collects extra positional args (tuple)
**kwargsdef f(**opts)Collects extra keyword args (dict)
def demo(*args, **kwargs):
    print("args:", args)
    print("kwargs:", kwargs)

demo(1, 2, 3, a=10, b=20)
# args: (1, 2, 3)
# kwargs: {'a': 10, 'b': 20}

Scope & Closures

Python resolves variable names using the LEGB rule: Local → Enclosing → Global → Built-in.

ScopeDescription
LocalNames inside the current function
EnclosingNames in outer (non-global) functions
GlobalNames at the module level
Built-inNames preloaded by Python (e.g. len)

Examples

x = "global"

def outer():
    msg = "enclosing"
    def inner():
        nonlocal msg
        print(x, msg)
    inner()

outer()  # global enclosing
👉 global lets you modify a module-level variable. 👉 nonlocal lets you modify a variable in an enclosing (but not global) scope. 👉 Closures happen when an inner function remembers variables from its enclosing scope.

Anonymous Functions → Lambdas

Use lambda for short, throwaway functions. Best for one-liners where a full def would be overkill.

square = lambda x: x**2
print(square(5))  # 25

words = ["solviyo", "python", "cheatsheet"]
print(sorted(words, key=lambda w: len(w)))
# ['python', 'solviyo', 'cheatsheet']
👉 Lambdas are limited to a single expression. Use def for complex logic.

Decorators

Decorators wrap one function with another, adding extra behavior.

DecoratorUsage
@staticmethodBind method to class, no self
@classmethodBind method to class, gets cls
@propertyDefine getter/setter-like methods
def logger(func):
    def wrapper(*args, **kwargs):
        print(f"[Solviyo Log] Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@logger
def greet(name):
    return f"Hello {name}"

print(greet("Python"))

Generators & Iterators

Generators produce items lazily using yield. Iterators expose __iter__() and __next__().

def countdown(n):
    while n > 0:
        yield n
        n -= 1

for num in countdown(3):
    print(num)
# 3 2 1
nums = [10, 20, 30]
it = iter(nums)

print(next(it))  # 10
print(next(it))  # 20
👉 Generators save memory — they yield one value at a time instead of building the whole list in memory.

Built-in Functional Tools

Python provides built-ins for applying functions across iterables.

FunctionUsage
map(func, iterable)Apply func to each item
filter(func, iterable)Keep items where func returns True
reduce(func, iterable)Accumulate to a single value (from functools)
zip(*iterables)Combine items element-wise
from functools import reduce

nums = [1, 2, 3, 4]
print(list(map(lambda x: x*2, nums)))     # [2, 4, 6, 8]
print(list(filter(lambda x: x%2==0, nums)))  # [2, 4]
print(reduce(lambda a,b: a+b, nums))      # 10
print(list(zip("abc", nums)))             # [('a',1),('b',2),('c',3)]

Imports

Python imports can be absolute, relative, or use aliases.

TypeExampleNotes
Absoluteimport mathMost common; full path
Relativefrom . import utilsWithin packages; uses dots
Aliasingimport numpy as npShorter reference name
Selectivefrom math import sqrtImport only what you need

Built-in Modules

Python comes batteries-included. Here are some must-know modules:

ModuleUse CaseExample
mathMathematical functionsmath.sqrt(16) → 4.0
randomRandom numbersrandom.choice([1,2,3])
datetimeDates & timesdatetime.date.today()
osFile system, env varsos.listdir(".")
sysPython runtime infosys.version
import math, random, datetime

print(math.factorial(5))         # 120
print(random.randint(1, 10))     # random int
print(datetime.date.today())     # current date

Creating Packages

A package is just a folder with an __init__.py file.

my_project/
│
├── app.py
├── utils/
│   ├── __init__.py
│   ├── math_tools.py
│   └── string_tools.py
# app.py
from utils import math_tools

print(math_tools.add(2, 3))

Virtual Environments

Keep dependencies isolated per project using venv.

python -m venv venv
source venv/bin/activate   # macOS/Linux
venv\Scripts\activate      # Windows
👉 When active, pip install installs into the venv, not globally.

Dependency Management

Two common ways to lock dependencies:

FilePurposeExample
requirements.txtPin exact versionsrequests==2.31.0
pyproject.tomlModern build metadata[tool.poetry.dependencies]
# Freeze dependencies
pip freeze > requirements.txt

# Install dependencies
pip install -r requirements.txt

Classes & Objects

In Python, everything is an object. Classes define blueprints for creating objects, bundling attributes (data) and methods (behavior).

Basic Syntax

class Dog:
    # class attribute
    species = "Canis familiaris"

    def __init__(self, name, age):
        # instance attributes
        self.name = name
        self.age = age

    def bark(self):
        return f"{self.name} says woof!"

# create objects
fido = Dog("Fido", 3)
print(fido.bark())  # Fido says woof!

Attributes & Methods

TypeDefinedExample
Class AttributeInside class, shared by all objectsspecies
Instance AttributeInside __init__, unique to each objectself.name, self.age
Instance MethodDefined with def, uses selfbark()

Adding & Accessing Attributes

# add a new attribute dynamically
fido.color = "brown"
print(fido.color)  # brown

# access class attribute
print(Dog.species)  # Canis familiaris
👉 Use self to access instance data. 👉 Objects can have attributes added at runtime. 👉 Class attributes are shared unless shadowed by an instance attribute.

Inheritance

Inheritance lets a class (child) reuse and extend behavior from another class (parent).

Single Inheritance

class Animal:
    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):
        return "Woof!"

dog = Dog()
print(dog.speak())  # Woof!

Multiple Inheritance

class Walker:
    def move(self):
        return "Walking"

class Swimmer:
    def move(self):
        return "Swimming"

class Amphibian(Walker, Swimmer):
    pass

frog = Amphibian()
print(frog.move())  # Walking (first base class wins)
👉 Python resolves method lookups using the MRO (Method Resolution Order). 👉 In Amphibian(Walker, Swimmer), Python searches in Walker → Swimmer → object.

Using super()

super() lets child classes call methods from their parent without naming it directly.

class Vehicle:
    def __init__(self, brand):
        self.brand = brand

class Car(Vehicle):
    def __init__(self, brand, model):
        super().__init__(brand)  # call parent __init__
        self.model = model

car = Car("Tesla", "Model S")
print(car.brand, car.model)  # Tesla Model S

Types of Inheritance

TypeDescriptionExample
SingleOne base class, one child classDog(Animal)
MultipleChild inherits from multiple parentsAmphibian(Walker, Swimmer)
MultilevelChild → Parent → Grandparent chainC → B → A
HierarchicalMultiple children from one parentDog(Animal), Cat(Animal)

Polymorphism

Polymorphism allows different classes to define methods with the same name, but different behavior. This makes code more flexible and extensible.

Method Overriding

class Animal:
    def speak(self):
        return "Some sound"

class Dog(Animal):
    def speak(self):  # overrides parent method
        return "Woof!"

class Cat(Animal):
    def speak(self):  # overrides parent method
        return "Meow!"

animals = [Dog(), Cat()]
for a in animals:
    print(a.speak())  
    # Woof!
    # Meow!

Built-in Example

Python’s built-in functions also show polymorphism. The same len() works on strings, lists, tuples, and more:

print(len("Solviyo"))    # 7 (string length)
print(len([1, 2, 3]))    # 3 (list length)
print(len((10, 20)))     # 2 (tuple length)

Key Points

ConceptDescriptionExample
OverridingChild class redefines a parent methodDog.speak()
Same InterfaceDifferent objects respond to the same methoda.speak() → Dog or Cat
Built-in PolymorphismFunctions like len(), iter()len("abc"), len([1,2,3])
👉 Polymorphism is not limited to class hierarchies — Python’s duck typing means “if it walks like a duck and quacks like a duck, it’s a duck.” 👉 As long as objects implement the required methods, they can be used interchangeably.

Encapsulation

Encapsulation restricts direct access to an object’s data. In Python, this is done by naming conventions rather than enforced rules.

Public, Protected, Private

class Account:
    def __init__(self, user, balance):
        self.user = user          # public
        self._balance = balance   # protected (convention)
        self.__pin = "1234"       # private (name mangling)

    def get_balance(self):
        return f"{self.user}'s balance: {self._balance}"

    def __get_pin(self):  # private method
        return self.__pin

acc = Account("SolviyoUser", 500)

print(acc.user)        # accessible
print(acc._balance)    # accessible but discouraged
# print(acc.__pin)     # AttributeError
print(acc._Account__pin)  # accessible via name mangling (not recommended)

Access Levels

LevelConventionAccessibility
PublicvariableFully accessible anywhere
Protected_variableAccessible, but meant for internal use only
Private__variableClass-internal use (name mangled)
👉 Python relies on developer discipline for encapsulation — unlike Java or C++. 👉 Use getters/setters only when needed (validation, computed properties). 👉 @property is Python’s idiomatic way to manage controlled access.

Using @property

class User:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):  # getter
        return self._name

    @name.setter
    def name(self, value):  # setter
        if not value:
            raise ValueError("Name cannot be empty")
        self._name = value

u = User("Solviyo")
print(u.name)   # Solviyo
u.name = "AI"   # valid update

Special Methods (Dunder Methods)

Special methods in Python start and end with __ (double underscores). They let you customize how objects behave with built-in functions and operators.

Example: Custom Class with Special Methods

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages

    def __str__(self):   # human-readable
        return f"{self.title} by {self.author}"

    def __repr__(self):  # developer-friendly
        return f"Book({self.title!r}, {self.author!r}, {self.pages})"

    def __len__(self):   # works with len()
        return self.pages

    def __eq__(self, other):  # ==
        return self.title == other.title

b1 = Book("Python Tricks", "Solviyo", 250)
b2 = Book("Python Tricks", "Solviyo", 250)

print(str(b1))    # Python Tricks by Solviyo
print(repr(b1))   # Book('Python Tricks', 'Solviyo', 250)
print(len(b1))    # 250
print(b1 == b2)   # True

Common Special Methods

MethodPurposeExample
__init__Constructor, initialize attributesBook("Title", "Author", 100)
__str__User-friendly stringprint(obj)
__repr__Developer string (debugging)obj in REPL
__len__Called by len()len(obj)
__eq__Equality checkobj1 == obj2
__add__Overload + operatorobj1 + obj2
__iter__, __next__Make class iterablefor x in obj
__enter__, __exit__Context managerswith obj:
👉 __str__ is for end users, __repr__ is for developers. 👉 If you only define __repr__, it’s often used as fallback for __str__. 👉 Special methods let your classes feel “native” in Python.

Class vs Static Methods

Besides normal instance methods, Python supports class methods and static methods. These are defined using decorators and control how methods access data.

Example

class MathUtils:
    pi = 3.14159

    def area_of_circle(self, r):  # instance method
        return self.pi * r * r

    @classmethod
    def get_pi(cls):  # class method
        return cls.pi

    @staticmethod
    def add(x, y):  # static method
        return x + y

m = MathUtils()

# Instance method (needs object)
print(m.area_of_circle(5))  # 78.53975

# Class method (works via class or object)
print(MathUtils.get_pi())   # 3.14159

# Static method (no access to class/instance data)
print(MathUtils.add(3, 4))  # 7

Comparison

Method TypeDecoratorFirst ArgAccessUse Case
InstanceNoneselfInstance attributes & class attributesObject-specific behavior
Class@classmethodclsClass attributes (shared across instances)Factory methods, alternative constructors
Static@staticmethodNoneNo direct accessUtility functions logically tied to class
👉 @classmethod is great for alternative constructors (e.g., Date.from_string("2025-09-28")). 👉 @staticmethod is just a namespaced function inside the class. 👉 Regular instance methods remain the most common.

Dataclasses & Enums

Python provides dataclasses (for simpler class boilerplate) and enums (for named constants). These improve readability and reduce manual code.

Dataclasses

from dataclasses import dataclass

@dataclass
class Book:
    title: str
    author: str
    pages: int = 0

b1 = Book("Python 101", "Solviyo", 250)
print(b1)  # Book(title='Python 101', author='Solviyo', pages=250)

Frozen Dataclasses

Frozen dataclasses make instances immutable:

@dataclass(frozen=True)
class Config:
    api_key: str

cfg = Config("XYZ-123")
# cfg.api_key = "ABC"  # ❌ Error: cannot assign to field

Dataclass Benefits

FeatureNormal ClassDataclass
Auto __init__ManualGenerated automatically
Auto __repr__ManualGenerated automatically
ImmutabilityManual @propertyfrozen=True
👉 Use dataclasses when you need lightweight data containers. 👉 Frozen dataclasses are useful for config objects, keys, and constants.

Enums

from enum import Enum, auto

class Status(Enum):
    PENDING = auto()
    ACTIVE = auto()
    INACTIVE = auto()

print(Status.ACTIVE)       # Status.ACTIVE
print(Status.ACTIVE.name)  # ACTIVE
print(Status.ACTIVE.value) # 2

Enum Use Cases

ScenarioWhy Enums Help
Status FlagsAvoids using raw strings ("active", "inactive")
ConstantsGroups related constants in one class
ReadabilitySelf-documenting & safer than magic numbers
👉 Enums are iterable, so you can loop over members with for status in Status. 👉 Use auto() for automatic numbering. 👉 Great for states, categories, or configuration flags.

Comprehensions & Context Managers

Comprehensions provide a compact way to build collections, while context managers simplify resource handling. Both improve readability and reduce boilerplate.

List, Dict, Set, and Nested Comprehensions

# List comprehension
squares = [x**2 for x in range(6)]
# [0, 1, 4, 9, 16, 25]
# Dict comprehension
square_dict = {x: x**2 for x in range(6)}
# {0:0, 1:1, 2:4, 3:9, 4:16, 5:25}
# Set comprehension
unique_lengths = {len(word) for word in ["solviyo", "python", "ai", "python"]}
# {2, 6, 7}
# Nested comprehension (matrix)
matrix = [[i*j for j in range(3)] for i in range(3)]
# [[0, 0, 0], [0, 1, 2], [0, 2, 4]]

When to Use Comprehensions

CaseUse LoopUse Comprehension
Complex logic✔️ Clearer with if/else blocks❌ Can reduce readability
Simple transformation❌ Verbose✔️ Concise & faster
Readability✔️ For beginners✔️ For short, clean expressions
👉 Prefer comprehensions for simple, one-line transformations. 👉 Avoid nesting too deeply — readability matters! 👉 Great for filtering, mapping, and lightweight data reshaping.

Context Managers

# Built-in context manager
with open("solviyo.txt", "w") as f:
    f.write("Python Cheat Sheets are awesome!")
# Custom context manager
class SolviyoLogger:
    def __enter__(self):
        print("Start logging...")
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Stop logging...")

with SolviyoLogger():
    print("Inside the block")
👉 with ensures cleanup automatically (like closing files). 👉 Use custom context managers for logging, locks, or resources. 👉 Reduces chances of resource leaks and errors.

Advanced Python Modules

Python’s standard library provides powerful built-in modules for data processing and performance. Here we explore itertools, functools, and collections with practical examples.

Itertools Module

itertools helps with efficient looping and combinatorial problems.

from itertools import combinations, permutations, product

# Combinations (order doesn't matter)
print(list(combinations([1,2,3], 2)))
# [(1, 2), (1, 3), (2, 3)]

# Permutations (order matters)
print(list(permutations([1,2,3], 2)))
# [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

# Cartesian product
print(list(product([1,2], ['a','b'])))
# [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
👉 Use combinations for subsets, permutations when order matters, and product for multi-set pairing. 👉 Extremely useful in algorithms, games, and test case generation.

Functools Module

functools provides tools for higher-order functions and performance optimization.

from functools import lru_cache, partial, reduce

# lru_cache for memoization
@lru_cache(maxsize=100)
def fib(n):
    if n < 2: return n
    return fib(n-1) + fib(n-2)

print(fib(30))  # Cached calls improve performance

# partial: pre-filling arguments
def power(base, exp):
    return base ** exp

square = partial(power, exp=2)
print(square(5))  # 25

# reduce: cumulative function
nums = [1, 2, 3, 4]
total = reduce(lambda x, y: x + y, nums)
print(total)  # 10
👉 lru_cache improves recursive performance. 👉 partial helps create specialized versions of functions. 👉 reduce applies a function cumulatively (like sum/product).

Collections Module

collections offers specialized containers beyond dicts and lists.

from collections import Counter, defaultdict, deque, OrderedDict

# Counter
cnt = Counter("solviyo loves python")
print(cnt.most_common(3))  # [('o', 3), (' ', 2), ('s', 2)]

# defaultdict
dd = defaultdict(int)
dd['missing'] += 1
print(dd)  # defaultdict(, {'missing': 1})

# deque (fast appends & pops from both ends)
dq = deque([1,2,3])
dq.appendleft(0)
print(dq)  # deque([0,1,2,3])

# OrderedDict (preserves insertion order, Python 3.6+ dict does too)
od = OrderedDict()
od['a'] = 1
od['b'] = 2
print(list(od.keys()))  # ['a','b']
ClassUse Case
CounterCounting frequencies (e.g., words, items)
defaultdictAvoids KeyError, auto-creates default values
dequeFast queue/stack operations on both ends
OrderedDictPreserve insertion order (historically before dict did)
👉 Use collections when default Python containers feel limited. 👉 Counter is excellent for quick statistics. 👉 deque outperforms lists for frequent appends/pops from both ends.

Typing, Async & Metaprogramming

Modern Python supports type hints for clarity, async/await for concurrency, and metaprogramming for dynamic code. These advanced tools help make code more reliable, scalable, and flexible.

Typing & Type Hints

Type hints improve readability, catch bugs earlier (via tools like mypy), and enable better IDE support.

from typing import List, Union, Optional

def greet(name: str, age: Optional[int] = None) -> str:
    if age:
        return f"Hello {name}, you are {age} years old."
    return f"Hello {name}!"

def add(values: List[int]) -> int:
    return sum(values)

def combine(x: Union[int, str], y: Union[int, str]) -> str:
    return str(x) + str(y)
👉 Union = multiple possible types. 👉 Optional[X] = either X or None. 👉 List[int] = generics notation.

Async & Await

Python uses async and await for concurrent programming with an event loop. Ideal for I/O-bound tasks like web requests, DB queries, or file operations.

import asyncio

async def fetch_data():
    print("Fetching data...")
    await asyncio.sleep(2)
    return {"source": "Solviyo", "data": [1,2,3]}

async def main():
    result = await fetch_data()
    print(result)

asyncio.run(main())
ConceptDescription
async defDefines a coroutine function
awaitPauses until coroutine/task is complete
asyncio.run()Runs an event loop until finished
👉 Best for network calls, APIs, and parallel I/O. 👉 Avoid for CPU-heavy tasks (use multiprocessing instead).

Metaprogramming

Metaprogramming lets Python code generate or modify code dynamically. Use with caution for advanced use cases.

# type(): create classes dynamically
MyClass = type("MyClass", (), {"x": 42})
obj = MyClass()
print(obj.x)  # 42

# Metaclasses: control class creation
class Meta(type):
    def __new__(cls, name, bases, attrs):
        attrs["tag"] = "CreatedBySolviyo"
        return super().__new__(cls, name, bases, attrs)

class Demo(metaclass=Meta):
    pass

print(Demo.tag)  # CreatedBySolviyo

# eval / exec: run code strings (use cautiously!)
code = "print('Hello from exec at Solviyo!')"
exec(code)
👉 type() can build classes on the fly. 👉 Metaclasses are advanced — great for frameworks & ORMs. 👉 eval/exec are powerful but risky — avoid with untrusted input.

Files & Persistence

Python provides powerful tools for working with files and structured data formats like JSON and CSV. Proper handling ensures reliability and prevents resource leaks.

File Handling

Use the built-in open() function for reading and writing files. Always prefer context managers (with) for automatic closing.

# Writing to a file
with open("solviyo_notes.txt", "w") as f:
    f.write("Learning Python with Solviyo!")

# Reading from a file
with open("solviyo_notes.txt", "r") as f:
    content = f.read()
    print(content)

JSON Handling

JSON (JavaScript Object Notation) is widely used for data exchange. Python’s json module makes serialization and deserialization simple.

import json

# Writing JSON
data = {"site": "Solviyo", "language": "Python"}
with open("data.json", "w") as f:
    json.dump(data, f)

# Reading JSON
with open("data.json", "r") as f:
    loaded = json.load(f)
    print(loaded)

CSV Handling

CSV (Comma-Separated Values) is common for tabular data. Use the csv module for reading and writing.

import csv

# Writing CSV
rows = [["Name", "Score"], ["Alice", 90], ["Bob", 85]]
with open("scores.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

# Reading CSV
with open("scores.csv", "r") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

When to Use

FormatUse Case
Plain TextSimple notes, logs, or unstructured data
JSONAPIs, configs, structured but lightweight data
CSVTabular data, spreadsheets, interoperability
👉 Always use context managers (with) to prevent memory leaks. 👉 For large JSON/CSV files, consider streaming or chunked reading. 👉 Ensure file encoding (UTF-8 recommended) for cross-platform compatibility.

Error Handling & Debugging

Python uses exceptions to signal errors. Understanding how to handle and raise exceptions properly makes your programs more reliable and easier to debug.

Try / Except / Else / Finally

Wrap risky code in try. Use except for handling, else for success cases, and finally for cleanup.

try:
    num = int("10a")
except ValueError:
    print("Invalid number!")
else:
    print("Conversion successful")
finally:
    print("Execution finished")

Common Exceptions

Python raises built-in exceptions for common errors. Some useful ones include:

ExceptionWhen it Occurs
ValueErrorWrong value (e.g., int("abc"))
TypeErrorInvalid operation on data types ("2" + 2)
KeyErrorAccessing missing dict keys
IndexErrorIndex out of range in a list
ZeroDivisionErrorDividing by zero

Raising Exceptions

Use raise to signal errors intentionally. You can also create custom exceptions by subclassing Exception.

# Raising a built-in exception
def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("Division by zero is not allowed")
    return a / b

# Custom exception
class SolviyoError(Exception):
    pass

def check_value(x):
    if x < 0:
        raise SolviyoError("Negative values not supported")

check_value(-5)
👉 Use specific exceptions (ValueError, KeyError) instead of a bare except. 👉 Add descriptive messages when raising errors. 👉 Keep custom exceptions meaningful and project-specific.

Practice Python After Reading

Now that you’ve explored the Python Cheat Sheet, test your knowledge and sharpen your skills: