A comprehensive, well-organized reference for Python programming
📋 Table of Contents
- 🔤 String Methods
- 📝 List Methods
- 🗂️ Dictionary Methods
- 📦 Tuple & Named Tuples
- 🔸 Set & Frozenset
- 💾 Bytes & Bytearray
- 🔄 List Comprehensions
- ⏰ Date & Time
- ⚙️ User-Defined Functions
- 🔧 Built-in Functions
- 📁 File I/O Operations
- 🚨 Exception Handling
- 🏗️ Classes & OOP
- 📦 Modules & Packages
- 🔍 Regular Expressions
- 📊 Data Structures (Collections)
- 🧵 Iterators & Generators
- 🎨 Context Managers
- ⚡ Performance & Optimization
- 🧪 Testing Basics
- 🔢 Data Structures & Algorithms
🔤 String Methods
🧹 Cleaning & Trimming
| Method | Description | Example |
|---|---|---|
s.strip() | Remove whitespace from both ends | " hello ".strip() → "hello" |
s.strip(chars) | Remove specific characters | "***hello***".strip("*") → "hello" |
s.lstrip() | Remove from left side only | " hello ".lstrip() → "hello " |
s.rstrip() | Remove from right side only | " hello ".rstrip() → " hello" |
✂️ Splitting & Joining
| Method | Description | Example |
|---|---|---|
s.split() | Split on whitespace | "a b c".split() → ['a', 'b', 'c'] |
s.split(sep, maxsplit) | Split by separator | "a,b,c".split(",") → ['a', 'b', 'c'] |
s.splitlines() | Split by line breaks | "a\nb\nc".splitlines() → ['a', 'b', 'c'] |
sep.join(iterable) | Join with separator | ",".join(['a', 'b', 'c']) → "a,b,c" |
🔍 Searching & Testing
| Method | Description | Example |
|---|---|---|
sub in s | Check if substring exists | "ell" in "hello" → True |
s.startswith(prefix) | Check start | "hello".startswith("hel") → True |
s.endswith(suffix) | Check end | "hello".endswith("lo") → True |
s.find(sub) | Find index (returns -1 if not found) | "hello".find("e") → 1 |
s.index(sub) | Find index (raises error if not found) | "hello".index("e") → 1 |
s.count(sub) | Count occurrences | "hello".count("l") → 2 |
🔁 Modifying & Case
| Method | Description | Example |
|---|---|---|
s.replace(old, new) | Replace text | "hello".replace("l", "x") → "hexxo" |
s.upper() | Convert to uppercase | "hello".upper() → "HELLO" |
s.lower() | Convert to lowercase | "HELLO".lower() → "hello" |
s.capitalize() | Capitalize first letter | "hello".capitalize() → "Hello" |
s.title() | Title case | "hello world".title() → "Hello World" |
s.swapcase() | Swap case | "Hello".swapcase() → "hELLO" |
✅ Validation Methods
| Method | Description | Example |
|---|---|---|
s.isdigit() | All digits | "123".isdigit() → True |
s.isalpha() | All letters | "abc".isalpha() → True |
s.isalnum() | Letters and digits | "abc123".isalnum() → True |
s.islower() | All lowercase | "hello".islower() → True |
s.isupper() | All uppercase | "HELLO".isupper() → True |
s.isspace() | All whitespace | " ".isspace() → True |
🎨 Formatting
| Method | Description | Example |
|---|---|---|
s.center(width) | Center string | "hi".center(5) → " hi " |
s.ljust(width) | Left justify | "hi".ljust(5) → "hi " |
s.rjust(width) | Right justify | "hi".rjust(5) → " hi" |
s.zfill(width) | Pad with zeros | "42".zfill(5) → "00042" |
📝 List Methods
➕ Adding Elements
| Method | Description | Example |
|---|---|---|
lst.append(item) | Add single item to end | [1,2].append(3) → [1,2,3] |
lst.extend(iterable) | Add multiple items | [1,2].extend([3,4]) → [1,2,3,4] |
lst.insert(index, item) | Insert at position | [1,3].insert(1, 2) → [1,2,3] |
lst += [item] | Alternative to append | lst += [4] |
lst += iterable | Alternative to extend | lst += [4,5,6] |
🗑️ Removing Elements
| Method | Description | Example |
|---|---|---|
lst.remove(item) | Remove first occurrence | [1,2,2,3].remove(2) → [1,2,3] |
lst.pop() | Remove and return last item | [1,2,3].pop() → returns 3, list becomes [1,2] |
lst.pop(index) | Remove at index | [1,2,3].pop(1) → returns 2, list becomes [1,3] |
lst.clear() | Remove all items | [1,2,3].clear() → [] |
del lst[index] | Delete by index | del lst[1] |
🔍 Searching & Information
| Method | Description | Example |
|---|---|---|
lst.index(item) | Find index of item | [1,2,3].index(2) → 1 |
lst.count(item) | Count occurrences | [1,2,2,3].count(2) → 2 |
len(lst) | Number of items | len([1,2,3]) → 3 |
item in lst | Check if item exists | 2 in [1,2,3] → True |
🔄 Sorting & Reversing
| Method | Description | Example |
|---|---|---|
lst.sort() | Sort in place | [3,1,2].sort() → [1,2,3] |
lst.sort(reverse=True) | Sort descending | [1,2,3].sort(reverse=True) → [3,2,1] |
lst.reverse() | Reverse in place | [1,2,3].reverse() → [3,2,1] |
sorted(lst) | Return new sorted list | sorted([3,1,2]) → [1,2,3] |
list(reversed(lst)) | Return new reversed list | list(reversed([1,2,3])) → [3,2,1] |
✂️ Slicing
| Operation | Description | Example |
|---|---|---|
lst[start:end] | Slice from start to end-1 | [1,2,3,4][1:3] → [2,3] |
lst[start:] | From start to end | [1,2,3,4][1:] → [2,3,4] |
lst[:end] | From beginning to end-1 | [1,2,3,4][:2] → [1,2] |
lst[::step] | Every step-th element | [1,2,3,4,5][::2] → [1,3,5] |
lst[::-1] | Reverse copy | [1,2,3][::-1] → [3,2,1] |
🧮 Advanced Operations
| Operation | Description | Example |
|---|---|---|
sum(lst) | Sum numeric elements | sum([1,2,3]) → 6 |
max(lst) | Maximum value | max([1,3,2]) → 3 |
min(lst) | Minimum value | min([1,3,2]) → 1 |
lst * n | Repeat list n times | [1,2] * 3 → [1,2,1,2,1,2] |
lst1 + lst2 | Concatenate lists | [1,2] + [3,4] → [1,2,3,4] |
🗂️ Dictionary Methods
🔑 Accessing Keys, Values & Items
| Method | Description | Example |
|---|---|---|
d.keys() | Get all keys | {'a':1, 'b':2}.keys() → dict_keys(['a', 'b']) |
d.values() | Get all values | {'a':1, 'b':2}.values() → dict_values([1, 2]) |
d.items() | Get key-value pairs | {'a':1, 'b':2}.items() → dict_items([('a', 1), ('b', 2)]) |
🔍 Getting & Setting Values
| Method | Description | Example |
|---|---|---|
d[key] | Get value (raises KeyError if missing) | {'a':1}['a'] → 1 |
d.get(key, default) | Get value safely | {'a':1}.get('b', 0) → 0 |
d.setdefault(key, default) | Get or set default | d.setdefault('new', []) |
d[key] = value | Set value | d['a'] = 1 |
d.update(other) | Update with another dict | d.update({'b': 2, 'c': 3}) |
🗑️ Removing Items
| Method | Description | Example |
|---|---|---|
del d[key] | Delete key (raises KeyError if missing) | del d['a'] |
d.pop(key) | Remove and return value | d.pop('a') → returns value |
d.pop(key, default) | Remove safely with default | d.pop('missing', None) |
d.popitem() | Remove and return arbitrary item | d.popitem() → ('key', 'value') |
d.clear() | Remove all items | d.clear() → {} |
🏗️ Creating Dictionaries
| Method | Description | Example |
|---|---|---|
dict(iterable) | From key-value pairs | dict([('a',1), ('b',2)]) → {'a':1, 'b':2} |
dict(zip(keys, values)) | From separate sequences | dict(zip(['a','b'], [1,2])) → {'a':1, 'b':2} |
dict.fromkeys(keys, value) | From keys with same value | dict.fromkeys(['a','b'], 0) → {'a':0, 'b':0} |
{k: v for ...} | Dictionary comprehension | {x: x**2 for x in range(3)} → {0:0, 1:1, 2:4} |
🔄 Dictionary Operations
| Operation | Description | Example |
|---|---|---|
key in d | Check if key exists | 'a' in {'a':1, 'b':2} → True |
len(d) | Number of items | len({'a':1, 'b':2}) → 2 |
d.copy() | Shallow copy | d2 = d.copy() |
📊 Collections.Counter (Counting)
from collections import Counter
# Create counter
counter = Counter(['a', 'b', 'a', 'c', 'b', 'a'])
# Counter({'a': 3, 'b': 2, 'c': 1})
# Common methods
counter.most_common(2) # [('a', 3), ('b', 2)]
counter['a'] # 3
counter.update(['a', 'd']) # Add more elementsPython📦 Tuple & Named Tuples
📦 Regular Tuples
🏗️ Creating Tuples
| Method | Description | Example |
|---|---|---|
() | Empty tuple | t = () |
(item,) | Single item (comma required) | t = (1,) |
(item1, item2, ...) | Multiple items | t = (1, 2, 3) |
tuple(iterable) | From iterable | tuple([1, 2, 3]) → (1, 2, 3) |
🔍 Tuple Operations
| Operation | Description | Example |
|---|---|---|
t[index] | Access by index | (1, 2, 3)[1] → 2 |
t[start:end] | Slicing | (1, 2, 3, 4)[1:3] → (2, 3) |
len(t) | Length | len((1, 2, 3)) → 3 |
item in t | Membership test | 2 in (1, 2, 3) → True |
t.count(item) | Count occurrences | (1, 2, 2, 3).count(2) → 2 |
t.index(item) | Find index | (1, 2, 3).index(2) → 1 |
🔄 Tuple Operations
| Operation | Description | Example |
|---|---|---|
t1 + t2 | Concatenation | (1, 2) + (3, 4) → (1, 2, 3, 4) |
t * n | Repetition | (1, 2) * 3 → (1, 2, 1, 2, 1, 2) |
a, b, c = t | Unpacking | a, b, c = (1, 2, 3) |
🏷️ Named Tuples
from collections import namedtuple
# Define named tuple type
Point = namedtuple('Point', ['x', 'y'])
Person = namedtuple('Person', 'name age city') # Space-separated also works
# Create instances
p = Point(10, 20)
person = Person('Alice', 30, 'NYC')
# Access data
print(p.x, p.y) # 10 20 (by name)
print(p[0], p[1]) # 10 20 (by index)
x, y = p # Unpacking
# Methods
print(p._asdict()) # {'x': 10, 'y': 20}
print(Point._fields) # ('x', 'y')
p2 = p._replace(x=15) # Point(x=15, y=20)
p3 = Point._make([5, 25]) # Point(x=5, y=25)Python🔸 Set & Frozenset
🔸 Set Operations
🏗️ Creating Sets
| Method | Description | Example |
|---|---|---|
set() | Empty set | s = set() |
{item1, item2, ...} | Set literal | s = {1, 2, 3} |
set(iterable) | From iterable | set([1, 2, 2, 3]) → {1, 2, 3} |
➕ Adding & Removing
| Method | Description | Example |
|---|---|---|
s.add(item) | Add single item | s.add(4) |
s.update(iterable) | Add multiple items | s.update([4, 5, 6]) |
s.remove(item) | Remove (raises KeyError if missing) | s.remove(3) |
s.discard(item) | Remove safely | s.discard(10) # No error if missing |
s.pop() | Remove arbitrary item | item = s.pop() |
s.clear() | Remove all items | s.clear() |
🧮 Set Mathematics
| Operation | Operator | Method | Description |
|---|---|---|---|
| Union | `s1 \ | s2` | s1.union(s2) |
| Intersection | s1 & s2 | s1.intersection(s2) | Common elements |
| Difference | s1 - s2 | s1.difference(s2) | Elements in s1 but not s2 |
| Symmetric Diff | s1 ^ s2 | s1.symmetric_difference(s2) | Elements in either, but not both |
✅ Set Comparisons
| Operation | Operator | Method | Description |
|---|---|---|---|
| Subset | s1 <= s2 | s1.issubset(s2) | All elements of s1 in s2 |
| Proper subset | s1 < s2 | N/A | Subset but not equal |
| Superset | s1 >= s2 | s1.issuperset(s2) | s1 contains all elements of s2 |
| Disjoint | N/A | s1.isdisjoint(s2) | No common elements |
# Examples
s1 = {1, 2, 3}
s2 = {3, 4, 5}
print(s1 | s2) # {1, 2, 3, 4, 5} - Union
print(s1 & s2) # {3} - Intersection
print(s1 - s2) # {1, 2} - Difference
print(s1 ^ s2) # {1, 2, 4, 5} - Symmetric differencePython❄️ Frozenset (Immutable Set)
fs = frozenset([1, 2, 3])
# Supports all read operations and set math
# Cannot use: add, remove, discard, pop, clear, updatePython💾 Bytes & Bytearray
💾 Bytes (Immutable)
🏗️ Creating Bytes
| Method | Description | Example |
|---|---|---|
b'string' | Bytes literal | b'Hello' |
bytes(iterable) | From integers 0-255 | bytes([72, 101, 108, 108, 111]) → b'Hello' |
str.encode(encoding) | From string | 'Hello'.encode('utf-8') → b'Hello' |
bytes.fromhex(hex_string) | From hex | bytes.fromhex('48656c6c6f') → b'Hello' |
🔄 Bytes Operations
| Operation | Description | Example |
|---|---|---|
b[index] | Access byte (returns int) | b'Hello'[0] → 72 |
b[start:end] | Slicing | b'Hello'[1:4] → b'ell' |
len(b) | Length | len(b'Hello') → 5 |
b1 + b2 | Concatenation | b'Hello' + b' World' → b'Hello World' |
b * n | Repetition | b'Hi' * 3 → b'HiHiHi' |
🔄 Converting from Bytes
| Method | Description | Example |
|---|---|---|
b.decode(encoding) | To string | b'Hello'.decode('utf-8') → 'Hello' |
b.hex() | To hex string | b'Hello'.hex() → '48656c6c6f' |
list(b) | To list of integers | list(b'Hi') → [72, 105] |
🔄 Bytearray (Mutable)
🏗️ Creating Bytearrays
| Method | Description | Example |
|---|---|---|
bytearray() | Empty bytearray | ba = bytearray() |
bytearray(size) | Filled with zeros | bytearray(5) → 5 zero bytes |
bytearray(iterable) | From integers | bytearray([72, 101, 108, 108, 111]) |
bytearray(string, encoding) | From string | bytearray('Hello', 'utf-8') |
✏️ Modifying Bytearrays
| Method | Description | Example |
|---|---|---|
ba[index] = value | Modify byte | ba[0] = 74 |
ba.append(byte) | Add byte to end | ba.append(33) # Add ‘!’ |
ba.extend(iterable) | Add multiple bytes | ba.extend(b' World') |
ba.insert(index, byte) | Insert at position | ba.insert(0, 72) |
ba.remove(byte) | Remove first occurrence | ba.remove(72) |
ba.pop(index) | Remove and return | item = ba.pop() |
ba.clear() | Remove all | ba.clear() |
# Example usage
ba = bytearray(b'Hello')
ba[0] = 74 # Change 'H' to 'J'
ba.append(33) # Add '!'
ba.extend(b' World') # Add more text
print(ba.decode()) # 'Jello! World'Python🔄 List Comprehensions
🧱 Basic Syntax
# Basic pattern
[expression for item in iterable]
# With condition
[expression for item in iterable if condition]
# With conditional expression (ternary)
[expr1 if condition else expr2 for item in iterable]Python🎯 Simple Examples
| Pattern | Example | Result |
|---|---|---|
| Transform | [x * 2 for x in range(5)] | [0, 2, 4, 6, 8] |
| Filter | [x for x in range(10) if x % 2 == 0] | [0, 2, 4, 6, 8] |
| Transform + Filter | [x**2 for x in range(10) if x % 2 == 0] | [0, 4, 16, 36, 64] |
| Conditional | [x if x > 0 else -x for x in [-2, -1, 0, 1, 2]] | [2, 1, 0, 1, 2] |
🔗 Nested Loops
# Cartesian product
[(x, y) for x in [1, 2] for y in [3, 4]]
# Result: [(1, 3), (1, 4), (2, 3), (2, 4)]
# Flatten 2D list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
# Result: [1, 2, 3, 4, 5, 6, 7, 8, 9]Python🎭 Working with Strings
# Remove vowels
[char for char in "hello world" if char not in "aeiou"]
# Result: ['h', 'l', 'l', ' ', 'w', 'r', 'l', 'd']
# Word lengths
[len(word) for word in "the quick brown fox".split()]
# Result: [3, 5, 5, 3]
# Uppercase words
[word.upper() for word in ["apple", "banana", "cherry"]]
# Result: ['APPLE', 'BANANA', 'CHERRY']Python🧮 Mathematical Operations
# Squares
[x**2 for x in range(1, 6)]
# Result: [1, 4, 9, 16, 25]
# Even squares only
[x**2 for x in range(1, 11) if x % 2 == 0]
# Result: [4, 16, 36, 64, 100]
# Pythagorean triples
[(a, b, c) for a in range(1, 11) for b in range(a, 11) for c in range(b, 11) if a**2 + b**2 == c**2]
# Result: [(3, 4, 5), (6, 8, 10)]Python🗂️ Other Comprehensions
Set Comprehension
{x**2 for x in range(5)}
# Result: {0, 1, 4, 9, 16}PythonDictionary Comprehension
{x: x**2 for x in range(5)}
# Result: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# From two lists
keys = ['a', 'b', 'c']
values = [1, 2, 3]
{k: v for k, v in zip(keys, values)}
# Result: {'a': 1, 'b': 2, 'c': 3}PythonGenerator Expression (Memory Efficient)
# Generator (lazy evaluation)
squares_gen = (x**2 for x in range(1000000))
# Only computes values when needed
for square in squares_gen:
if square > 100:
breakPython⏰ Date & Time
📅 datetime Module
🏗️ Creating Date/Time Objects
from datetime import date, time, datetime, timedelta
# Current date/time
today = date.today() # Current date
now = datetime.now() # Current local datetime
utc_now = datetime.utcnow() # Current UTC datetime
# Specific date/time
specific_date = date(2025, 10, 25)
specific_time = time(14, 30, 45) # 2:30:45 PM
specific_datetime = datetime(2025, 10, 25, 14, 30, 45)Python🎨 Formatting & Parsing
dt = datetime(2025, 10, 25, 14, 30, 45)
# Format to string
dt.strftime('%Y-%m-%d %H:%M:%S') # '2025-10-25 14:30:45'
dt.strftime('%B %d, %Y') # 'October 25, 2025'
dt.isoformat() # '2025-10-25T14:30:45'
# Parse from string
datetime.strptime('2025-10-25', '%Y-%m-%d')
datetime.fromisoformat('2025-10-25T14:30:45')Python📝 Common Format Codes
| Code | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2025 |
%m | Month (01-12) | 10 |
%d | Day (01-31) | 25 |
%H | Hour (00-23) | 14 |
%M | Minute (00-59) | 30 |
%S | Second (00-59) | 45 |
%A | Full weekday | Saturday |
%B | Full month | October |
%a | Short weekday | Sat |
%b | Short month | Oct |
🧮 Date Arithmetic
from datetime import timedelta
# Add/subtract time
future = datetime.now() + timedelta(days=7, hours=3, minutes=30)
past = datetime.now() - timedelta(weeks=2)
# Difference between dates
dt1 = datetime(2025, 10, 25)
dt2 = datetime(2025, 11, 1)
diff = dt2 - dt1
print(diff.days) # 7
print(diff.total_seconds()) # 604800.0
# Replace components
modified = dt1.replace(year=2026, month=12)Python🔍 Extracting Components
dt = datetime.now()
print(dt.year, dt.month, dt.day) # Year, month, day
print(dt.hour, dt.minute, dt.second) # Hour, minute, second
print(dt.weekday()) # Monday=0, Sunday=6
print(dt.isoweekday()) # Monday=1, Sunday=7Python🏹 Arrow Library (Third-party)
Install with: pip install arrow
import arrow
# Create arrow objects
now = arrow.now() # Current local time
utc = arrow.utcnow() # Current UTC time
past = arrow.get('2025-10-25') # From string
timestamp = arrow.get(1698230400) # From timestamp
# Formatting
now.format('YYYY-MM-DD HH:mm:ss') # Custom format
now.isoformat() # ISO format
now.humanize() # "just now", "2 hours ago"
# Timezone handling
utc_time = now.to('UTC')
eastern = now.to('US/Eastern')
# Arithmetic
future = now.shift(days=7, hours=3)
past = now.shift(months=-2)
# Ranges
for dt in arrow.Arrow.range('hour', start, end):
print(dt)Python📋 Quick Comparison
| Feature | datetime | arrow |
|---|---|---|
| Parsing | strptime() | get() |
| Formatting | strftime() | format() |
| Timezones | Manual (pytz) | Built-in |
| Arithmetic | timedelta | shift() |
| Human readable | Manual | humanize() |
| Ease of use | Complex | Simple |
⚙️ User-Defined Functions
🏗️ Function Basics
# Basic function
def greet(name):
"""Greet a person by name."""
return f"Hello, {name}!"
# Function with default parameters
def power(base, exponent=2):
return base ** exponent
# Multiple return values
def divmod_custom(a, b):
quotient = a // b
remainder = a % b
return quotient, remainder # Returns tuple
# Call functions
message = greet("Alice")
result = power(3) # Uses default exponent=2
result = power(3, 4) # Uses exponent=4
q, r = divmod_custom(10, 3) # Unpacking return valuesPython📦 Parameter Types
def flexible_function(a, b=10, *args, **kwargs):
"""
a: Required positional argument
b: Optional argument with default value
*args: Variable number of positional arguments (tuple)
**kwargs: Variable number of keyword arguments (dict)
"""
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"kwargs={kwargs}")
# Different ways to call:
flexible_function(1) # a=1, b=10, args=(), kwargs={}
flexible_function(1, 20) # a=1, b=20, args=(), kwargs={}
flexible_function(1, 20, 30, 40) # a=1, b=20, args=(30, 40), kwargs={}
flexible_function(1, 20, 30, x=100, y=200) # a=1, b=20, args=(30,), kwargs={'x': 100, 'y': 200}Python🔄 Advanced Function Features
Lambda Functions (Anonymous)
# Simple lambda
square = lambda x: x ** 2
add = lambda a, b: a + b
# Using with built-in functions
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers)) # [1, 4, 9, 16, 25]
evens = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
# Sorting with lambda
students = [('Alice', 85), ('Bob', 90), ('Charlie', 78)]
students.sort(key=lambda student: student[1]) # Sort by gradePythonClosures
def make_multiplier(factor):
"""Returns a function that multiplies by factor."""
def multiplier(number):
return number * factor
return multiplier
# Create specialized functions
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15PythonDecorators
def timer(func):
"""Decorator to measure function execution time."""
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
@timer
def slow_function():
import time
time.sleep(1)
return "Done!"
# When called, prints execution time
result = slow_function()Python🎯 Type Hints (Python 3.5+)
from typing import List, Dict, Tuple, Optional, Union
def process_data(
numbers: List[int],
multiplier: float = 1.0
) -> List[float]:
"""Process a list of numbers."""
return [n * multiplier for n in numbers]
def get_user_info(user_id: int) -> Optional[Dict[str, str]]:
"""Get user info, returns None if user not found."""
# Implementation here
pass
def flexible_input(value: Union[int, str]) -> str:
"""Accept either int or string."""
return str(value)Python🔄 Higher-Order Functions
from functools import reduce
import operator
numbers = [1, 2, 3, 4, 5]
# map: Apply function to each element
doubled = list(map(lambda x: x * 2, numbers))
# [2, 4, 6, 8, 10]
# filter: Keep elements that match condition
evens = list(filter(lambda x: x % 2 == 0, numbers))
# [2, 4]
# reduce: Combine all elements into single value
total = reduce(lambda a, b: a + b, numbers)
# 15 (equivalent to sum(numbers))
product = reduce(operator.mul, numbers)
# 120 (1 * 2 * 3 * 4 * 5)Python🔧 Built-in Functions
🔄 Type Conversion
| Function | Purpose | Example |
|---|---|---|
int(x) | Convert to integer | int('42') → 42 |
float(x) | Convert to float | float('3.14') → 3.14 |
str(x) | Convert to string | str(42) → '42' |
bool(x) | Convert to boolean | bool(0) → False |
list(x) | Convert to list | list('abc') → ['a', 'b', 'c'] |
tuple(x) | Convert to tuple | tuple([1, 2, 3]) → (1, 2, 3) |
set(x) | Convert to set | set([1, 1, 2]) → {1, 2} |
dict(x) | Convert to dictionary | dict([('a', 1), ('b', 2)]) → {'a': 1, 'b': 2} |
🧮 Mathematical Functions
| Function | Purpose | Example |
|---|---|---|
abs(x) | Absolute value | abs(-5) → 5 |
round(x, n) | Round to n decimals | round(3.14159, 2) → 3.14 |
pow(x, y) | Power (x^y) | pow(2, 3) → 8 |
min(iterable) | Minimum value | min([3, 1, 4]) → 1 |
max(iterable) | Maximum value | max([3, 1, 4]) → 4 |
sum(iterable) | Sum of values | sum([1, 2, 3]) → 6 |
divmod(a, b) | Quotient and remainder | divmod(10, 3) → (3, 1) |
📊 Sequence Operations
| Function | Purpose | Example |
|---|---|---|
len(x) | Length of sequence | len([1, 2, 3]) → 3 |
sorted(iterable) | Return sorted list | sorted([3, 1, 2]) → [1, 2, 3] |
reversed(seq) | Reverse iterator | list(reversed([1, 2, 3])) → [3, 2, 1] |
enumerate(iterable) | Add index numbers | list(enumerate(['a', 'b'])) → [(0, 'a'), (1, 'b')] |
zip(*iterables) | Combine iterables | list(zip([1, 2], ['a', 'b'])) → [(1, 'a'), (2, 'b')] |
all(iterable) | True if all are truthy | all([1, 2, 3]) → True |
any(iterable) | True if any is truthy | any([0, 1, 0]) → True |
🔍 Inspection Functions
| Function | Purpose | Example |
|---|---|---|
type(x) | Get object type | type(42) → <class 'int'> |
isinstance(obj, class) | Check type | isinstance(42, int) → True |
id(x) | Object memory address | id(42) |
dir(x) | List object attributes | dir(str) |
vars(x) | Object’s dict | vars(obj) |
callable(x) | Check if callable | callable(len) → True |
hasattr(obj, name) | Check if attribute exists | hasattr([], 'append') → True |
getattr(obj, name) | Get attribute value | getattr([], 'append') |
🔄 Functional Programming
| Function | Purpose | Example |
|---|---|---|
map(func, iterable) | Apply function to each item | list(map(str.upper, ['a', 'b'])) → ['A', 'B'] |
filter(func, iterable) | Filter items | list(filter(lambda x: x > 0, [-1, 0, 1])) → [1] |
iter(obj) | Create iterator | it = iter([1, 2, 3]) |
next(iterator) | Get next item | next(it) → 1 |
range(start, stop, step) | Generate numbers | list(range(0, 10, 2)) → [0, 2, 4, 6, 8] |
💻 Input/Output
| Function | Purpose | Example |
|---|---|---|
print(*objects) | Print to console | print("Hello", "World") |
input(prompt) | Get user input | name = input("Name: ") |
open(file, mode) | Open file | f = open('file.txt', 'r') |
format(value, spec) | Format value | format(3.14159, '.2f') → '3.14' |
🔢 Number Base Conversions
| Function | Purpose | Example |
|---|---|---|
bin(x) | Binary representation | bin(5) → '0b101' |
oct(x) | Octal representation | oct(8) → '0o10' |
hex(x) | Hexadecimal representation | hex(255) → '0xff' |
chr(x) | Character from Unicode code | chr(65) → 'A' |
ord(c) | Unicode code from character | ord('A') → 65 |
🔧 Advanced
| Function | Purpose | Example |
|---|---|---|
eval(expression) | Evaluate string as code | eval('2 + 3') → 5 |
exec(code) | Execute code string | exec('x = 5; print(x)') |
compile(source, filename, mode) | Compile code | compile('x=1', '', 'exec') |
globals() | Global variables dict | globals()['x'] |
locals() | Local variables dict | locals() |
help(obj) | Interactive help | help(str) |
💡 Practical Examples
Working with Files
# Reading a file
with open('data.txt', 'r') as f:
content = f.read()
lines = f.readlines()
# Writing to a file
with open('output.txt', 'w') as f:
f.write('Hello, World!')PythonData Processing Pipeline
numbers = range(1, 11)
# Chain operations
result = list(
map(lambda x: x ** 2, # Square each number
filter(lambda x: x % 2 == 0, # Keep only even numbers
numbers))) # [4, 16, 36, 64, 100]
# Or using comprehension (more Pythonic)
result = [x**2 for x in numbers if x % 2 == 0]PythonUsing enumerate and zip
# enumerate: Add index to items
names = ['Alice', 'Bob', 'Charlie']
for i, name in enumerate(names, start=1):
print(f"{i}. {name}")
# Output: 1. Alice, 2. Bob, 3. Charlie
# zip: Combine multiple iterables
first_names = ['John', 'Jane', 'Bob']
last_names = ['Doe', 'Smith', 'Johnson']
ages = [30, 25, 35]
for first, last, age in zip(first_names, last_names, ages):
print(f"{first} {last} is {age} years old")Python🎯 Quick Reference Summary
🔤 String Essentials
- Clean:
strip(),lstrip(),rstrip() - Split/Join:
split(),join() - Search:
find(),startswith(),endswith(),in - Modify:
replace(),upper(),lower(),title() - Validate:
isdigit(),isalpha(),isalnum()
📝 List Essentials
- Add:
append(),extend(),insert(),+= - Remove:
remove(),pop(),clear(),del - Info:
len(),count(),index(),in - Order:
sort(),reverse(),sorted(),reversed()
🗂️ Dict Essentials
- Access:
[],get(),keys(),values(),items() - Modify:
update(),setdefault(),pop(),clear() - Create:
dict(),dict.fromkeys(),{k:v for ...}
🔸 Set Essentials
- Math:
|(union),&(intersection),-(difference),^(symmetric diff) - Test:
<=(subset),>=(superset),isdisjoint() - Modify:
add(),update(),remove(),discard()
🔧 Built-in Essentials
- Convert:
int(),str(),list(),dict(),set() - Math:
sum(),min(),max(),abs(),round() - Iterate:
range(),enumerate(),zip(),map(),filter() - Inspect:
len(),type(),isinstance(),dir()
📁 File I/O Operations
📖 Reading Files
# Read entire file
with open('file.txt', 'r') as f:
content = f.read() # Entire file as string
with open('file.txt', 'r') as f:
lines = f.readlines() # List of lines (with \n)
with open('file.txt', 'r') as f:
lines = f.read().splitlines() # List of lines (without \n)
# Read line by line (memory efficient)
with open('file.txt', 'r') as f:
for line in f:
print(line.strip()) # Process each line
# Read specific number of characters
with open('file.txt', 'r') as f:
chunk = f.read(100) # Read first 100 charactersPython✏️ Writing Files
# Write (overwrites existing content)
with open('file.txt', 'w') as f:
f.write('Hello, World!')
f.write('\nSecond line')
# Append to existing file
with open('file.txt', 'a') as f:
f.write('\nAppended line')
# Write multiple lines
lines = ['Line 1\n', 'Line 2\n', 'Line 3\n']
with open('file.txt', 'w') as f:
f.writelines(lines)
# Write with print function
with open('file.txt', 'w') as f:
print('Hello', 'World', file=f)Python🗂️ File Modes & Types
| Mode | Description | Example Use |
|---|---|---|
'r' | Read (default) | Reading text files |
'w' | Write (truncates) | Creating new files |
'a' | Append | Adding to log files |
'r+' | Read & Write | Updating files |
'rb' | Read binary | Images, videos |
'wb' | Write binary | Saving binary data |
📂 Working with Paths
import os
from pathlib import Path
# os.path (traditional)
file_path = os.path.join('folder', 'subfolder', 'file.txt')
directory = os.path.dirname(file_path)
filename = os.path.basename(file_path)
name, ext = os.path.splitext(filename)
# pathlib (modern, recommended)
path = Path('folder') / 'subfolder' / 'file.txt'
print(path.parent) # folder/subfolder
print(path.name) # file.txt
print(path.stem) # file
print(path.suffix) # .txt
print(path.exists()) # True/False
print(path.is_file()) # True/False
print(path.is_dir()) # True/FalsePython📁 Directory Operations
import os
import shutil
from pathlib import Path
# Create directories
os.makedirs('path/to/directory', exist_ok=True)
Path('path/to/directory').mkdir(parents=True, exist_ok=True)
# List directory contents
files = os.listdir('.')
files = list(Path('.').iterdir())
# Walk through directory tree
for root, dirs, files in os.walk('.'):
for file in files:
file_path = os.path.join(root, file)
print(file_path)
# Copy, move, delete
shutil.copy2('source.txt', 'destination.txt') # Copy file
shutil.copytree('source_dir', 'dest_dir') # Copy directory
shutil.move('old_location', 'new_location') # Move/rename
os.remove('file.txt') # Delete file
shutil.rmtree('directory') # Delete directoryPython🔍 File Information
import os
from pathlib import Path
# File stats
stat_info = os.stat('file.txt')
path = Path('file.txt')
print(path.stat().st_size) # File size in bytes
print(path.stat().st_mtime) # Last modified timestamp
print(os.path.getsize('file.txt')) # File size
print(os.path.getmtime('file.txt')) # Last modified timePython🚨 Exception Handling
🎯 Basic Try-Except
# Basic exception handling
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")
# Multiple exceptions
try:
value = int(input("Enter a number: "))
result = 10 / value
except ValueError:
print("Invalid number format!")
except ZeroDivisionError:
print("Cannot divide by zero!")
# Catch multiple exceptions at once
try:
# risky code
pass
except (ValueError, TypeError, KeyError) as e:
print(f"Error occurred: {e}")Python🔧 Advanced Exception Handling
# Complete try-except-else-finally block
try:
file = open('data.txt', 'r')
data = file.read()
number = int(data)
except FileNotFoundError:
print("File not found!")
except ValueError:
print("Invalid number in file!")
else:
# Runs only if no exception occurred
print("File processed successfully!")
result = number * 2
finally:
# Always runs (cleanup code)
if 'file' in locals():
file.close()
print("Cleanup completed")Python🚀 Raising Exceptions
# Raise built-in exceptions
def validate_age(age):
if age < 0:
raise ValueError("Age cannot be negative")
if age > 150:
raise ValueError("Age seems unrealistic")
return age
# Custom exceptions
class CustomError(Exception):
"""Custom exception for specific use cases."""
pass
class ValidationError(Exception):
"""Raised when validation fails."""
def __init__(self, message, error_code=None):
super().__init__(message)
self.error_code = error_code
def process_data(data):
if not data:
raise ValidationError("Data cannot be empty", error_code=100)Python📝 Common Built-in Exceptions
| Exception | When it occurs | Example |
|---|---|---|
ValueError | Invalid value for type | int('abc') |
TypeError | Wrong type | 'hello' + 5 |
KeyError | Missing dictionary key | dict['missing_key'] |
IndexError | List index out of range | [1,2,3][5] |
FileNotFoundError | File doesn’t exist | open('missing.txt') |
AttributeError | Missing attribute/method | 'hello'.missing_method() |
ZeroDivisionError | Division by zero | 10 / 0 |
ImportError | Cannot import module | import non_existent_module |
🛡️ Exception Best Practices
# Good: Be specific about exceptions
try:
with open('config.json', 'r') as f:
config = json.load(f)
except FileNotFoundError:
config = {} # Use default config
except json.JSONDecodeError:
raise ValueError("Invalid JSON in config file")
# Good: Use context managers for resource management
try:
with open('file.txt', 'r') as f:
content = f.read()
except FileNotFoundError:
print("File not found")
# File automatically closed even if exception occurs
# Good: Log exceptions for debugging
import logging
try:
risky_operation()
except Exception as e:
logging.error(f"Operation failed: {e}", exc_info=True)
raise # Re-raise the exceptionPython🏗️ Classes & OOP
📦 Basic Class Definition
class Person:
# Class variable (shared by all instances)
species = "Homo sapiens"
def __init__(self, name, age):
# Instance variables
self.name = name
self.age = age
self._email = None # Protected (convention)
self.__ssn = None # Private (name mangling)
# Instance method
def introduce(self):
return f"Hi, I'm {self.name} and I'm {self.age} years old"
# Instance method with parameters
def have_birthday(self):
self.age += 1
return f"Happy birthday! Now I'm {self.age}"
# Property (getter)
@property
def email(self):
return self._email
# Property setter
@email.setter
def email(self, value):
if '@' in value:
self._email = value
else:
raise ValueError("Invalid email format")
# String representation
def __str__(self):
return f"Person(name='{self.name}', age={self.age})"
def __repr__(self):
return f"Person('{self.name}', {self.age})"
# Usage
person = Person("Alice", 30)
print(person.introduce()) # Hi, I'm Alice and I'm 30 years old
person.email = "alice@email.com"
print(person.email) # alice@email.comPython🧬 Inheritance
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
return "Some generic animal sound"
def info(self):
return f"{self.name} is a {self.species}"
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "Canis lupus") # Call parent constructor
self.breed = breed
# Override parent method
def make_sound(self):
return "Woof!"
# Add new method
def fetch(self):
return f"{self.name} is fetching the ball!"
class Cat(Animal):
def __init__(self, name, indoor=True):
super().__init__(name, "Felis catus")
self.indoor = indoor
def make_sound(self):
return "Meow!"
# Usage
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers", indoor=True)
print(dog.make_sound()) # Woof!
print(cat.info()) # Whiskers is a Felis catus
print(dog.fetch()) # Buddy is fetching the ball!Python🔧 Special Methods (Magic Methods)
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __repr__(self):
return f"Vector({self.x}, {self.y})"
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __len__(self):
return int((self.x**2 + self.y**2)**0.5)
def __getitem__(self, index):
if index == 0:
return self.x
elif index == 1:
return self.y
else:
raise IndexError("Vector index out of range")
# Usage
v1 = Vector(2, 3)
v2 = Vector(1, 4)
v3 = v1 + v2 # Vector(3, 7)
v4 = v1 * 2 # Vector(4, 6)
print(v1 == v2) # False
print(v1[0]) # 2 (accessing like a list)Python🏭 Class Methods and Static Methods
class MathUtils:
pi = 3.14159
def __init__(self, precision=2):
self.precision = precision
@classmethod
def circle_area(cls, radius):
"""Class method - works with class, not instance"""
return cls.pi * radius * radius
@staticmethod
def add(a, b):
"""Static method - independent function grouped in class"""
return a + b
@classmethod
def from_string(cls, math_string):
"""Alternative constructor"""
precision = len(math_string.split('.')[-1])
return cls(precision)
# Usage
area = MathUtils.circle_area(5) # Can call without creating instance
result = MathUtils.add(10, 20) # Static method
math_obj = MathUtils.from_string("3.14159") # Alternative constructorPython🎭 Abstract Base Classes
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
# Concrete method (can be used by subclasses)
def description(self):
return f"This is a shape with area {self.area()}"
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
# Cannot instantiate ABC directly
# shape = Shape() # This would raise TypeError
rect = Rectangle(5, 3)
print(rect.area()) # 15
print(rect.description()) # This is a shape with area 15Python📦 Modules & Packages
📥 Importing Modules
# Different ways to import
import math # Import entire module
import math as m # Import with alias
from math import sqrt, pi # Import specific functions
from math import * # Import all (not recommended)
# Usage
print(math.sqrt(16)) # 4.0
print(m.pi) # 3.141592653589793
print(sqrt(25)) # 5.0Python📦 Creating Your Own Module
# File: my_utils.py
"""
A utility module with helpful functions.
"""
def greet(name):
"""Greet a person by name."""
return f"Hello, {name}!"
def factorial(n):
"""Calculate factorial of n."""
if n <= 1:
return 1
return n * factorial(n - 1)
# Module-level variable
VERSION = "1.0.0"
# Code that runs when module is executed directly
if __name__ == "__main__":
print("This module is being run directly")
print(f"Version: {VERSION}")Python# File: main.py - Using the module
import my_utils
from my_utils import greet
print(my_utils.greet("Alice")) # Hello, Alice!
print(greet("Bob")) # Hello, Bob!
print(my_utils.factorial(5)) # 120
print(my_utils.VERSION) # 1.0.0Python📁 Creating Packages
my_package/
__init__.py
math_utils.py
string_utils.py
subpackage/
__init__.py
advanced.pyPython# File: my_package/__init__.py
"""
My custom package for utilities.
"""
from .math_utils import add, multiply
from .string_utils import capitalize_words
__version__ = "1.0.0"
__all__ = ['add', 'multiply', 'capitalize_words']Python# File: my_package/math_utils.py
def add(a, b):
return a + b
def multiply(a, b):
return a * bPython# Usage
from my_package import add, multiply
import my_package.string_utils as su
result = add(5, 3) # 8
text = su.capitalize_words("hello world")Python🔄 Module Search Path & Reloading
import sys
import importlib
# View module search paths
print(sys.path)
# Add custom path
sys.path.append('/path/to/my/modules')
# Reload a module (useful in development)
import my_module
importlib.reload(my_module)
# Check if module is available
try:
import optional_module
HAS_OPTIONAL = True
except ImportError:
HAS_OPTIONAL = FalsePython📊 Popular Standard Library Modules
import os # Operating system interface
import sys # System-specific parameters
import json # JSON encoder/decoder
import datetime # Date and time handling
import random # Generate random numbers
import re # Regular expressions
import urllib.request # URL handling
import sqlite3 # SQLite database
import csv # CSV file reading/writing
import collections # Specialized container datatypes
import itertools # Iterator functions
import functools # Higher-order functions
import pathlib # Object-oriented filesystem paths
import logging # Logging facility
import argparse # Command-line argument parsing
import configparser # Configuration file parserPython🔍 Regular Expressions
🎯 Basic Pattern Matching
import re
text = "The quick brown fox jumps over the lazy dog"
# Basic search
match = re.search(r'fox', text)
if match:
print(f"Found 'fox' at position {match.start()}")
# Find all matches
matches = re.findall(r'\b\w{5}\b', text) # All 5-letter words
print(matches) # ['quick', 'brown', 'jumps']
# Split by pattern
words = re.split(r'\s+', text) # Split by whitespace
print(words)Python🔧 Common Regex Patterns
| Pattern | Meaning | Example |
|---|---|---|
. | Any character except newline | a.c matches abc, a5c |
* | 0 or more repetitions | ab* matches a, ab, abbb |
+ | 1 or more repetitions | ab+ matches ab, abbb |
? | 0 or 1 repetition | ab? matches a, ab |
{n} | Exactly n repetitions | a{3} matches aaa |
{n,m} | n to m repetitions | a{2,4} matches aa, aaa, aaaa |
^ | Start of string | ^hello matches start |
$ | End of string | world$ matches end |
\d | Any digit | \d+ matches 123 |
\w | Word character | \w+ matches hello_123 |
\s | Whitespace | \s+ matches spaces/tabs |
[abc] | Character class | [aeiou] matches vowels |
[^abc] | Negated class | [^0-9] matches non-digits |
📧 Practical Examples
import re
# Email validation
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
def is_valid_email(email):
return bool(re.match(email_pattern, email))
# Phone number extraction
phone_pattern = r'\b\d{3}-\d{3}-\d{4}\b'
text = "Call me at 555-123-4567 or 555-987-6543"
phone_numbers = re.findall(phone_pattern, text)
# URL extraction
url_pattern = r'https?://[^\s]+'
text = "Visit https://example.com or http://test.org"
urls = re.findall(url_pattern, text)
# Replace patterns
text = "The price is $25.99 and $15.50"
# Replace prices with "PRICE"
cleaned = re.sub(r'\$\d+\.\d{2}', 'PRICE', text)
print(cleaned) # "The price is PRICE and PRICE"Python🔄 Advanced Regex Features
import re
# Groups and capturing
pattern = r'(\d{4})-(\d{2})-(\d{2})' # YYYY-MM-DD
text = "Today is 2025-10-25"
match = re.search(pattern, text)
if match:
year, month, day = match.groups()
print(f"Year: {year}, Month: {month}, Day: {day}")
# Named groups
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
match = re.search(pattern, text)
if match:
print(match.groupdict()) # {'year': '2025', 'month': '10', 'day': '25'}
# Lookahead and lookbehind
# Positive lookahead: match X if followed by Y
pattern = r'\d+(?= dollars)' # Numbers followed by " dollars"
text = "I have 100 dollars and 50 cents"
matches = re.findall(pattern, text) # ['100']
# Case-insensitive matching
pattern = r'python'
text = "I love Python programming"
match = re.search(pattern, text, re.IGNORECASE)Python🛠️ Regex Compilation and Performance
import re
# Compile regex for better performance when used multiple times
email_regex = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
def validate_emails(email_list):
valid_emails = []
for email in email_list:
if email_regex.match(email):
valid_emails.append(email)
return valid_emails
# Multi-line and verbose regex
complex_pattern = re.compile(r'''
^ # Start of string
[a-zA-Z0-9._%+-]+ # Username part
@ # @ symbol
[a-zA-Z0-9.-]+ # Domain name
\. # Dot
[a-zA-Z]{2,} # Top-level domain
$ # End of string
''', re.VERBOSE)Python📊 Data Structures (Collections)
🔄 collections.deque (Double-ended Queue)
from collections import deque
# Create deque
dq = deque([1, 2, 3])
dq = deque(maxlen=5) # Limited size deque
# Add elements
dq.append(4) # Add to right: [1, 2, 3, 4]
dq.appendleft(0) # Add to left: [0, 1, 2, 3, 4]
# Remove elements
right_item = dq.pop() # Remove from right
left_item = dq.popleft() # Remove from left
# Extend
dq.extend([5, 6, 7]) # Extend right
dq.extendleft([1, 2]) # Extend left (order reversed)
# Rotate
dq.rotate(1) # Rotate right by 1
dq.rotate(-2) # Rotate left by 2
# Use cases: sliding window, undo functionality, breadth-first searchPython🏷️ collections.OrderedDict
from collections import OrderedDict
# Maintains insertion order (note: regular dict does this in Python 3.7+)
od = OrderedDict()
od['first'] = 1
od['second'] = 2
od['third'] = 3
# Move to end
od.move_to_end('first') # Move 'first' to end
od.move_to_end('second', last=False) # Move 'second' to beginning
# Pop items
last_item = od.popitem() # Remove last item
first_item = od.popitem(last=False) # Remove first itemPython🔢 collections.Counter
from collections import Counter
# Count elements
words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
counter = Counter(words)
print(counter) # Counter({'apple': 3, 'banana': 2, 'cherry': 1})
# Most common elements
print(counter.most_common(2)) # [('apple', 3), ('banana', 2)]
# Arithmetic operations
counter1 = Counter(['a', 'b', 'c', 'a'])
counter2 = Counter(['a', 'b', 'b', 'd'])
print(counter1 + counter2) # Addition
print(counter1 - counter2) # Subtraction
print(counter1 & counter2) # Intersection
print(counter1 | counter2) # Union
# Update counter
counter.update(['apple', 'date'])
counter.subtract(['banana'])Python🔗 collections.ChainMap
from collections import ChainMap
# Combine multiple dictionaries
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
dict3 = {'c': 5, 'd': 6}
# ChainMap searches in order
combined = ChainMap(dict1, dict2, dict3)
print(combined['b']) # 2 (from dict1, first occurrence)
print(combined['c']) # 4 (from dict2, first occurrence)
# Add new context
combined = combined.new_child({'e': 7})
print(combined['e']) # 7Python📝 collections.defaultdict
from collections import defaultdict
# Dictionary with default values
dd = defaultdict(list) # Default value is empty list
dd['fruits'].append('apple')
dd['fruits'].append('banana')
print(dd['fruits']) # ['apple', 'banana']
print(dd['vegetables']) # [] (empty list, no KeyError)
# With different default types
int_dd = defaultdict(int) # Default: 0
set_dd = defaultdict(set) # Default: empty set
str_dd = defaultdict(str) # Default: empty string
# Custom default function
def default_factory():
return "N/A"
custom_dd = defaultdict(default_factory)
print(custom_dd['missing']) # "N/A"
# Practical example: grouping
from collections import defaultdict
students = [
('Alice', 'Math'),
('Bob', 'Science'),
('Alice', 'English'),
('Charlie', 'Math'),
('Bob', 'Math')
]
# Group by student
grouped = defaultdict(list)
for student, subject in students:
grouped[student].append(subject)
print(dict(grouped))
# {'Alice': ['Math', 'English'], 'Bob': ['Science', 'Math'], 'Charlie': ['Math']}Python🗂️ heapq (Priority Queue)
import heapq
# Create heap (min-heap by default)
heap = [3, 1, 4, 1, 5, 9, 2, 6]
heapq.heapify(heap) # Convert list to heap in-place
# Add elements
heapq.heappush(heap, 0)
# Remove smallest element
smallest = heapq.heappop(heap)
# Get n smallest/largest elements
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
smallest_3 = heapq.nsmallest(3, numbers) # [1, 1, 2]
largest_3 = heapq.nlargest(3, numbers) # [9, 6, 5]
# Priority queue with custom objects
class Task:
def __init__(self, priority, description):
self.priority = priority
self.description = description
def __lt__(self, other):
return self.priority < other.priority
def __repr__(self):
return f"Task(priority={self.priority}, desc='{self.description}')"
# Usage
tasks = []
heapq.heappush(tasks, Task(3, "Low priority"))
heapq.heappush(tasks, Task(1, "High priority"))
heapq.heappush(tasks, Task(2, "Medium priority"))
next_task = heapq.heappop(tasks) # Gets highest priority taskPython🧵 Iterators & Generators
🔄 Understanding Iterators
# Any object with __iter__() and __next__() methods
class CountUp:
def __init__(self, start, end):
self.start = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.start >= self.end:
raise StopIteration
self.start += 1
return self.start - 1
# Usage
counter = CountUp(1, 5)
for num in counter:
print(num) # 1, 2, 3, 4
# Built-in iter() function
my_list = [1, 2, 3]
iterator = iter(my_list)
print(next(iterator)) # 1
print(next(iterator)) # 2Python⚡ Generators (Simple and Powerful)
# Generator function (uses yield)
def count_up(start, end):
while start < end:
yield start
start += 1
# Usage
for num in count_up(1, 5):
print(num) # 1, 2, 3, 4
# Generator expressions
squares = (x**2 for x in range(10)) # Generator, not list
print(next(squares)) # 0
print(next(squares)) # 1
# Memory efficient file processing
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line.strip()
# Process file line by line without loading entire file
for line in read_large_file('large_file.txt'):
process_line(line)Python🧮 Advanced Generator Features
# Generator with send() and throw()
def accumulator():
total = 0
while True:
value = yield total
if value is not None:
total += value
acc = accumulator()
next(acc) # Prime the generator
print(acc.send(10)) # 10
print(acc.send(5)) # 15
print(acc.send(3)) # 18
# Generator pipeline
def read_numbers(filename):
with open(filename) as f:
for line in f:
yield int(line.strip())
def square_numbers(numbers):
for num in numbers:
yield num ** 2
def filter_even(numbers):
for num in numbers:
if num % 2 == 0:
yield num
# Chain generators together
def process_numbers(filename):
numbers = read_numbers(filename)
squared = square_numbers(numbers)
even_squares = filter_even(squared)
return even_squares
# Memory efficient - processes one number at a time
for result in process_numbers('numbers.txt'):
print(result)Python🔧 itertools Module
import itertools
# Infinite iterators
counter = itertools.count(10, 2) # 10, 12, 14, 16, ...
cycler = itertools.cycle(['A', 'B', 'C']) # A, B, C, A, B, C, ...
repeater = itertools.repeat('hello', 3) # hello, hello, hello
# Combinatorial iterators
list1 = [1, 2]
list2 = ['a', 'b']
# Cartesian product
product = list(itertools.product(list1, list2))
# [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
# Permutations
perms = list(itertools.permutations([1, 2, 3], 2))
# [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
# Combinations
combs = list(itertools.combinations([1, 2, 3, 4], 2))
# [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
# Grouping
data = [('A', 1), ('A', 2), ('B', 3), ('B', 4), ('A', 5)]
grouped = itertools.groupby(data, key=lambda x: x[0])
for key, group in grouped:
print(f"{key}: {list(group)}")
# Chain multiple iterables
chained = itertools.chain([1, 2], [3, 4], [5, 6])
# 1, 2, 3, 4, 5, 6
# Take while condition is true
numbers = [1, 3, 5, 8, 9, 11]
odds = list(itertools.takewhile(lambda x: x % 2 == 1, numbers))
# [1, 3, 5]Python🎨 Context Managers
🔧 Built-in Context Managers
# File handling (most common)
with open('file.txt', 'r') as f:
content = f.read()
# File automatically closed
# Multiple files
with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
data = infile.read()
outfile.write(data.upper())
# Suppress exceptions
from contextlib import suppress
with suppress(FileNotFoundError):
with open('might_not_exist.txt', 'r') as f:
content = f.read()
# No exception raised if file doesn't existPython🏗️ Creating Custom Context Managers
# Method 1: Class-based
class DatabaseConnection:
def __init__(self, database_url):
self.database_url = database_url
self.connection = None
def __enter__(self):
print(f"Connecting to {self.database_url}")
# self.connection = create_connection(self.database_url)
self.connection = f"Connected to {self.database_url}"
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
print("Closing database connection")
if self.connection:
# self.connection.close()
self.connection = None
# Return False to propagate exceptions
return False
# Usage
with DatabaseConnection("postgresql://localhost") as conn:
print(f"Using connection: {conn}")
# Do database operations
# Connection automatically closed
# Method 2: Function-based with contextlib
from contextlib import contextmanager
@contextmanager
def timer():
import time
start = time.time()
print("Timer started")
try:
yield start
finally:
end = time.time()
print(f"Timer finished. Elapsed: {end - start:.2f}s")
# Usage
with timer() as start_time:
# Do some work
import time
time.sleep(1)
print("Working...")Python🔄 Advanced Context Manager Examples
from contextlib import contextmanager, ExitStack
import tempfile
import os
# Temporary directory
@contextmanager
def temporary_directory():
temp_dir = tempfile.mkdtemp()
try:
yield temp_dir
finally:
import shutil
shutil.rmtree(temp_dir)
# Usage
with temporary_directory() as temp_dir:
file_path = os.path.join(temp_dir, 'temp_file.txt')
with open(file_path, 'w') as f:
f.write("Temporary content")
# Directory and all contents automatically deleted
# Managing multiple context managers
def process_files(filenames):
with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
# All files will be automatically closed
for f in files:
print(f.read())
# Custom exception handling in context manager
@contextmanager
def ignore_errors(*exceptions):
try:
yield
except exceptions as e:
print(f"Ignored exception: {e}")
# Usage
with ignore_errors(ValueError, TypeError):
result = int("not_a_number") # ValueError ignored
print("This won't be reached")
print("This will be reached")Python🛡️ Context Manager Best Practices
# Always handle cleanup in __exit__ or finally
@contextmanager
def resource_manager():
resource = acquire_resource()
try:
yield resource
finally:
# Cleanup always happens
release_resource(resource)
# Proper exception handling
class SafeContextManager:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
print(f"Exception occurred: {exc_val}")
# Log exception, clean up, etc.
# Return True to suppress exception, False to propagate
return False # Usually want to propagate exceptions
# Nested context managers
with open('file1.txt') as f1:
with open('file2.txt') as f2:
# Both files properly managed
pass
# Or equivalently:
with open('file1.txt') as f1, open('file2.txt') as f2:
passPython⚡ Performance & Optimization
📊 Measuring Performance
import time
import timeit
from functools import wraps
# Simple timing decorator
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "Done"
# Using timeit for small code snippets
execution_time = timeit.timeit(
'sum([1, 2, 3, 4, 5])',
number=1000000
)
print(f"Time: {execution_time:.4f} seconds")
# Compare different approaches
time1 = timeit.timeit(
lambda: [i**2 for i in range(1000)],
number=1000
)
time2 = timeit.timeit(
lambda: list(map(lambda x: x**2, range(1000))),
number=1000
)
print(f"List comprehension: {time1:.4f}s")
print(f"Map function: {time2:.4f}s")Python🚀 Optimization Techniques
List vs Generator Performance
# Memory efficient - use generators for large datasets
def fibonacci_list(n):
"""Returns list of first n Fibonacci numbers (memory intensive)"""
fib = []
a, b = 0, 1
for _ in range(n):
fib.append(a)
a, b = b, a + b
return fib
def fibonacci_generator(n):
"""Yields first n Fibonacci numbers (memory efficient)"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# For large n, generator uses constant memory
for fib_num in fibonacci_generator(1000000):
if fib_num > 1000:
breakPythonString Concatenation Optimization
# Inefficient - creates new string each time
def slow_concat(strings):
result = ""
for s in strings:
result += s # Creates new string object each time
return result
# Efficient - join operation
def fast_concat(strings):
return "".join(strings)
# For formatting
def format_data(items):
# Slow
result = ""
for item in items:
result += f"Item: {item}\n"
# Fast
result = "\n".join(f"Item: {item}" for item in items)
return resultPythonDictionary vs List for Lookups
# Efficient lookups with sets/dicts (O(1) average)
valid_ids = {1, 2, 3, 4, 5, 100, 200, 300} # Set for membership testing
user_data = {1: "Alice", 2: "Bob", 3: "Charlie"} # Dict for key-value lookup
def is_valid_user(user_id):
return user_id in valid_ids # O(1) average
# Inefficient with lists (O(n))
valid_ids_list = [1, 2, 3, 4, 5, 100, 200, 300]
def is_valid_user_slow(user_id):
return user_id in valid_ids_list # O(n) - scans entire listPython🔧 Built-in Performance Tools
# collections.Counter for counting
from collections import Counter
import string
# Efficient counting
def count_letters_fast(text):
return Counter(text.lower())
# Less efficient
def count_letters_slow(text):
counts = {}
for char in text.lower():
if char in counts:
counts[char] += 1
else:
counts[char] = 1
return counts
# Use appropriate data structures
from collections import deque
# Efficient queue operations
queue = deque()
queue.append(1) # O(1)
queue.appendleft(0) # O(1)
queue.pop() # O(1)
queue.popleft() # O(1)
# Inefficient with lists
queue_list = []
queue_list.append(1) # O(1)
queue_list.insert(0, 0) # O(n) - shifts all elements
queue_list.pop() # O(1)
queue_list.pop(0) # O(n) - shifts all elementsPython🧮 Algorithm Optimization
# Memoization for expensive recursive functions
from functools import lru_cache
@lru_cache(maxsize=None) # Cache all results
def fibonacci_memo(n):
if n < 2:
return n
return fibonacci_memo(n-1) + fibonacci_memo(n-2)
# Manual memoization
def memoize(func):
cache = {}
@wraps(func)
def wrapper(*args):
if args in cache:
return cache[args]
result = func(*args)
cache[args] = result
return result
return wrapper
@memoize
def expensive_function(n):
# Simulate expensive computation
time.sleep(0.1)
return n ** 2
# Use list comprehensions instead of loops when possible
# Fast
squares = [x**2 for x in range(1000)]
# Slower
squares = []
for x in range(1000):
squares.append(x**2)
# Use built-in functions (implemented in C)
numbers = list(range(1000000))
# Fast - built-in sum
total = sum(numbers)
# Slower - manual loop
total = 0
for num in numbers:
total += numPython🔍 Profiling Code
import cProfile
import pstats
def profile_function():
# Code to profile
numbers = [i**2 for i in range(100000)]
return sum(numbers)
# Profile with cProfile
cProfile.run('profile_function()', 'profile_stats')
# Analyze results
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative')
stats.print_stats(10) # Top 10 functions by cumulative time
# Line-by-line profiling (requires line_profiler package)
# pip install line_profiler
# @profile # Uncomment when using line_profiler
def detailed_function():
x = [i for i in range(1000)]
y = [i**2 for i in x]
z = sum(y)
return z
# Run with: kernprof -l -v script.pyPython🧪 Testing Basics
✅ unittest (Built-in Testing Framework)
import unittest
class MathOperations:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
class TestMathOperations(unittest.TestCase):
def setUp(self):
"""Run before each test method"""
self.math_ops = MathOperations()
def tearDown(self):
"""Run after each test method"""
pass
def test_add_positive_numbers(self):
result = self.math_ops.add(2, 3)
self.assertEqual(result, 5)
def test_add_negative_numbers(self):
result = self.math_ops.add(-1, -1)
self.assertEqual(result, -2)
def test_divide_normal(self):
result = self.math_ops.divide(10, 2)
self.assertEqual(result, 5.0)
def test_divide_by_zero(self):
with self.assertRaises(ValueError):
self.math_ops.divide(10, 0)
def test_divide_with_message(self):
with self.assertRaisesRegex(ValueError, "Cannot divide by zero"):
self.math_ops.divide(5, 0)
# Run tests
if __name__ == '__main__':
unittest.main()Python🔧 Common unittest Assertions
import unittest
class TestAssertions(unittest.TestCase):
def test_equality(self):
self.assertEqual(1 + 1, 2)
self.assertNotEqual(1, 2)
self.assertAlmostEqual(0.1 + 0.2, 0.3, places=7)
def test_truth_values(self):
self.assertTrue(True)
self.assertFalse(False)
self.assertIsNone(None)
self.assertIsNotNone("something")
def test_membership(self):
self.assertIn('a', 'abc')
self.assertNotIn('x', 'abc')
def test_collections(self):
list1 = [1, 2, 3]
list2 = [1, 2, 3]
self.assertListEqual(list1, list2)
self.assertCountEqual([1, 2, 3], [3, 2, 1]) # Order doesn't matter
def test_types(self):
self.assertIsInstance(42, int)
self.assertIsInstance("hello", str)
def test_regex(self):
self.assertRegex("hello123", r"\w+\d+")Python🎭 Mocking and Test Doubles
import unittest
from unittest.mock import Mock, patch, MagicMock
# Example function that makes external calls
def get_user_data(user_id):
# Simulates API call
import requests
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json()
def process_user(user_id):
user_data = get_user_data(user_id)
return f"Hello, {user_data['name']}!"
class TestMocking(unittest.TestCase):
@patch('requests.get')
def test_get_user_data(self, mock_get):
# Setup mock response
mock_response = Mock()
mock_response.json.return_value = {'name': 'Alice', 'id': 123}
mock_get.return_value = mock_response
# Test the function
result = get_user_data(123)
# Assertions
self.assertEqual(result['name'], 'Alice')
mock_get.assert_called_once_with("https://api.example.com/users/123")
@patch('__main__.get_user_data') # Patch in the module where it's used
def test_process_user(self, mock_get_user_data):
# Setup mock
mock_get_user_data.return_value = {'name': 'Bob', 'id': 456}
# Test
result = process_user(456)
# Assertions
self.assertEqual(result, "Hello, Bob!")
mock_get_user_data.assert_called_once_with(456)
def test_with_mock_object(self):
# Create mock objects
mock_database = Mock()
mock_database.get_user.return_value = {'name': 'Charlie'}
# Test code that uses the mock
user = mock_database.get_user(789)
self.assertEqual(user['name'], 'Charlie')
# Verify interactions
mock_database.get_user.assert_called_with(789)Python🎯 pytest (Popular Third-party Framework)
# pip install pytest
import pytest
# Simple test functions (no classes needed)
def test_addition():
assert 1 + 1 == 2
def test_string_operations():
text = "hello world"
assert "world" in text
assert text.startswith("hello")
assert len(text) == 11
# Parameterized tests
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(0, 0, 0),
(-1, 1, 0),
(10, -5, 5)
])
def test_addition_parametrized(a, b, expected):
assert a + b == expected
# Fixtures for setup/teardown
@pytest.fixture
def sample_data():
"""Provides test data for multiple tests"""
return [1, 2, 3, 4, 5]
def test_with_fixture(sample_data):
assert len(sample_data) == 5
assert sum(sample_data) == 15
# Exception testing
def test_division_by_zero():
with pytest.raises(ZeroDivisionError):
result = 1 / 0
def test_exception_message():
with pytest.raises(ValueError, match="invalid literal"):
int("not_a_number")
# Temporary files and directories
def test_file_operations(tmp_path):
# tmp_path is a pytest fixture that provides temporary directory
test_file = tmp_path / "test.txt"
test_file.write_text("Hello, World!")
content = test_file.read_text()
assert content == "Hello, World!"
# Skipping tests
@pytest.mark.skip(reason="Not implemented yet")
def test_future_feature():
pass
@pytest.mark.skipif(sys.platform == "win32", reason="Unix only")
def test_unix_specific():
passPython🧪 Test-Driven Development (TDD) Example
# Step 1: Write failing test
import unittest
class TestCalculator(unittest.TestCase):
def test_add(self):
calc = Calculator()
result = calc.add(2, 3)
self.assertEqual(result, 5)
# Step 2: Write minimal code to pass
class Calculator:
def add(self, a, b):
return a + b
# Step 3: Refactor and add more tests
class TestCalculatorExtended(unittest.TestCase):
def setUp(self):
self.calc = Calculator()
def test_add_positive(self):
self.assertEqual(self.calc.add(2, 3), 5)
def test_add_negative(self):
self.assertEqual(self.calc.add(-1, -1), -2)
def test_add_zero(self):
self.assertEqual(self.calc.add(5, 0), 5)
def test_subtract(self):
self.assertEqual(self.calc.subtract(5, 3), 2)
def test_multiply(self):
self.assertEqual(self.calc.multiply(3, 4), 12)
def test_divide(self):
self.assertEqual(self.calc.divide(10, 2), 5)
def test_divide_by_zero(self):
with self.assertRaises(ValueError):
self.calc.divide(10, 0)
# Enhanced Calculator implementation
class Calculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
def multiply(self, a, b):
return a * b
def divide(self, a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / bPython📊 Test Coverage
# Install coverage: pip install coverage
# Run tests with coverage
# coverage run -m pytest tests/
# coverage report
# coverage html # Creates HTML report
# Example of testing coverage
def fibonacci(n):
"""Calculate nth Fibonacci number"""
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
class TestFibonacci(unittest.TestCase):
def test_fibonacci_zero(self):
self.assertEqual(fibonacci(0), 0)
def test_fibonacci_one(self):
self.assertEqual(fibonacci(1), 1)
def test_fibonacci_positive(self):
self.assertEqual(fibonacci(5), 5)
self.assertEqual(fibonacci(7), 13)
def test_fibonacci_negative(self):
self.assertEqual(fibonacci(-1), 0)
# This test suite provides 100% code coveragePython🔢 Data Structures & Algorithms
📊 Array/List Operations & Complexity
| Operation | Syntax | Time Complexity | Space Complexity | Example |
|---|---|---|---|---|
| Access | arr[i] | O(1) | O(1) | nums[5] |
| Search | item in arr | O(n) | O(1) | 5 in [1,2,3,4,5] |
| Insertion (end) | arr.append(item) | O(1) amortized | O(1) | nums.append(6) |
| Insertion (beginning) | arr.insert(0, item) | O(n) | O(1) | nums.insert(0, 0) |
| Insertion (middle) | arr.insert(i, item) | O(n) | O(1) | nums.insert(2, 10) |
| Deletion (end) | arr.pop() | O(1) | O(1) | nums.pop() |
| Deletion (beginning) | arr.pop(0) | O(n) | O(1) | nums.pop(0) |
| Deletion (middle) | arr.pop(i) | O(n) | O(1) | nums.pop(2) |
| Sort | arr.sort() | O(n log n) | O(1) | nums.sort() |
| Reverse | arr.reverse() | O(n) | O(1) | nums.reverse() |
🗂️ Dictionary/Hash Table Operations
| Operation | Syntax | Average Time | Worst Time | Example |
|---|---|---|---|---|
| Access | dict[key] | O(1) | O(n) | ages['Alice'] |
| Search | key in dict | O(1) | O(n) | 'Alice' in ages |
| Insertion | dict[key] = value | O(1) | O(n) | ages['Bob'] = 25 |
| Deletion | del dict[key] | O(1) | O(n) | del ages['Alice'] |
| Get keys | dict.keys() | O(1) | O(1) | ages.keys() |
| Get values | dict.values() | O(1) | O(1) | ages.values() |
| Get items | dict.items() | O(1) | O(1) | ages.items() |
🔸 Set Operations & Complexity
| Operation | Syntax | Time Complexity | Example |
|---|---|---|---|
| Add | set.add(item) | O(1) average | s.add(5) |
| Remove | set.remove(item) | O(1) average | s.remove(5) |
| Search | item in set | O(1) average | 5 in s |
| Union | `set1 \ | set2` | O(len(s1) + len(s2)) |
| Intersection | set1 & set2 | O(min(len(s1), len(s2))) | s1 & s2 |
| Difference | set1 - set2 | O(len(s1)) | s1 - s2 |
| Symmetric Diff | set1 ^ set2 | O(len(s1) + len(s2)) | s1 ^ s2 |
🌲 Tree Data Structures Implementation
Binary Tree Node
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = rightPythonTree Traversal Algorithms
| Algorithm | Implementation | Time | Space | Use Case |
|---|---|---|---|---|
| Preorder | Root → Left → Right | O(n) | O(h) | Copy tree structure |
| Inorder | Left → Root → Right | O(n) | O(h) | Get sorted order (BST) |
| Postorder | Left → Right → Root | O(n) | O(h) | Delete nodes safely |
| Level Order | BFS using queue | O(n) | O(w) | Level-by-level processing |
# Tree Traversal Implementations
def preorder(root):
if not root: return []
return [root.val] + preorder(root.left) + preorder(root.right)
def inorder(root):
if not root: return []
return inorder(root.left) + [root.val] + inorder(root.right)
def postorder(root):
if not root: return []
return postorder(root.left) + postorder(root.right) + [root.val]
def level_order(root):
if not root: return []
from collections import deque
queue, result = deque([root]), []
while queue:
node = queue.popleft()
result.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return resultPython📚 Stack & Queue Operations
Stack (LIFO) – Using List
| Operation | Syntax | Time | Space | Example |
|---|---|---|---|---|
| Push | stack.append(item) | O(1) | O(1) | stack.append(5) |
| Pop | stack.pop() | O(1) | O(1) | item = stack.pop() |
| Top/Peek | stack[-1] | O(1) | O(1) | top = stack[-1] |
| Is Empty | len(stack) == 0 | O(1) | O(1) | not stack |
| Size | len(stack) | O(1) | O(1) | len(stack) |
Queue (FIFO) – Using collections.deque
| Operation | Syntax | Time | Space | Example |
|---|---|---|---|---|
| Enqueue | queue.append(item) | O(1) | O(1) | queue.append(5) |
| Dequeue | queue.popleft() | O(1) | O(1) | item = queue.popleft() |
| Front | queue[0] | O(1) | O(1) | front = queue[0] |
| Is Empty | len(queue) == 0 | O(1) | O(1) | not queue |
| Size | len(queue) | O(1) | O(1) | len(queue) |
🔗 Linked List Implementation
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class LinkedList:
def __init__(self):
self.head = None
self.size = 0
def append(self, val): # O(n) time
new_node = ListNode(val)
if not self.head:
self.head = new_node
else:
curr = self.head
while curr.next:
curr = curr.next
curr.next = new_node
self.size += 1
def prepend(self, val): # O(1) time
new_node = ListNode(val)
new_node.next = self.head
self.head = new_node
self.size += 1
def delete(self, val): # O(n) time
if not self.head: return
if self.head.val == val:
self.head = self.head.next
self.size -= 1
return
curr = self.head
while curr.next and curr.next.val != val:
curr = curr.next
if curr.next:
curr.next = curr.next.next
self.size -= 1
def search(self, val): # O(n) time
curr = self.head
while curr:
if curr.val == val:
return True
curr = curr.next
return FalsePython🏔️ Heap Operations (Priority Queue)
| Operation | Syntax | Time Complexity | Example |
|---|---|---|---|
| Create Heap | heapq.heapify(list) | O(n) | heapq.heapify([3,1,4,1,5]) |
| Push | heapq.heappush(heap, item) | O(log n) | heapq.heappush(heap, 2) |
| Pop Min | heapq.heappop(heap) | O(log n) | min_val = heapq.heappop(heap) |
| Peek Min | heap[0] | O(1) | min_val = heap[0] |
| Push-Pop | heapq.heappushpop(heap, item) | O(log n) | heapq.heappushpop(heap, 5) |
| Replace | heapq.heapreplace(heap, item) | O(log n) | heapq.heapreplace(heap, 3) |
| N Largest | heapq.nlargest(n, iterable) | O(n log k) | heapq.nlargest(3, [1,3,5,2,4]) |
| N Smallest | heapq.nsmallest(n, iterable) | O(n log k) | heapq.nsmallest(2, [1,3,5,2,4]) |
🔍 Search Algorithms
Linear Search
def linear_search(arr, target):
"""Time: O(n), Space: O(1)"""
for i, val in enumerate(arr):
if val == target:
return i
return -1PythonBinary Search
def binary_search(arr, target):
"""Time: O(log n), Space: O(1) - Array must be sorted"""
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
def binary_search_recursive(arr, target, left=0, right=None):
"""Time: O(log n), Space: O(log n) due to recursion"""
if right is None:
right = len(arr) - 1
if left > right:
return -1
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
return binary_search_recursive(arr, target, mid + 1, right)
else:
return binary_search_recursive(arr, target, left, mid - 1)Python📊 Sorting Algorithms
| Algorithm | Best Case | Average Case | Worst Case | Space | Stable | In-place |
|---|---|---|---|---|---|---|
| Bubble Sort | O(n) | O(n²) | O(n²) | O(1) | Yes | Yes |
| Selection Sort | O(n²) | O(n²) | O(n²) | O(1) | No | Yes |
| Insertion Sort | O(n) | O(n²) | O(n²) | O(1) | Yes | Yes |
| Merge Sort | O(n log n) | O(n log n) | O(n log n) | O(n) | Yes | No |
| Quick Sort | O(n log n) | O(n log n) | O(n²) | O(log n) | No | Yes |
| Heap Sort | O(n log n) | O(n log n) | O(n log n) | O(1) | No | Yes |
| Tim Sort (Python default) | O(n) | O(n log n) | O(n log n) | O(n) | Yes | No |
Sorting Implementations
def bubble_sort(arr):
"""Time: O(n²), Space: O(1)"""
n = len(arr)
for i in range(n):
swapped = False
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
if not swapped:
break
return arr
def merge_sort(arr):
"""Time: O(n log n), Space: O(n)"""
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
def quick_sort(arr):
"""Time: O(n log n) avg, O(n²) worst, Space: O(log n)"""
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)Python🌐 Graph Algorithms
Graph Representation
# Adjacency List
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}
# Adjacency Matrix
graph_matrix = [
[0, 1, 1, 0, 0, 0], # A
[1, 0, 0, 1, 1, 0], # B
[1, 0, 0, 0, 0, 1], # C
[0, 1, 0, 0, 0, 0], # D
[0, 1, 0, 0, 0, 1], # E
[0, 0, 1, 0, 1, 0] # F
]PythonGraph Traversal
| Algorithm | Data Structure | Time | Space | Use Case |
|---|---|---|---|---|
| DFS | Stack/Recursion | O(V + E) | O(V) | Path finding, cycle detection |
| BFS | Queue | O(V + E) | O(V) | Shortest path, level-order |
def dfs(graph, start, visited=None):
"""Depth-First Search"""
if visited is None:
visited = set()
visited.add(start)
result = [start]
for neighbor in graph[start]:
if neighbor not in visited:
result.extend(dfs(graph, neighbor, visited))
return result
def bfs(graph, start):
"""Breadth-First Search"""
from collections import deque
visited = set([start])
queue = deque([start])
result = []
while queue:
node = queue.popleft()
result.append(node)
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
return resultPython🔄 Dynamic Programming Patterns
Common DP Problems & Solutions
| Problem | Recurrence | Time | Space | Example |
|---|---|---|---|---|
| Fibonacci | dp[i] = dp[i-1] + dp[i-2] | O(n) | O(1) | fib(5) = 5 |
| Climbing Stairs | dp[i] = dp[i-1] + dp[i-2] | O(n) | O(1) | Ways to climb n steps |
| Coin Change | dp[i] = min(dp[i-coin] + 1) | O(n*m) | O(n) | Min coins for amount |
| Longest Common Subsequence | dp[i][j] = dp[i-1][j-1] + 1 | O(n*m) | O(n*m) | LCS of two strings |
| 0/1 Knapsack | dp[i][w] = max(dp[i-1][w], dp[i-1][w-weight[i]] + value[i]) | O(n*W) | O(n*W) | Max value in knapsack |
# Fibonacci with memoization
def fibonacci_dp(n, memo={}):
if n in memo:
return memo[n]
if n <= 1:
return n
memo[n] = fibonacci_dp(n-1, memo) + fibonacci_dp(n-2, memo)
return memo[n]
# Coin Change Problem
def coin_change(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for i in range(coin, amount + 1):
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
# Longest Common Subsequence
def lcs(text1, text2):
m, n = len(text1), len(text2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if text1[i-1] == text2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]Python🎯 Two Pointers Technique
| Pattern | Use Case | Time | Example |
|---|---|---|---|
| Opposite Ends | Palindrome, Two Sum (sorted) | O(n) | left=0, right=len(arr)-1 |
| Same Direction | Remove duplicates, sliding window | O(n) | slow=0, fast=1 |
| Fast & Slow | Cycle detection, middle element | O(n) | Floyd’s algorithm |
def two_sum_sorted(arr, target):
"""Two pointers for sorted array"""
left, right = 0, len(arr) - 1
while left < right:
current_sum = arr[left] + arr[right]
if current_sum == target:
return [left, right]
elif current_sum < target:
left += 1
else:
right -= 1
return []
def is_palindrome(s):
"""Check palindrome using two pointers"""
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
def find_cycle(head):
"""Floyd's cycle detection algorithm"""
if not head or not head.next:
return None
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
else:
return None # No cycle
# Find cycle start
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slowPython🪟 Sliding Window Technique
| Pattern | Use Case | Time | Space | Example |
|---|---|---|---|---|
| Fixed Size | Max sum of k elements | O(n) | O(1) | Moving average |
| Variable Size | Longest substring | O(n) | O(k) | Min window substring |
def max_sum_subarray(arr, k):
"""Fixed sliding window"""
if len(arr) < k:
return 0
# Initial window sum
window_sum = sum(arr[:k])
max_sum = window_sum
# Slide the window
for i in range(k, len(arr)):
window_sum = window_sum - arr[i-k] + arr[i]
max_sum = max(max_sum, window_sum)
return max_sum
def longest_substring_without_repeating(s):
"""Variable sliding window"""
char_index = {}
left = max_length = 0
for right, char in enumerate(s):
if char in char_index and char_index[char] >= left:
left = char_index[char] + 1
char_index[char] = right
max_length = max(max_length, right - left + 1)
return max_lengthPython🔢 Bit Manipulation
| Operation | Syntax | Example | Use Case |
|---|---|---|---|
| AND | a & b | 5 & 3 = 1 | Check if bit is set |
| OR | `a \ | b` | `5 \ |
| XOR | a ^ b | 5 ^ 3 = 6 | Toggle bit, find unique |
| NOT | ~a | ~5 = -6 | Flip all bits |
| Left Shift | a << b | 5 << 1 = 10 | Multiply by 2^b |
| Right Shift | a >> b | 5 >> 1 = 2 | Divide by 2^b |
def count_set_bits(n):
"""Count number of 1s in binary representation"""
count = 0
while n:
count += n & 1
n >>= 1
return count
def is_power_of_two(n):
"""Check if n is power of 2"""
return n > 0 and (n & (n - 1)) == 0
def find_single_number(nums):
"""Find the number that appears once (others appear twice)"""
result = 0
for num in nums:
result ^= num
return result
def swap_numbers(a, b):
"""Swap without temporary variable"""
a = a ^ b
b = a ^ b
a = a ^ b
return a, bPython📈 Algorithm Complexity Cheat Sheet
Time Complexity Hierarchy (Best to Worst)
- O(1) – Constant: Hash table access, array indexing
- O(log n) – Logarithmic: Binary search, balanced tree operations
- O(n) – Linear: Linear search, simple loops
- O(n log n) – Linearithmic: Efficient sorting (merge, heap)
- O(n²) – Quadratic: Nested loops, simple sorting (bubble, selection)
- O(n³) – Cubic: Triple nested loops
- O(2ⁿ) – Exponential: Recursive Fibonacci, subset generation
- O(n!) – Factorial: Permutation generation
Space Complexity Patterns
- O(1) – In-place algorithms
- O(log n) – Recursive algorithms with balanced recursion
- O(n) – Single array/list storage
- O(n²) – 2D matrix storage
🎲 Common Algorithmic Patterns
| Pattern | When to Use | Time | Examples |
|---|---|---|---|
| Divide & Conquer | Problem can be split | O(n log n) | Merge sort, binary search |
| Greedy | Local optimal → global optimal | Varies | Dijkstra, activity selection |
| Backtracking | Explore all possibilities | O(2ⁿ) typically | N-Queens, sudoku solver |
| Dynamic Programming | Overlapping subproblems | O(n) to O(n³) | Fibonacci, knapsack |
| Two Pointers | Search pairs in sorted data | O(n) | Two sum, palindrome |
| Sliding Window | Contiguous subarray problems | O(n) | Max subarray, substring |
| BFS/DFS | Graph/tree traversal | O(V + E) | Shortest path, connectivity |
This cheat sheet covers the most commonly used Python features. For more advanced topics, refer to the official Python documentation.
Discover more from Altgr Blog
Subscribe to get the latest posts sent to your email.
