Complete 2025 Best Python Cheat Sheet

Python is one of the most popular and beginner-friendly programming languages in the world. Whether you're building websites, analyzing data, automating tasks, or diving into machine learning, Python is everywhere — and for good reason. Its clean syntax and vast ecosystem make it a go-to choice for developers of all levels.

But with so many functions, libraries, and syntax rules, it’s not always easy to remember everything. That’s where a Python Cheat Sheet comes in handy. It's a compact, easy-to-scan reference guide designed to help you code faster, avoid repetitive Googling, and boost your overall productivity.

let's start

Python Basics

Variables and Data Types

In Python, variables are used to store data. You don’t need to declare the type explicitly — Python automatically determines the data type at runtime. This is known as dynamic typing. Understanding how variables and data types work is the first step to writing effective Python code.

Python supports several core data types, including:

  • Integers for whole numbers
  • Floats for decimal numbers
  • Strings for text
  • Booleans for logical values (True/False)

You can also convert between these types when needed, and check the type of any variable using built-in functions.

Here’s a quick overview of variable assignment, type conversion, and type checking in Python:

Variable Assignment

Python Variables
x=10# Integer
name="Alice"# String
price=19.99# Float
is_valid=True# Boolean

Common Data Types

  • int → Whole numbers like 5, -3, 100
  • float → Decimal numbers like 3.14, 0.5, -1.0
  • str → Strings of text like "hello" or 'world'
  • bool → Boolean values: True or False

Type Conversion

You can convert between types using built-in functions:

Python Type Conversion
str(100)# Converts integer to string: '100'
int("42")# Converts string to integer: 42
float("3.14")# Converts string to float: 3.14
bool(0)# Converts 0 to False

Type Checking

Use the type() function to check a variable’s type:

Python type() Function
type(42) # Output: <class 'int'>
type("Python") # Output: <class 'str'>
type(3.14) # Output: <class 'float'>
type(True) # Output: <class 'bool'>

Operators

Operators in Python are special symbols or keywords used to perform operations on variables and values. Understanding operators is crucial for writing logical and efficient code. Python supports several types of operators, each serving a specific purpose — from math operations to comparisons and logical checks.

Below is a breakdown of the most commonly used operator types in Python:

Arithmetic Operators

Used to perform basic mathematical operations:

Python Arithmetic Operators
a + b # Addition
a - b # Subtraction
a * b # Multiplication
a / b # Division (float)
a // b # Floor division (integer)
a % b # Modulus (remainder)
a ** b # Exponentiation (power)

Comparison Operators

Used to compare two values and return a boolean (True or False):

Comparison Operators
a == b# Equal to
a != b# Not equal to
a < b# Less than
a > b# Greater than
a <= b# Less than or equal to
a >= b# Greater than or equal to

Logical Operators

Used to combine multiple conditions:

Python Logical Operators
a and b # Returns True if both a and b are True
a or b # Returns True if either a or b is True
not a # Returns True if a is False

Assignment Operators

Used to assign and update the value of a variable:

Python Assignment Operators
x = 10 # Assign
x += 5 # Add and assign (x = x + 5)
x -= 3 # Subtract and assign
x *= 2 # Multiply and assign
x /= 4 # Divide and assign

Membership Operators

Used to check if a value exists in a sequence (like list, string, etc.):

Python Membership Operators
"value" in list # True if value exists
"value" not in list # True if value does not exist

Identity Operators

Used to check if two variables refer to the same object in memory:

Python Identity Operators
a is b # True if a and b refer to the same object
a is not b # True if a and b do not refer to the same object

Comments

Comments are lines in your code that are ignored by the Python interpreter. They’re useful for explaining your logic, making notes, or temporarily disabling parts of code. Well-written comments improve code readability and maintainability.

Python supports two main types of comments:

Single-line Comments

Use the # symbol to add a comment on a single line. Everything after the # is ignored by Python.

Python Comments
# This is a single-line comment
x = 5 # This is also a comment

Multi-line Comments

There is no official multi-line comment syntax in Python, but you can simulate it using triple quotes (''' or """). These are technically multi-line strings, but if they’re not assigned to a variable, they’re ignored — effectively acting as comments.

Python Multi-line Comments
"""
This is a multi-line comment.
It spans multiple lines.
Useful for large explanations or documentation.
"""

String Operations

String Basics

Strings are one of the most commonly used data types in Python. They are sequences of characters enclosed in either single quotes (' ') or double quotes (" "). Python also supports multi-line strings using triple quotes.

Understanding how to create, access, and manipulate strings is essential for text processing and data handling.

Creating Strings

Python Strings
s1 = 'Hello'
s2 = "World"
s3 = """This is
a multi-line
string"""

String Indexing and Slicing

Strings are zero-indexed, meaning the first character has index 0. You can access individual characters or extract parts of the string using slicing.

String Indexing & Slicing
text = "Python"
# Indexing
text[0] # 'P'
text[-1] # 'n' (last character)
# Slicing
text[1:4] # 'yth' (from index 1 to 3)
text[:3] # 'Pyt' (from start to index 2)
text[3:] # 'hon' (from index 3 to end)
text[:] # 'Python' (entire string)

String Concatenation

You can combine (concatenate) strings using the + operator, and repeat them using the * operator.

String Concatenation & Repetition
greeting = "Hello" + " " + "World" # 'Hello World'
laugh = "ha" * 3 # 'hahaha'

String Methods

Python provides many built-in methods to work with strings efficiently. These methods allow you to manipulate, format, and analyze string data with ease. Below is a quick reference to the most commonly used string methods:

Case Conversion Methods

String Methods
text = "hello world"
text.upper() # 'HELLO WORLD'
text.lower() # 'hello world'
text.title() # 'Hello World'
text.capitalize() # 'Hello world'

Whitespace Removal Methods

String Whitespace Methods
data = " Hello "
data.strip() # 'Hello' → removes both sides
data.lstrip() # 'Hello ' → removes leading spaces
data.rstrip() # ' Hello' → removes trailing spaces

Splitting and Joining

Split & Join Strings
sentence = "Python is fun"
# Split into list
sentence.split() # ['Python', 'is', 'fun']
# Join list into string
words = ['Join', 'these', 'words']
" ".join(words) # 'Join these words'

Replace, Find, and Count

Replace, Find & Count
text = "banana"
text.replace("a", "o") # 'bonono' → replaces all 'a' with 'o'
text.find("n") # 2 → index of first 'n'
text.count("a") # 3 → total occurrences of 'a'

Start/End Checks

Startswith & Endswith
filename = "report.pdf"
filename.startswith("rep") # True
filename.endswith(".pdf") # True

Character Checks

These methods return True or False based on string content:

String Validation Methods
"123".isdigit() # True
"abc".isalpha() # True
"abc123".isalnum() # True (only letters and numbers)
"abc!".isalnum() # False (contains special character)

String Formatting

String formatting allows you to insert variables or values into strings in a readable and structured way. Python offers several methods for formatting strings — from modern f-strings to older techniques like .format() and % formatting.

f-Strings (Python 3.6+)

The most modern and preferred way to format strings. Use the f prefix and insert variables inside {}.

f-Strings (Formatted Strings)
name = "Alice"
age = 25
f"Hello, {name}. You are {age} years old." # Output: 'Hello, Alice. You are 25 years old.'

You can also use expressions inside {}:

f-Strings with Expressions
f"{2 + 3}" # '5'
f"{name.upper()}" # 'ALICE'

.format() Method

Useful for inserting multiple values using placeholders {}:

String Formatting with .format()
"Hello, {}. You are {}.".format("Bob", 30)
# Output: 'Hello, Bob. You are 30.'
# Positional or named arguments
"{0} scored {1}".format("Alice", 95)
"{name} is {age} years old.".format(name="Tom", age=22)

% Formatting (Old Style)

An older formatting style, similar to C-style strings:

% String Formatting
"Name: %s, Age: %d" % ("John", 28)
# Output: 'Name: John, Age: 28'

Common format specifiers:

  • %s – string
  • %d – integer
  • %f – float

You can also control decimal places:

Float Formatting with %f
"Pi is approximately %.2f" % 3.14159
# Output: 'Pi is approximately 3.14'

Multi-line Strings

Triple quotes allow you to write strings across multiple lines:

Multiline String ("""...""")
msg = """Dear User,
Thank you for using our service.
Regards,
Team
"""

These are also commonly used for documentation strings (docstrings) in functions and classes.

Data Structures

Lists

Lists are ordered, mutable (changeable) collections in Python. They can hold items of any data type and are commonly used to store sequences of elements like numbers, strings, or even other lists.

Creating Lists

You can create a list using square brackets [] or the list() constructor:

Creating Lists
fruits = ["apple", "banana", "cherry"]
numbers = list(range(5)) # [0, 1, 2, 3, 4]
mixed = [1, "two", 3.0, True]

List Indexing and Slicing

Lists are zero-indexed. Use indexing to access individual elements and slicing to access sublists.

List Indexing & Slicing
fruits = ["apple", "banana", "cherry", "date"]
fruits[0] # 'apple'
fruits[-1] # 'date'
fruits[1:3] # ['banana', 'cherry']
fruits[:2] # ['apple', 'banana']
fruits[2:] # ['cherry', 'date']
fruits[:] # Full copy of the list

Common List Methods

List Methods
lst = [1, 2, 3]
lst.append(4) # [1, 2, 3, 4]
lst.insert(1, 10) # [1, 10, 2, 3, 4]
lst.remove(2) # [1, 10, 3, 4] → removes first occurrence of 2
lst.pop() # [1, 10, 3] → removes and returns last element
lst.index(10) # 1 → returns index of first matching element
lst.count(3) # 1 → number of times 3 appears

List Comprehensions

A concise way to create new lists by applying an expression to each item in an iterable.

List Comprehension
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
evens = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]

Nested Lists

Lists can contain other lists (2D or multi-dimensional structures).

2D List (Matrix) Access
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
matrix[1][2] # 6 → row 1, column 2

Tuples

Tuples are ordered, immutable sequences in Python. Unlike lists, you cannot modify (add/remove/change) the elements of a tuple once it's created. Tuples are useful for fixed data collections, safer data handling, and as dictionary keys.

Creating Tuples

You can define tuples with parentheses () or without (comma is what defines a tuple):

Tuple Creation
t1 = (1, 2, 3)
t2 = "a", "b", "c" # Tuple without parentheses
single = (5,) # Single-element tuple (note the comma)
empty = tuple() # Empty tuple

Tuple Unpacking

You can extract values from a tuple directly into variables:

Tuple Unpacking
point = (10, 20)
x, y = point
# x = 10, y = 20
a, b, c = (1, 2, 3)

You can also use the * operator for extended unpacking:

Extended Tuple Unpacking
a, *b = (1, 2, 3, 4)
# a = 1, b = [2, 3, 4]

Tuple Methods

Tuples have fewer methods than lists due to immutability:

Tuple Methods
t = (1, 2, 2, 3)
t.count(2) # 2 → counts how many times 2 appears
t.index(3) # 3 → returns index of first occurrence of 3

Named Tuples

For readable and self-documenting tuples, use namedtuple from the collections module:

namedtuple Example
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)
p.x # 10
p.y # 20

Named tuples behave like regular tuples but allow access to elements by name.

Dictionaries

Dictionaries are unordered, mutable collections in Python used to store data in key-value pairs. They are one of the most powerful and flexible data structures in Python.

Creating Dictionaries

Dictionary Creation
person = {
"name": "Alice",
"age": 30,
"city": "New York"
}
empty_dict = {} # Empty dictionary
alt = dict(name="Bob", age=25)

Keys must be immutable (like strings, numbers, or tuples), and values can be any type.

Accessing Values

Accessing Dictionary Values
person["name"] # 'Alice'
person.get("age") # 30
person.get("email") # Returns None (no error if key doesn't exist)

Dictionary Methods

Dictionary Methods
data = {"a": 1, "b": 2, "c": 3}
data.keys() # dict_keys(['a', 'b', 'c'])
data.values() # dict_values([1, 2, 3])
data.items() # dict_items([('a', 1), ('b', 2), ('c', 3)])
data.get("a") # 1
data.update({"d": 4}) # Adds key 'd' with value 4
data.pop("b") # Removes key 'b' and returns its value

Dictionary Comprehensions

Quickly create or transform dictionaries:

Dictionary Comprehension
squares = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Filtering
evens = {k: v for k, v in squares.items() if v % 2 == 0}

Nested Dictionaries

Dictionaries can contain other dictionaries, useful for structured data:

Nested Dictionary Access
students = {
"alice": {"age": 20, "grade": "A"},
"bob": {"age": 22, "grade": "B"}
}
students["alice"]["grade"] # 'A'

Sets

Sets are unordered collections of unique elements. They are useful when you need to store non-duplicate items, perform mathematical set operations, or check for membership efficiently.

Creating Sets

Set Creation & Uniqueness
s = {1, 2, 3}
empty_set = set() # Note: {} creates an empty dictionary
# Duplicates are automatically removed
nums = {1, 2, 2, 3} # {1, 2, 3}

Sets can contain any immutable types (e.g., numbers, strings, tuples).

Set Operations

Python sets support mathematical operations:

Set Operations
a = {1, 2, 3}
b = {3, 4, 5}
a | b # Union: {1, 2, 3, 4, 5}
a & b # Intersection: {3}
a - b # Difference: {1, 2}
a ^ b # Symmetric Difference: {1, 2, 4, 5}

Set Methods

Set Methods
s = {1, 2, 3}
s.add(4) # {1, 2, 3, 4}
s.remove(2) # Removes 2; raises error if not found
s.discard(5) # Removes 5 if present; no error if missing
s.update([5, 6]) # Adds multiple elements: {1, 3, 4, 5, 6}

Set Comprehensions

Like list/dict comprehensions, but for sets:

Set Comprehension
squares = {x**2 for x in range(5)}
# {0, 1, 4, 9, 16}
# With condition
evens = {x for x in range(10) if x % 2 == 0}

Control Flow

Conditional Statements

Control flow in Python allows you to execute code based on certain conditions. Conditional statements help your program make decisions and follow different paths depending on the data.

if, elif, else

The most basic conditional structure:

if-elif-else Statement
x = 10
if x > 0:
print("Positive")
elif x == 0:
print("Zero")
else:
print("Negative")
  • You can have multiple elif blocks but only one if and one else.
  • Blocks are defined by indentation, not curly braces.

Nested Conditions

You can place one condition inside another:

Nested if Statement
x = 5
if x > 0:
if x < 10:
print("Positive and less than 10")

Use nested conditions carefully to avoid deeply indented code (which can be harder to read).

Ternary Operator (Inline if)

For simple one-line conditions:

Ternary Operator
x = 5
result = "Even" if x % 2 == 0 else "Odd"

It’s equivalent to:

if-else Statement
if x % 2 == 0:
result = "Even"
else:
result = "Odd"

Match-Case (Python 3.10+)

A more readable alternative to long if-elif chains, similar to switch in other languages:

match-case Statement
status = 404
match status:
case 200:
print("OK")
case 404:
print("Not Found")
case 500:
print("Server Error")
case _:
print("Unknown status")
  • _ acts as the default case.
  • Match-case is pattern matching, not just value comparison.

Loops

Loops in Python are used to execute a block of code multiple times. Python provides two main types of loops: for and while. You can control the loop flow using keywords like break, continue, and even use an else block with a loop.

for Loops

Used to iterate over a sequence (list, string, tuple, etc.):

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

You can loop over strings:

for Loop (String Iteration)
for char in "Python":
print(char)

while Loops

Repeatedly runs as long as the condition is True:

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

range() Function

Generates a sequence of numbers, commonly used with for loops:

for Loop with range()
for i in range(5): # 0 to 4
print(i)
for i in range(1, 6): # 1 to 5
print(i)
for i in range(0, 10, 2): # 0, 2, 4, 6, 8
print(i)

break and continue

Control the flow inside loops:

break and continue
# break – exits the loop
for i in range(5):
if i == 3:
break
print(i) # Output: 0 1 2
# continue – skips to next iteration
for i in range(5):
if i == 3:
continue
print(i) # Output: 0 1 2 4

Loop with else

The else block runs only if the loop completes normally (no break):

for...else Statement
for i in range(3):
print(i)
else:
print("Loop finished without break")

If a break is encountered, the else part is skipped.

Nested Loops

You can place one loop inside another to work with multi-dimensional data:

Nested for Loops
for i in range(2):
for j in range(3):
print(f"{i}, {j}")

Loop Control

Python provides powerful built-in functions like enumerate() and zip() to simplify and optimize how you loop through data. You can also iterate directly over dictionary keys and values in an intuitive way.

enumerate()

Use enumerate() when you need both the index and the value during iteration.

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

You can also set a custom starting index:

enumerate(start=1)
fruits = ["apple", "banana", "cherry"]
for i, item in enumerate(fruits, start=1):
print(i, item)

zip()

Use zip() to iterate over two (or more) sequences in parallel.

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

If the lists are of unequal length, zip() stops at the shortest one.

Iterating Over Dictionaries

You can iterate through keys, values, or both using built-in methods:

Iterating Over a Dictionary
person = {"name": "Alice", "age": 30}
# Keys
for key in person:
print(key)
# Values
for value in person.values():
print(value)
# Key-value pairs
for key, value in person.items():
print(f"{key}: {value}")

Functions

Function Basics

Functions in Python are reusable blocks of code that perform a specific task. They help make code more modular, readable, and organized. You can define your own functions using the def keyword.

Defining Functions

Simple Function: greet()
def greet():
print("Hello!")

Call the function using its name:

Function Call: greet()
greet() # Output: Hello!

Function Parameters and Arguments

Functions can accept parameters (placeholders) and work with actual arguments (values) when called:

Function with Argument
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # Output: Hello, Alice!

You can pass multiple arguments:

Function with Return
def add(a, b):
return a + b
add(3, 4) # Output: 7

Return Statements

Use return to send a value back from the function:

Function Return to Variable
def square(x):
return x * x
result = square(5) # result = 25

If there’s no return, the function returns None by default.

Default Parameters

Provide default values for parameters:

Function with Default Argument
def greet(name="Guest"):
print(f"Hello, {name}!")
greet() # Hello, Guest
greet("Alice") # Hello, Alice

Keyword Arguments

You can pass arguments using the key=value syntax:

Function with Keyword Arguments
def describe(name, age):
print(f"{name} is {age} years old.")
describe(age=25, name="Bob")

Keyword arguments improve clarity and allow flexible ordering.

Advanced Function Concepts

Beyond basic function definitions, Python provides powerful features like flexible argument handling, anonymous functions, scoping rules, and decorators. Mastering these allows you to write cleaner, more reusable, and dynamic code.

*args and **kwargs

Used to handle variable numbers of arguments in functions.

  • *args → collects positional arguments into a tuple.
  • **kwargs → collects keyword arguments into a dictionary.
*args and **kwargs in Function
def demo(*args, **kwargs):
print("Positional:", args)
print("Keyword:", kwargs)
demo(1, 2, 3, a=10, b=20)

Output:

Console Output
Positional: (1, 2, 3)
Keyword: {'a': 10, 'b': 20}

Lambda Functions

Anonymous, one-line functions used for short tasks:

Lambda Function
square = lambda x: x * x
square(5) # Output: 25

Often used with functions like map(), filter(), or sorted().

Scope: Local vs Global

  • Local: variables defined inside a function — accessible only there.
  • Global: variables defined outside — accessible anywhere (unless shadowed locally).
Global vs Local Variables
x = 10 # Global
def func():
x = 5 # Local
print(x)
func() # Output: 5
print(x) # Output: 10

global and nonlocal Keywords

Use global to modify a global variable inside a function:

Global Keyword Example
count = 0
def increment():
global count
count += 1

Use nonlocal to modify a variable from an enclosing (non-global) scope:

nonlocal Keyword Example
def outer():
x = 10
def inner():
nonlocal x
x += 1
inner()
print(x)

Decorators (Basic)

Decorators are functions that wrap other functions to extend or modify their behavior.

Function Decorator
def decorator(func):
def wrapper():
print("Before function")
func()
print("After function")
return wrapper
@decorator
def say_hello():
print("Hello")
say_hello()

Output:

Output
Before function
Hello
After function

File Handling

Python makes it easy to work with files — whether you're reading data, writing logs, or handling configurations. The open() function is your gateway to file manipulation, and the with statement ensures files are managed safely.

Opening Files with open()

The open() function returns a file object:

Open File in Read Mode
file = open("data.txt", "r") # Open in read mode

Basic syntax:

open() Syntax
open(filename, mode)

Reading Files

.read() – Read entire file content as a string:

Read File Content
f = open("file.txt", "r")
content = f.read()
f.close()

.readline() – Read one line at a time:

Read One Line
line = f.readline()

.readlines() – Read all lines as a list:

Readlines Example
lines = f.readlines()

Writing Files

.write() – Write a single string to the file:

Write to File
f = open("file.txt", "w")
f.write("Hello, World!")
f.close()

.writelines() – Write a list of strings:

Write Multiple Lines
lines = ["First line\n", "Second line\n"]
f.writelines(lines)

Important: Writing ('w') overwrites the file if it exists.

File Modes

ModeDescription
'r'Read (default)
'w'Write (creates or overwrites)
'a'Append (adds to end)
'x'Create (fails if exists)
'b'Binary mode
't'Text mode (default)
'+'Read and write mode

Examples:

File Modes: Binary & Append+Read
open("file.txt", "rb") # Read in binary mode
open("file.txt", "a+") # Append and read mode

Context Managers (with Statement)

Recommended way to handle files — automatically closes the file:

With Statement for Files
with open("file.txt", "r") as f:
    content = f.read()
# No need to call f.close()

This ensures file resources are properly released, even if an error occurs.

File Methods

Once you’ve opened a file using Python’s open() function, you can use various methods to manage reading, writing, and file position. Python also has built-in modules for working with structured file formats like CSV and JSON.

.close(), .seek(), .tell()

.close()

Closes the file and frees system resources:

Open and Close File
f = open("file.txt", "r")
f.close()

Best practice: Use with blocks to handle closing automatically.

.tell()

Returns the current file cursor position (in bytes):

File Pointer Position
with open("file.txt", "r") as f:
    print(f.tell()) # 0 → at the beginning

.seek()

Moves the file cursor to a specific position:

Seek and Read
with open("file.txt", "r") as f:
    f.seek(5) # Move to 5th byte
    data = f.read() # Read from there

Working with CSV Files (csv module)

The csv module helps in reading and writing CSV (Comma-Separated Values) files.

Read & Write CSV File
import csv
# Reading a CSV
with open("data.csv", newline="") as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)
# Writing a CSV
with open("output.csv", "w", newline="") as file:
    writer = csv.writer(file)
    writer.writerow(["name", "age"])
    writer.writerow(["Alice", 30])

For dictionaries:

DictReader & DictWriter
import csv
# Reading CSV using DictReader
with open("data.csv", "r", newline="") as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(row["name"], row["age"])
# Writing CSV using DictWriter
with open("output.csv", "w", newline="") as file:
    fieldnames = ["name", "age"]
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({"name": "Bob", "age": 28})

JSON File Operations (json module)

The json module is used for reading and writing JSON data.

JSON Read & Write
import json
# Writing to JSON
data = {"name": "Alice", "age": 25}
with open("data.json", "w") as f:
    json.dump(data, f)
# Reading from JSON
with open("data.json", "r") as f:
    content = json.load(f)
    print(content["name"]) # Alice

Other useful functions:

  • json.dumps() → converts Python object to JSON string
  • json.loads() → parses JSON string to Python object

Exception Handling

Try-Except

Exception handling in Python allows your program to gracefully handle errors instead of crashing. This is done using try, except, else, and finally blocks.

Basic try-except

Wrap risky code in a try block, and handle errors in the except block:

Try-Except Example
try:
    x = 10 / 0
except:
    print("An error occurred.")

Output:

Output
An error occurred.

Multiple except Blocks

You can handle different types of exceptions separately:

Try-Except (Multiple Exceptions)
try:
    num = int("abc")
except ValueError:
    print("Invalid conversion to int.")
except ZeroDivisionError:
    print("Cannot divide by zero.")

Specific Exceptions

Always try to catch specific exceptions, not general ones. This makes debugging easier and avoids hiding real bugs.

Try-Except with File Open
try:
    with open("file.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("File not found.")

else and finally Blocks

  • else: Runs if no exceptions occur.
  • finally: Always runs, whether or not there was an exception.
Try-Except-Else-Finally
try:
    x = 5 / 1
except ZeroDivisionError:
    print("Division by zero.")
else:
    print("No errors occurred.")
finally:
    print("Always executed.")

Output:

Output
No errors occurred.
Always executed.

Use finally for cleanup tasks like closing files or releasing resources.

Common Exceptions

Python has many built-in exceptions, and knowing the most common ones helps you catch and debug errors effectively. Here are some that you’ll frequently encounter:

ValueError

Occurs when a function receives an argument of the correct type but an inappropriate value.

ValueError Example
int("abc") # Raises ValueError

TypeError

Raised when an operation or function is applied to an object of inappropriate type.

TypeError Example
5 + "5" # TypeError: unsupported operand type(s)

IndexError

Occurs when trying to access an index that is out of range in a sequence.

IndexError Example
lst = [1, 2, 3]
print(lst[5]) # IndexError

KeyError

Happens when you try to access a dictionary key that doesn’t exist.

KeyError Example
person = {"name": "Alice"}
print(person["age"]) # KeyError

Use .get() to avoid this:

Safe Dictionary Access
person = {"name": "Alice"}
print(person.get("age")) # Returns None instead of raising KeyError

FileNotFoundError

Raised when trying to open a file that doesn’t exist.

FileNotFoundError Example
with open("nofile.txt", "r") as f:
data = f.read() # FileNotFoundError

ZeroDivisionError

Happens when a number is divided by zero.

ZeroDivisionError Example
x = 10 / 0 # ZeroDivisionError

Custom Exceptions

You can define your own exceptions by inheriting from the Exception class:

Custom Exception: MyError
class MyError(Exception):
pass
def check_age(age):
if age < 0:
raise MyError("Age cannot be negative.")
check_age(-1)

Output:

Output (Error)
Traceback (most recent call last):
...
MyError: Age cannot be negative.

Custom exceptions are useful for application-specific error handling.

Object-Oriented Programming

Classes and Objects

Python supports object-oriented programming (OOP), a method of structuring code using classes and objects. It helps model real-world entities and encourages code reuse and organization.

Class Definition

A class is like a blueprint for creating objects.

Class Definition: Person
class Person:
pass

This defines an empty class named Person.

Creating Objects

An object is an instance of a class.

Creating an Object
p1 = Person()
print(type(p1)) # <class '__main__.Person'>

Instance Variables and Methods

You can define data (variables) and behaviors (methods) inside the class:

Class with Constructor & Method
class Person:
def __init__(self, name, age):
self.name = name # instance variable
self.age = age
def greet(self):
print(f"Hello, I'm {self.name} and I'm {self.age} years old.")

Create and use the object:

Using the Person Class
p1 = Person("Alice", 30)
p1.greet() # Output: Hello, I'm Alice and I'm 30 years old.

__init__ Method

  • A special method called automatically when a new object is created.
  • It’s used to initialize instance variables.
Constructor Example
def __init__(self, name):
self.name = name

self Keyword

  • Refers to the current object instance.
  • Used to access variables and methods inside the class.
Object Attribute Reference
self.name # refers to the object's 'name' attribute

OOP Concepts

Object-Oriented Programming in Python allows for more advanced features like inheritance, method overriding, and shared or independent variables and methods. These features make your code more flexible, extensible, and reusable.

Inheritance

A class can inherit properties and methods from another class (called the parent or base class):

Inheritance in Python
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def bark(self):
print("Dog barks")
d = Dog()
d.speak() # Inherited
d.bark() # Own method

Method Overriding

A child class can override methods from the parent class:

Method Overriding
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
print("Dog barks") # Overrides parent method
Dog().speak() # Output: Dog barks

super() Function

Used to call methods from the parent class, especially useful in method overriding:

Using super() in Overriding
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
super().speak() # Calls parent method
print("Dog barks")
Dog().speak()

Output:

Output
Animal speaks
Dog barks

Class Variables vs Instance Variables

  • Instance variables: Unique to each object.
  • Class variables: Shared across all instances of the class.
Class & Instance Variable
class Person:
species = "Human" # Class variable
def __init__(self, name):
self.name = name # Instance variable
Class & Instance Variable Access
p1 = Person("Alice")
p2 = Person("Bob")
print(p1.species) # Human
print(p2.name) # Bob

Static Methods and Class Methods

Static Method: Doesn’t access instance or class data

Static Method Example
class Math:
@staticmethod
def add(a, b):
return a + b
print(Math.add(3, 4)) # 7

Class Method: Receives the class itself (cls) as the first argument

Class Method Example
class Person:
count = 0
@classmethod
def increment(cls):
cls.count += 1

Use static methods for utility functions, and class methods when modifying or accessing class-level data.

Special Methods

Special methods in Python (also called magic methods or dunder methods) let you define how your custom objects behave with built-in functions and operators. They all start and end with double underscores (e.g., __init__, __str__).

__str__ and __repr__

Both define how your object is represented as a string.

  • __str__: For readable string output (used by print()).
  • __repr__: For unambiguous representation (used in debugging or in the interpreter).
__str__() vs __repr__()
class Person:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Person: {self.name}"
def __repr__(self):
return f"Person('{self.name}')"
p = Person("Alice")
print(str(p)) # Person: Alice
print(repr(p)) # Person('Alice')

__len__, __getitem__, __setitem__

These let your objects behave like collections (lists, dicts, etc.).

Custom List with Dunder Methods
class MyList:
def __init__(self):
self.data = [1, 2, 3]
def __len__(self):
return len(self.data)
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value

Usage:

Using Custom MyList Class
lst = MyList()
print(len(lst)) # 3
print(lst[1]) # 2
lst[1] = 42
print(lst[1]) # 42

Operator Overloading

You can redefine how operators behave for your custom objects by implementing special methods like:

  • __add__ → +
  • __sub__ → -
  • __mul__ → *
  • __eq__ → ==
  • __lt__ → <

Example:

Custom Addition with Point Class
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __str__(self):
return f"({self.x}, {self.y})"
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = p1 + p2
print(p3) # (4, 6)

Modules and Packages

Importing

Python supports modular programming through modules and packages. A module is simply a .py file containing Python code (functions, classes, variables). A package is a folder containing multiple modules and an __init__.py file.

To use code from other modules, you use the import statement.

import Statement

Import an entire module:

Math Module – Square Root
import math
print(math.sqrt(16)) # 4.0

from ... import

Import specific components directly:

Importing `pi` and `sqrt`
from math import pi, sqrt
print(pi) # 3.1415...
print(sqrt(25)) # 5.0

import ... as

Alias a module or function to a shorter name:

Using NumPy Array
import numpy as np
print(np.array([1, 2, 3]))

Or alias a function:

Import with Alias
from math import sqrt as square_root
print(square_root(9)) # 3.0

Importing Specific Functions

You can import just the parts you need from large modules to reduce memory usage and improve readability:

Random Number Generation
from random import randint, choice
print(randint(1, 10))

Tip: Use only what you need to keep your code clean and efficient.

Standard Library Modules

Python comes with a rich standard library—a collection of built-in modules that let you perform common tasks without installing third-party packages. Below are some essential and frequently used modules:

math, random, datetime

math – Mathematical functions:

Using math Module
import math
print(math.sqrt(16)) # 4.0
print(math.pi) # 3.1415...
print(math.ceil(2.3)) # 3

random – Random number generation:

Using random Module
import random
print(random.randint(1, 10)) # Random int between 1 and 10
print(random.choice(['a', 'b'])) # Random item from list

datetime – Date and time handling:

Using datetime & timedelta
from datetime import datetime, timedelta
now = datetime.now()
print(now.strftime("%Y-%m-%d %H:%M:%S"))
future = now + timedelta(days=7)
print(future)

os, sys, pathlib

os – Interacting with the operating system:

Using os Module
import os
print(os.getcwd()) # Current directory
print(os.listdir()) # List files

sys – Access to system-specific parameters:

Using sys Module
import sys
print(sys.argv) # Command line arguments
print(sys.version) # Python version

pathlib – Object-oriented file paths:

Using pathlib Module
from pathlib import Path
p = Path("example.txt")
print(p.exists()) # True/False
print(p.name) # File name

collections, itertools

collections – Specialized container datatypes:

Using collections.Counter
from collections import Counter
c = Counter("banana")
print(c) # Counter({'a': 3, 'n': 2, 'b': 1})

itertools – Tools for efficient looping:

Using collections.Counter
from collections import Counter
c = Counter("banana")
print(c) # Counter({'a': 3, 'n': 2, 'b': 1})

json, csv, re

json – Working with JSON data:

Using json.loads()
import json
data = json.loads('{"name": "Alice"}')
print(data["name"])

csv – Read/write CSV files:

Using csv.reader()
import csv
with open("data.csv") as f:
reader = csv.reader(f)
for row in reader:
print(row)

re – Regular expressions:

Using re.search()
import re
match = re.search(r"\d+", "Order #12345")
print(match.group()) # 12345

These built-in modules save time and are highly optimized for common tasks.

Creating Modules

In Python, you can organize your code into modules and packages to make it more reusable, readable, and maintainable. Creating your own module is simple — it’s just a .py file that can be imported into other Python scripts.

Creating .py Files (Custom Modules)

Any .py file can be used as a module.

Example: math_utils.py

Add & Subtract Functions
def add(a, b):
return a + b
def subtract(a, b):
return a - b

You can now import this module in another script:

Import from math_utils
import math_utils
print(math_utils.add(2, 3)) # Output: 5

if __name__ == "__main__"

This special block lets you run a file both:

  • As a script (direct execution)
  • As a module (when imported)
Main Check in Python
def greet():
print("Hello!")
if __name__ == "__main__":
greet() # This runs only if the file is run directly

So when you import this module somewhere else, greet() won't automatically run — it runs only when executed directly.

Package Structure

A package is a folder that contains Python modules and an optional __init__.py file (required in older Python versions to mark the folder as a package).

Example structure:

Python Package: my_package
my_package/
├── __init__.py # Marks this folder as a package
├── utils.py # Utility functions
└── math_ops.py # Math-related operations

You can then import like this:

Import from Package
from my_package import utils
from my_package.math_ops import add

You can even make reusable packages and distribute them via tools like pip.

Built-in Functions

Common Built-ins

Python provides a set of built-in functions that are always available—no import required. These functions make common tasks like getting input, working with collections, or performing math operations much easier.

print() and input()

Python I/O Basics
print("Hello, world!") # Output text to the console
name = input("Enter your name: ") # Read user input

len() and type()

len() & type() Functions
len("hello") # 5 → Length of string
len([1, 2, 3]) # 3 → Number of list items
type(42) # <class 'int'>
type("abc") # <class 'str'>

min(), max(), sum(), sorted()

List Summary Functions
numbers = [4, 1, 7, 2]
min(numbers) # 1
max(numbers) # 7
sum(numbers) # 14
sorted(numbers) # [1, 2, 4, 7]

abs(), round(), pow()

Built-in Math Functions
abs(-5) # 5 → Absolute value
round(3.14159, 2) # 3.14 → Round to 2 decimal places
pow(2, 3) # 8 → 2 raised to the power 3

all() and any()

Logical Built-ins
all([True, True, False]) # False → All must be True
any([False, False, True]) # True → At least one True

enumerate() and zip()

enumerate() – Loop with index:

Using enumerate()
for index, value in enumerate(["a", "b", "c"]):
    print(index, value)

zip() – Combine two lists element-wise:

Using zip()
names = ["Alice", "Bob"]
scores = [85, 92]
for name, score in zip(names, scores):
    print(name, score)

These built-ins are powerful and widely used in daily Python coding.

Type Conversion Functions

Python provides built-in functions to convert between data types. These are useful when you're working with user input, performing calculations, or formatting data for output.

int(), float(), str(), bool()

int() – Converts to integer:

Using int()
int("10")        # 10
int(3.7)           # 3

float() – Converts to float:

Using float()
float("5.2")     # 5.2
float(2)             # 2.0

str() – Converts to string:

Using str()
str(123)         # "123"
str(True)        # "True"

bool() – Converts to boolean:

Using bool()
bool(0)           # False
bool("hello")   # True
bool([])          # False

Tip: Empty values (like 0, '', [], None) become False. Everything else is True.

list(), tuple(), dict(), set()

list() – Converts to list:

Using list()
list("abc")          # ['a', 'b', 'c']
list((1, 2, 3))   # [1, 2, 3]

tuple() – Converts to tuple:

Using tuple()
tuple([1, 2])       # (1, 2)

dict() – Converts to dictionary (from key-value pairs):

Using dict()
dict([("a", 1), ("b", 2)])         # {'a': 1, 'b': 2}

set() – Converts to set (removes duplicates):

Using set()
set([1, 2, 2, 3])         # {1, 2, 3}

These functions are essential when transforming data between types in real-world applications.

Utility Functions

Python offers several built-in utility functions that help with data processing, introspection, and debugging. These functions make your code cleaner and more efficient.

map(), filter(), reduce()

  • map(function, iterable)
    Applies a function to every item in an iterable and returns a map object.
Using map() with lambda
numbers = [1, 2, 3]
squares = map(lambda x: x**2, numbers)
print(list(squares))   # [1, 4, 9]
  • filter(function, iterable)

Returns items from an iterable for which the function returns True.

Using filter() with lambda
numbers = [1, 2, 3, 4]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens))   # [2, 4]
  • reduce(function, iterable)

Applies a rolling computation to sequential pairs in an iterable. (Requires functools module)

Using reduce() with lambda
from functools import reduce
numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product)   # 24

isinstance(), hasattr(), getattr()

  • isinstance(object, classinfo)
    Checks if an object is an instance of a class or tuple of classes.
isinstance Example
isinstance(5, int)   # True
  • hasattr(object, name)

Checks if an object has an attribute with the given name.

hasattr Example
hasattr(obj, 'attr_name')
  • getattr(object, name, default)

Gets the attribute value of an object; returns default if attribute doesn’t exist.

getattr Example
getattr(obj, 'attr_name', None)

dir(), help(), id()

  • dir(object)
    Lists attributes and methods of an object.
dir Example
dir([]) # Lists methods of list objects
  • help(object)

Shows the documentation/help for an object or module.

help Example
help(str) # Shows help/documentation for str
  • id(object)

Returns the unique identifier (memory address) of an object.

Python Built-in Function
id(obj) # Returns the unique ID of the object

These utility functions are essential tools for working with data and understanding Python objects.

List/Dict/Set Comprehensions

List Comprehensions

List comprehensions provide a concise way to create lists by applying an expression to each item in an iterable. They are more readable and often faster than traditional loops.

Basic Syntax

Python List Comprehension
[new_item for item in iterable] # Creates a new list by processing each item in iterable

Example: Create a list of squares

Python List Comprehension Example
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]

With Conditions

You can add an if condition to filter items:

Python List Comprehension with Condition
even_squares = [x**2 for x in range(10) if x % 2 == 0] # Squares of even numbers

Nested Comprehensions

For nested loops, list comprehensions can be combined:

Python Nested List Comprehension
matrix = [[1, 2], [3, 4]]
flat = [num for row in matrix for num in row] # [1, 2, 3, 4]

Multiple Iterables

You can iterate over multiple iterables simultaneously using nested loops:

Python List Comprehension - Pairs
pairs = [(x, y) for x in [1, 2] for y in ['a', 'b']]
# [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]

List comprehensions make your code concise and pythonic. They are widely used for transforming and filtering data efficiently.

Dictionary Comprehensions

Dictionary comprehensions provide a compact way to create dictionaries by generating key-value pairs from an iterable or another dictionary. They are similar to list comprehensions but build dictionaries instead of lists.

Basic Syntax

Python Dictionary Comprehension Syntax
{key_expression: value_expression for item in iterable}

Example: Create a dictionary mapping numbers to their squares:

Python Dictionary Comprehension Example
squares = {x: x**2 for x in range(5)}
# Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

With Conditions

You can add an if condition to include only certain items:

Dictionary Comprehension with Condition
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
# Output: {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

Key-Value Transformations

You can transform both keys and values during comprehension:

Example: Convert a list of strings to a dictionary mapping each string to its length:

Dictionary Comprehension Example
words = ['apple', 'banana', 'cherry']
lengths = {word: len(word) for word in words}
# Output: {'apple': 5, 'banana': 6, 'cherry': 6}

Dictionary comprehensions are a powerful and readable way to build dictionaries dynamically.

Set Comprehensions

Set comprehensions let you create sets in a concise and readable way, similar to list and dictionary comprehensions. They automatically handle duplicates since sets only store unique values.

Basic Syntax

Set Comprehension Syntax
{expression for item in iterable}

Example: Create a set of squares:

Set Comprehension Example
squares = {x**2 for x in range(5)}
# Output: {0, 1, 4, 9, 16}

With Conditions

You can add conditions to filter items:

Set Comprehension with Condition
even_squares = {x**2 for x in range(10) if x % 2 == 0}
# Output: {0, 4, 16, 36, 64}

Set comprehensions are useful when you want to quickly create a set based on some logic or filtering.

Regular Expressions

re Module

Python’s re module provides powerful tools for pattern matching and text processing using regular expressions.

re.search(), re.match(), re.findall()

Regular Expressions in Python
import re

# re.search() – Searches for a match anywhere in the string
match = re.search(r"\d+", "Order #12345")
print(match.group()) # 12345

# re.match() – Matches only at the beginning of the string
result = re.match(r"Hello", "Hello world")
print(result.group()) # Hello

# re.findall() – Finds all matching patterns
numbers = re.findall(r"\d+", "A1 B22 C333")
print(numbers) # ['1', '22', '333']

re.sub(), re.split()

Regex Replace and Split
# re.sub() – Replace all matches with another string
clean = re.sub(r"\s+", "-", "Hello World")
print(clean) # Hello-World

# re.split() – Split string based on pattern
parts = re.split(r"\s+", "Split this sentence")
print(parts) # ['Split', 'this', 'sentence']

Pattern Compilation

Compiled patterns improve performance when the same regex is used repeatedly.

Regex Compilation & Findall
pattern = re.compile(r"\d+")
print(pattern.findall("ID 101, 202, 303")) # ['101', '202', '303']

Common Patterns (Regular Expressions)

When writing regular expressions in Python, you use special symbols to define the kind of pattern you're looking for. Below are some of the most frequently used pattern types:

Character Classes

Character classes match any one character from a set.

Regex Character Classes
import re

re.findall(r"[aeiou]", "hello world") # ['e', 'o', 'o']
re.findall(r"[A-Z]", "My Name Is GPT") # ['M', 'N', 'I', 'G']
re.findall(r"\\d", "Age 25") # ['2', '5']
re.findall(r"\\w", "Hi!") # ['H', 'i']
re.findall(r"\\s", "a b\\tc\\nd") # [' ', '\\t', '\\n']
  • [abc] → matches ‘a’, ‘b’, or ‘c’
  • \d → digits (0–9)
  • \w → word characters (letters, digits, underscore)
  • \s → whitespace (space, tab, newline)

2. Quantifiers

Quantifiers specify how many times a pattern must occur.

Regex Quantifiers
re.findall(r"a+", "aaaabc") # ['aaaa']
re.findall(r"b{2}", "abbba") # ['bb']
re.findall(r"\\d{1,3}", "1234567") # ['123', '456', '7']
  • * → 0 or more
  • + → 1 or more
  • ? → 0 or 1
  • {n} → exactly n times
  • {n, m} → between n and m times

3. Anchors

Anchors match positions in the string (not characters).

Regex Anchors
re.findall(r"^Start", "Start here") # ['Start']
re.findall(r"end$", "The story ends") # []
re.findall(r"end$", "This is the end") # ['end']

^ → beginning of string

$ → end of string

\b → word boundary

\B → not a word boundary

4. Groups and Capturing

Use parentheses () to group parts of a regex and extract matched subpatterns.

Regex Grouping
match = re.search(r"My name is (\\w+)", "My name is Alice")
print(match.group(1)) # Alice

match = re.search(r"(\\d{2})/(\\d{2})/(\\d{4})", "Date: 12/07/2025")
print(match.groups()) # ('12', '07', '2025')

() → capture groups

group(n) → returns nth group

groups() → returns all matched groups as a tuple

Working with APIs and JSON

JSON Operations

Python’s json module makes it easy to work with JSON data — whether you're loading data from a file or converting Python objects into JSON format to send via an API.

Import JSON module first:

Import JSON Module
import json

json.loads() and json.dumps()

These are used to convert between JSON strings and Python objects.

Working with JSON Strings
# JSON string to Python object (dict)
json_str = '{"name": "Alice", "age": 25}'
data = json.loads(json_str)
print(data["name"]) # Alice
# Python object to JSON string
py_dict = {"name": "Bob", "age": 30}
json_out = json.dumps(py_dict)
print(json_out) # {"name": "Bob", "age": 30}

json.load() and json.dump()

These are used to read from or write to JSON files.

Writing & Reading JSON File
# Writing Python dict to a file as JSON
person = {"name": "Eve", "age": 40}
with open("person.json", "w") as f:
json.dump(person, f)
# Reading JSON from file to Python object
with open("person.json", "r") as f:
person_data = json.load(f)
print(person_data["age"]) # 40

Working with JSON Data

You typically use these methods when dealing with:

  • API responses (often as JSON strings)
  • Config files
  • Data interchange between systems

JSON maps directly to Python types:

  • JSON Object → Python dict
  • JSON Array → Python list
  • JSON String → Python str
  • JSON Number → Python int / float
  • true / false → True / False
  • null → None

HTTP Requests (requests module)

Python’s requests module is a powerful and easy-to-use HTTP client library for making API calls, such as GET and POST requests, handling headers, and reading responses.

First, install the module (if not already):

Install Requests Library
pip install requests

Then import it in Python:

Import Requests Module
import requests

Sending a GET Request

GET Request with `requests`
response = requests.get("https://api.example.com/data")
print(response.status_code) # 200
print(response.json()) # Parses JSON response to Python dict

You can pass query parameters using the params argument:

GET Request with Query Parameters
params = {"page": 1, "limit": 5}
response = requests.get("https://api.example.com/data", params=params)

Sending a POST Request

POST Request with Payload
payload = {"username": "admin", "password": "1234"}
response = requests.post("https://api.example.com/login", data=payload)
print(response.text)

For sending JSON data:

POST Request with JSON Payload
response = requests.post("https://api.example.com/data", json=payload)

Setting Headers

GET Request with Headers
headers = {
"Authorization": "Bearer your_api_token",
"Content-Type": "application/json"
}
response = requests.get("https://api.example.com/profile", headers=headers)

Response Handling

Handling API Response
if response.status_code == 200:
data = response.json() # Convert JSON response to Python
print(data)
else:
print("Request failed:", response.status_code)

Common response attributes:

  • response.text – Raw response text
  • response.json() – Parse JSON to dict
  • response.status_code – HTTP status code
  • response.headers – Response headers

Date and Time

datetime Module

Python’s built-in datetime module allows you to work with dates and times — from creating and formatting to parsing and calculating time differences.

Importing the module:

Import datetime Module
from datetime import datetime

datetime.now() and datetime.today()

Both give the current local date and time.

Datetime: Add Hours & Subtract Weeks
from datetime import datetime, timedelta
now = datetime.now()
in_two_hours = now + timedelta(hours=2)
last_week = now - timedelta(weeks=1)
print("In two hours:", in_two_hours)
print("Last week:", last_week)

Creating datetime Objects

You can create custom date-time objects manually:

Datetime: Custom Date Object
from datetime import datetime
custom_date = datetime(2025, 12, 25, 10, 30)
print(custom_date) # 2025-12-25 10:30:00

Formatting Dates with strftime()

Use .strftime() to convert a datetime object to a string in your desired format.

Datetime: Date Formatting
from datetime import datetime
now = datetime.now()
formatted = now.strftime("%d-%m-%Y %H:%M:%S")
print(formatted) # e.g., 12-07-2025 15:50:00

Common format codes:

  • %Y → Year (2025)
  • %m → Month (01–12)
  • %d → Day (01–31)
  • %H:%M:%S → Hour, Minute, Second

Parsing Strings with strptime()

Use .strptime() to convert a string into a datetime object.

Datetime: Parse Date from String
from datetime import datetime
date_str = "25-12-2025 10:30"
parsed_date = datetime.strptime(date_str, "%d-%m-%Y %H:%M")
print(parsed_date) # 2025-12-25 10:30:00

Time Operations

Python's datetime module, along with timedelta and timezone, lets you perform arithmetic with dates and times, measure durations, and manage timezones.

Time Arithmetic with timedelta

timedelta represents the difference between two dates or times.

Datetime: Date Arithmetic with timedelta
from datetime import datetime, timedelta
now = datetime.now()
tomorrow = now + timedelta(days=1)
yesterday = now - timedelta(days=1)
print("Now:", now)
print("Tomorrow:", tomorrow)
print("Yesterday:", yesterday)

You can also add or subtract minutes, hours, or weeks:

Datetime: Add Hours & Subtract Weeks
from datetime import datetime, timedelta
now = datetime.now()
in_two_hours = now + timedelta(hours=2)
last_week = now - timedelta(weeks=1)
print("In two hours:", in_two_hours)
print("Last week:", last_week)

timedelta Objects

You can calculate durations:

Datetime: Difference Between Two Dates
from datetime import datetime
start = datetime(2025, 7, 1)
end = datetime(2025, 7, 12)
difference = end - start
print(difference) # 11 days, 0:00:00
print(difference.days) # 11

Timezone Handling

Use timezone from the datetime module to manage time zones.

Datetime: UTC and IST Timezones
from datetime import datetime, timezone, timedelta
utc_now = datetime.now(timezone.utc)
print(utc_now) # Current UTC time

ist = timezone(timedelta(hours=5, minutes=30))
ist_time = datetime.now(ist)
print(ist_time) # Current IST time

To convert between timezones, you can use .astimezone():

Convert UTC to IST
converted = utc_now.astimezone(ist)
print(converted) # UTC converted to IST

Debugging and Testing

Debugging

Debugging helps identify and fix bugs in your Python code. Python offers several tools and techniques to make debugging more efficient.

1. print() Debugging (Basic)

Using print() is the simplest way to trace variable values or code execution:

Python: Debug and Divide Function
def divide(a, b):
    print("a =", a, "b =", b) # Debug print
    return a / b
result = divide(10, 2)
print("Result:", result)

While not ideal for large projects, it works well for quick checks.

2. Using the pdb Debugger (Built-in)

Python’s built-in interactive debugger lets you pause and inspect code line by line.

Python: Debugging with pdb
import pdb
def test_debug(x, y):
    pdb.set_trace() # Breakpoint for debugging
    result = x + y
    return result
test_debug(5, 3)

While debugging, you can use commands like:

  • n → next line
  • c → continue execution
  • p variable → print variable
  • q → quit debugger

3. Common Debugging Techniques

  • Check edge cases (e.g., 0, empty strings/lists, None)
  • Use try-except blocks to catch and understand exceptions
  • Isolate the bug by testing functions individually
  • Add assertions to validate assumptions:
Python: Assert Statement
assert x > 0, "x should be positive"

Error Handling Best Practices

Handling errors properly improves code reliability and maintainability. Here are some best practices to follow in Python:

Logging

Use Python’s built-in logging module instead of print() for recording events, errors, and debugging info. It provides more control over message levels and outputs.

Python: Basic Logging Example
import logging
logging.basicConfig(level=logging.INFO)
logging.info("This is an info message")
logging.error("This is an error message")

Logging levels include: DEBUG, INFO, WARNING, ERROR, CRITICAL.

Assert Statements

Use assert to test assumptions during development. If the condition is false, Python raises an AssertionError.

Python: Assert for Division
def divide(a, b):
assert b != 0, "Denominator must not be zero"
return a / b
divide(10, 0) # Raises AssertionError with message

Assertions help catch bugs early by validating inputs or states.


Unit Testing Basics

Unit tests check small parts of your code automatically to ensure they work correctly.

Python’s built-in unittest module helps create tests:

Python: Unit Testing with unittest
import unittest
def add(a, b):
return a + b
class TestAddFunction(unittest.TestCase):
def test_add_positive(self):
self.assertEqual(add(2, 3), 5)
def test_add_negative(self):
self.assertEqual(add(-1, -1), -2)
if __name__ == '__main__':
unittest.main()

Run tests frequently to catch errors before deployment.

Performance and Best Practices

Code Optimization

Writing efficient Python code improves speed and reduces resource use. Here are key concepts and tools:

Time Complexity Basics

  • Measures how execution time grows with input size.
  • Common complexities:
    • O(1) — constant time
    • O(n) — linear time
    • O(n²) — quadratic time
  • Aim to use algorithms with lower time complexity for better performance.

Memory Usage

  • Efficient use of memory prevents slowdowns and crashes.
  • Avoid unnecessary copies of large data structures.
  • Use generators and iterators to handle large data lazily.

Profiling Code

Profiling helps identify bottlenecks in your code.

  • Use built-in cProfile module:
Python: Profiling with cProfile
import cProfile
def my_function():
# your code here
pass
cProfile.run('my_function()')
  • For line-by-line profiling, use line_profiler (requires installation).

Optimizing code is about balancing speed, memory, and readability.

Python Best Practices

Following best practices helps keep your Python code clean, maintainable, and professional.

PEP 8 Style Guide

  • PEP 8 is the official Python style guide.
  • It covers naming conventions, indentation (4 spaces), line length (max 79 characters), spacing, imports, and more.
  • Use tools like flake8 or black to check and auto-format code.

Code Organization

  • Break code into functions and classes.
  • Group related functions in modules (.py files).
  • Use packages (folders with __init__.py) to organize modules.
  • Keep scripts and libraries separate.

Documentation Strings (Docstrings)

  • Use triple quotes """ """ to document modules, classes, and functions.
  • Explain purpose, parameters, and return values.
Python: Simple Add Function with Docstring
def add(a, b):
"""Return the sum of a and b."""
return a + b
  • Good docstrings improve code readability and help generate docs automatically.

Virtual Environments

  • Use virtual environments to isolate project dependencies.
  • Avoids conflicts between packages used by different projects.

Create and activate virtual environment:

Create and Activate Python Virtual Environment
python -m venv env
source env/bin/activate # Linux/macOS
.\env\Scripts\activate # Windows

Install packages within this environment without affecting system Python.

Common Patterns and Idioms

Pythonic Code

Pythonic code means writing in a way that is clear, concise, and uses Python’s best features and idioms.

List Comprehensions vs Loops

List comprehensions provide a compact way to create lists:

Python: Loop vs List Comprehension
# Using loop
squares = []
for x in range(5):
squares.append(x**2)
# Using list comprehension (more Pythonic)
squares = [x**2 for x in range(5)]

Context Managers

Use with statements to manage resources like files, ensuring proper cleanup:

Python: Read File Using with Statement
with open('file.txt', 'r') as f:
data = f.read()
# No need to explicitly close the file

Generator Expressions

Generators produce items one at a time, saving memory:

Python: List Comprehension vs Generator Expression
# List comprehension (creates full list in memory)
nums = [x**2 for x in range(1000)]
# Generator expression (generates on the fly)
nums_gen = (x**2 for x in range(1000))

Unpacking Sequences

Unpack tuples, lists, or other iterables easily:

Python: Tuple Unpacking & Starred Expressions
point = (10, 20)
x, y = point
# Unpacking with starred expressions
a, *b, c = [1, 2, 3, 4, 5]
# a=1, b=[2,3,4], c=5

Common Algorithms

Understanding basic algorithms helps you solve problems efficiently in Python.

Sorting Algorithms

Python’s built-in sorted() and list .sort() use Timsort, a hybrid sorting algorithm with O(n log n) average time complexity.

Python: Sorting Lists
numbers = [5, 2, 9, 1]
sorted_numbers = sorted(numbers) # Returns new sorted list
numbers.sort() # Sorts list in place

For custom sorting:

Python: Sort List by Length
words = ['apple', 'banana', 'cherry']
sorted_words = sorted(words, key=len) # Sort by length

Searching Algorithms

  • Linear Search: Check each element until found (O(n)).
Python: Linear Search Function
def linear_search(arr, target):
    for i, val in enumerate(arr):
        if val == target:
            return i
    return -1
  • Binary Search: Efficient for sorted lists (O(log n)).
Python: Binary Search Function
def binary_search(arr, target):
    low, high = 0, len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

Basic Data Structure Operations

  • Stacks: Use list with .append() and .pop() (LIFO).
Python: Simple Stack Using List
stack = []
stack.append(1)
stack.append(2)
stack.pop() # 2
  • Queues: Use collections.deque for efficient FIFO.
Python: Queue Using deque
from collections import deque
queue = deque()
queue.append('a')
queue.popleft() # 'a'
  • Linked Lists, Trees, Graphs: Typically implemented with custom classes.

Command Line and System

sys Module

The sys module provides access to system-specific parameters and functions that interact closely with the Python interpreter.

Import it like this:

Python: Import sys Module
import sys

sys.argv – Command Line Arguments

Used to access arguments passed to a Python script from the terminal.

Python: sys.argv Example
# script.py
import sys
print("Script name:", sys.argv[0])
print("Arguments:", sys.argv[1:])

Run from terminal:

Command: Run Python Script with Arguments
python script.py hello world

Output:

Output: sys.argv Result
Script name: script.py
Arguments: ['hello', 'world']

sys.path – Module Search Paths

Shows the list of directories where Python looks for modules.

Python: sys.path Example
import sys
print(sys.path)

You can modify this list to add custom module locations.

sys.version – Python Version Info

Python: sys.version Example
import sys
print(sys.version)
# Example: 3.11.3 (main, Apr 4 2023, 10:20:33) [Clang 14.0.0]

sys.exit() – Exiting a Script

Gracefully exit the program manually.

Python: Exit Program with sys.exit()
if error:
    print("Exiting...")
    sys.exit(1) # 0 = success, non-zero = error

os Module

The os module in Python lets you interact with the operating system — including working with files, directories, and environment variables.

Import it first:

Python: Import os Module
import os

os.getcwd() & os.chdir()

  • os.getcwd() → Returns the current working directory
  • os.chdir(path) → Changes the working directory
Python: Get & Change Working Directory
import os
print(os.getcwd()) # e.g., '/Users/hireit/Desktop'
os.chdir('/tmp') # Change to /tmp directory
print(os.getcwd()) # Output: '/tmp'

os.listdir()

Returns a list of files and directories in the given path.

Python: List Directory Contents
import os
print(os.listdir('.')) # Lists current directory
print(os.listdir('/usr')) # Lists files/folders in /usr

os.path Operations

These functions help with safe path handling:

Python: Common os.path Functions
import os
print(os.path.join("folder", "file.txt")) # folder/file.txt
print(os.path.exists("file.txt")) # True/False
print(os.path.abspath("script.py")) # Full absolute path
print(os.path.isdir("mydir")) # True if it's a directory
print(os.path.isfile("notes.txt")) # True if it's a file

Environment Variables

You can access and modify system environment variables.

Python: Import os Module
import os

Advanced Topics (Brief)

Generators and Iterators

Generators and iterators are used for efficient data processing, especially with large datasets, as they produce values on demand.

yield Keyword

Generators are functions that use yield instead of return. They pause execution and resume where they left off, saving memory.

Python: Exit Program with sys.exit()
if error:
    print("Exiting...")
    sys.exit(1) # 0 = success, non-zero = error

Output:

Output
3
2
1

Generator Expressions

Like list comprehensions but with () instead of []. They return a generator object (lazy evaluation).

Python: Generator Expression with for Loop
squares = (x**2 for x in range(5))
for val in squares:
print(val)

Iterator Protocol

An iterator is any object that implements:

  • __iter__() → returns the iterator object itself
  • __next__() → returns the next item or raises StopIteration

Example:

Python: Using iter() and next()
nums = iter([10, 20, 30])
print(next(nums)) # 10
print(next(nums)) # 20

Custom iterator:

Python: Custom Iterator with __iter__ & __next__
class Counter:
def __init__(self, limit):
self.current = 0
self.limit = limit
def __iter__(self):
return self
def __next__(self):
if self.current >= self.limit:
raise StopIteration
val = self.current
self.current += 1
return val

Context Managers

Context managers handle setup and cleanup actions automatically. The most common example is using the with statement when working with files, which ensures proper resource management.

with Statement

Used to wrap the execution of a block with methods for setup and teardown.

Python: Read File with with open()
with open("file.txt", "r") as f:
content = f.read()
# Automatically closes the file after the block

Even if an error occurs inside the block, the file is safely closed.

Creating Custom Context Managers

You can create your own context manager in two ways:

1. Using a Class (__enter__ and __exit__ methods)

Python: Custom Context Manager with __enter__ / __exit__
class ManagedResource:
def __enter__(self):
print("Resource acquired")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Resource released")
with ManagedResource() as r:
print("Using resource")

Output:

Output: Custom Context Manager
Resource acquired
Using resource
Resource released

2. Using the contextlib Module

For simpler context managers, use a generator with contextlib.contextmanager:

Python: Context Manager with @contextmanager
from contextlib import contextmanager
@contextmanager
def open_file(name):
f = open(name, 'r')
try:
yield f
finally:
f.close()
with open_file("file.txt") as f:
print(f.read())

Decorators

Decorators allow you to modify or enhance functions and classes without changing their actual code. They are widely used in Python for logging, access control, caching, and more.

Function Decorators

A function decorator wraps another function, often using closures.

Python: Decorator with Function Wrapper
def greet(func):
def wrapper():
print("Hello!")
func()
print("Goodbye!")
return wrapper
@greet
def say_name():
print("I'm Python.")
say_name()

Output:

Output
Hello!
I'm Python.
Goodbye!

@greet is equivalent to: say_name = greet(say_name)

Class Decorators

Decorators can also be used with classes to modify or wrap class behavior.

Python: Class Decorator for __repr__
def add_repr(cls):
cls.__repr__ = lambda self: f"<{cls.__name__}: {self.__dict__}>"
return cls
@add_repr
class User:
def __init__(self, name):
self.name = name
print(User("Alice"))
# Output: <User: {'name': 'Alice'}>

Common Decorator Patterns

  1. Logging
    Automatically logs function calls: pythonCopyEdit
Python: Function Decorator logger
def logger(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__} with {args}")
return func(*args, **kwargs)
return wrapper

2. Timing
Measure how long a function takes:

Python: Function Decorator timer
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f} sec")
return result
return wrapper
  1. Access Control / Authorization
    Useful in web apps to check permissions.
  2. Memoization / Caching
    Store results to speed up repeated calls (like @lru_cache from functools).

Conclusion

You now have the complete roadmap to Python mastery. This cheat sheet covers everything from basic syntax to advanced concepts that professional developers use daily.

Sia
Written by Sia

Sia is the co-founder of Corenexis and one of the earliest voices shaping its editorial direction. With years of hands-on experience covering AI and technology, she has been writing about the digital world long before it became everyone's favorite topic — and she still does it better than most.

View all posts by Sia →