Complete guide covering 50+ Python topics with professional best practices
Table of Contents
Professional Python Features
1. Type Hints & Annotations (PEP 484)
from typing import List, Dict, Optional, Union, Callable, TypeVar, Generic
from collections.abc import Iterable
# Basic type hints
def greet(name: str, age: int) -> str:
return f"Hello {name}, age {age}"
# Optional types
def find_user(user_id: int) -> Optional[Dict[str, str]]:
return {"name": "John"} if user_id > 0 else None
# Union types
def process_data(data: Union[str, List[str]]) -> List[str]:
return [data] if isinstance(data, str) else data
# Callable types
def apply_function(func: Callable[[int], int], value: int) -> int:
return func(value)
# Generic types
T = TypeVar('T')
def first_element(items: List[T]) -> Optional[T]:
return items[0] if items else None
# Type aliases
UserId = int
UserData = Dict[str, Union[str, int]]
def get_user(user_id: UserId) -> UserData:
return {"name": "John", "age": 30}Python2. Dataclasses (Python 3.7+)
from dataclasses import dataclass, field, asdict, astuple
from typing import List
from datetime import datetime
@dataclass
class User:
name: str
age: int
email: str
active: bool = True
created_at: datetime = field(default_factory=datetime.now)
tags: List[str] = field(default_factory=list)
def __post_init__(self):
"""Validation after initialization"""
if self.age < 0:
raise ValueError("Age cannot be negative")
@property
def is_adult(self) -> bool:
return self.age >= 18
# Usage
user = User(name="John", age=30, email="john@example.com")
user_dict = asdict(user)
user_tuple = astuple(user)
# Frozen dataclass (immutable)
@dataclass(frozen=True)
class Point:
x: float
y: floatPython3. Context Managers & Decorators
from contextlib import contextmanager
from functools import wraps
import time
from typing import Any, Callable
# Custom context manager (class-based)
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.elapsed = time.time() - self.start
print(f"Elapsed: {self.elapsed:.2f}s")
return False # Don't suppress exceptions
# Context manager (function-based)
@contextmanager
def timing_context(name: str):
start = time.time()
try:
yield
finally:
print(f"{name}: {time.time() - start:.2f}s")
# Usage
with timing_context("Operation"):
time.sleep(1)
# Decorator with arguments
def retry(max_attempts: int = 3, delay: float = 1.0):
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs) -> Any:
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
time.sleep(delay)
return None
return wrapper
return decorator
@retry(max_attempts=3, delay=0.5)
def fetch_data():
# Potentially failing operation
pass
# Cache decorator
from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_computation(n: int) -> int:
return sum(range(n))Python4. Generators & Iterators
from typing import Iterator, Generator
from itertools import islice, chain, cycle, groupby
# Generator function
def fibonacci() -> Generator[int, None, None]:
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Generator expression
squares_gen = (x**2 for x in range(1000000)) # Memory efficient
# Custom iterator
class RangeIterator:
def __init__(self, start: int, end: int):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self) -> int:
if self.current >= self.end:
raise StopIteration
self.current += 1
return self.current - 1
# Useful itertools patterns
from itertools import islice, chain, groupby
# Take first n items
first_10_fibs = list(islice(fibonacci(), 10))
# Chain multiple iterables
combined = chain([1, 2], [3, 4], [5, 6])
# Group consecutive items
data = [1, 1, 2, 2, 2, 3, 3]
grouped = {k: list(g) for k, g in groupby(data)}Python5. Async/Await (Asyncio)
import asyncio
from typing import List
import aiohttp
import aiofiles
# Async function
async def fetch_url(url: str) -> str:
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
# Concurrent async operations
async def fetch_multiple(urls: List[str]) -> List[str]:
tasks = [fetch_url(url) for url in urls]
return await asyncio.gather(*tasks)
# Async file operations
async def read_file_async(filepath: str) -> str:
async with aiofiles.open(filepath, 'r') as f:
return await f.read()
# Async context manager
class AsyncResource:
async def __aenter__(self):
await self.connect()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
await self.disconnect()
async def connect(self):
await asyncio.sleep(0.1)
async def disconnect(self):
await asyncio.sleep(0.1)
# Run async code
async def main():
result = await fetch_url("https://example.com")
results = await fetch_multiple(["url1", "url2"])
# Execute
# asyncio.run(main()) # Python 3.7+Python6. Property Decorators & Descriptors
class Temperature:
def __init__(self, celsius: float = 0):
self._celsius = celsius
@property
def celsius(self) -> float:
"""Getter"""
return self._celsius
@celsius.setter
def celsius(self, value: float) -> None:
"""Setter with validation"""
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
@property
def fahrenheit(self) -> float:
"""Computed property"""
return self._celsius * 9/5 + 32
@fahrenheit.setter
def fahrenheit(self, value: float) -> None:
self.celsius = (value - 32) * 5/9
# Descriptor protocol
class Validator:
def __init__(self, min_value: float = None, max_value: float = None):
self.min_value = min_value
self.max_value = max_value
def __set_name__(self, owner, name):
self.private_name = f'_{name}'
def __get__(self, obj, objtype=None):
return getattr(obj, self.private_name)
def __set__(self, obj, value):
if self.min_value is not None and value < self.min_value:
raise ValueError(f"Value must be >= {self.min_value}")
if self.max_value is not None and value > self.max_value:
raise ValueError(f"Value must be <= {self.max_value}")
setattr(obj, self.private_name, value)
class Person:
age = Validator(min_value=0, max_value=150)
def __init__(self, age: int):
self.age = age # Uses descriptorPython7. Protocols & Abstract Base Classes
from typing import Protocol
from abc import ABC, abstractmethod
# Protocol (structural subtyping - Python 3.8+)
class Drawable(Protocol):
def draw(self) -> None: ...
def render(obj: Drawable) -> None:
obj.draw() # Any object with draw() method works
# Abstract Base Class
class Animal(ABC):
@abstractmethod
def make_sound(self) -> str:
"""Must be implemented by subclass"""
pass
@abstractmethod
def move(self) -> None:
"""Must be implemented by subclass"""
pass
def describe(self) -> str:
"""Concrete method"""
return f"I am an animal that says {self.make_sound()}"
class Dog(Animal):
def make_sound(self) -> str:
return "Woof!"
def move(self) -> None:
print("Running on four legs")Python8. Enums & Literal Types
from enum import Enum, auto, IntEnum, Flag
from typing import Literal
# Basic Enum
class Status(Enum):
PENDING = "pending"
PROCESSING = "processing"
COMPLETED = "completed"
FAILED = "failed"
# Auto values
class Color(Enum):
RED = auto()
GREEN = auto()
BLUE = auto()
# IntEnum for numeric values
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
# Flag for bit operations
class Permission(Flag):
READ = auto()
WRITE = auto()
EXECUTE = auto()
# Usage
status = Status.PENDING
perm = Permission.READ | Permission.WRITE
# Literal types (Python 3.8+)
def process_mode(mode: Literal["read", "write", "append"]) -> None:
passPython9. Advanced Error Handling
from typing import Optional, Union
import logging
from contextlib import suppress
# Custom exceptions
class ValidationError(Exception):
"""Raised when validation fails"""
def __init__(self, field: str, message: str):
self.field = field
self.message = message
super().__init__(f"{field}: {message}")
class DatabaseError(Exception):
"""Database related errors"""
pass
# Exception chaining
def load_data(filename: str):
try:
with open(filename) as f:
return f.read()
except FileNotFoundError as e:
raise DatabaseError(f"Cannot load {filename}") from e
# Try-except-else-finally
def process_file(filename: str) -> Optional[str]:
try:
file = open(filename, 'r')
except FileNotFoundError:
logging.error(f"File {filename} not found")
return None
else:
# Only runs if no exception
data = file.read()
return data
finally:
# Always runs
if 'file' in locals():
file.close()
# Suppress exceptions
with suppress(FileNotFoundError, PermissionError):
os.remove('file.txt')
# Exception groups (Python 3.11+)
# try:
# raise ExceptionGroup("multiple errors", [
# ValueError("bad value"),
# TypeError("bad type")
# ])
# except* ValueError as e:
# print("Caught ValueError")
# except* TypeError as e:
# print("Caught TypeError")Python10. Logging Best Practices
import logging
from logging.handlers import RotatingFileHandler
import sys
# Configure logging
def setup_logging(log_file: str = 'app.log', level: int = logging.INFO):
# Create formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# File handler with rotation
file_handler = RotatingFileHandler(
log_file, maxBytes=10*1024*1024, backupCount=5
)
file_handler.setFormatter(formatter)
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(level)
root_logger.addHandler(file_handler)
root_logger.addHandler(console_handler)
# Usage
logger = logging.getLogger(__name__)
logger.info("Application started")
logger.warning("Warning message")
logger.error("Error occurred", exc_info=True) # Include traceback
# Structured logging
logger.info("User login", extra={
'user_id': 123,
'ip_address': '192.168.1.1',
'action': 'login'
})Python11. Configuration Management
from pathlib import Path
from typing import Any
import os
from dataclasses import dataclass
import json
import yaml # pip install pyyaml
from dotenv import load_dotenv # pip install python-dotenv
# Environment variables
load_dotenv() # Load from .env file
@dataclass
class Config:
"""Application configuration"""
DEBUG: bool = os.getenv('DEBUG', 'False') == 'True'
DATABASE_URL: str = os.getenv('DATABASE_URL', 'sqlite:///app.db')
SECRET_KEY: str = os.getenv('SECRET_KEY', 'default-secret-key')
API_KEY: str = os.getenv('API_KEY', '')
MAX_CONNECTIONS: int = int(os.getenv('MAX_CONNECTIONS', '10'))
@classmethod
def from_yaml(cls, filepath: Path) -> 'Config':
with open(filepath) as f:
data = yaml.safe_load(f)
return cls(**data)
@classmethod
def from_json(cls, filepath: Path) -> 'Config':
with open(filepath) as f:
data = json.load(f)
return cls(**data)
# Singleton pattern for config
class ConfigSingleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance.config = Config()
return cls._instance
# Usage
config = ConfigSingleton().configPython12. Testing Best Practices
import unittest
from unittest.mock import Mock, patch, MagicMock
import pytest # pip install pytest
from typing import Generator
# Pytest fixtures
@pytest.fixture
def sample_data() -> dict:
return {"name": "John", "age": 30}
@pytest.fixture
def database_connection():
"""Setup and teardown"""
conn = create_connection()
yield conn
conn.close()
# Parametrized tests
@pytest.mark.parametrize("input,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def test_double(input: int, expected: int):
assert double(input) == expected
# Mocking
def test_api_call():
with patch('requests.get') as mock_get:
mock_get.return_value.json.return_value = {"data": "test"}
result = fetch_data()
assert result == {"data": "test"}
mock_get.assert_called_once()
# Unittest class
class TestCalculator(unittest.TestCase):
def setUp(self):
self.calc = Calculator()
def test_add(self):
self.assertEqual(self.calc.add(2, 3), 5)
def test_divide_by_zero(self):
with self.assertRaises(ValueError):
self.calc.divide(10, 0)
def tearDown(self):
pass
# Test coverage: pytest --cov=myapp tests/PythonCore Topics
01 – Batch File Processing
from pathlib import Path
from typing import Iterator, Callable
import logging
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import shutil
# Modern Path approach (preferred over os.path)
def process_files_modern(directory: Path, pattern: str = '*.txt') -> Iterator[Path]:
"""Process files using pathlib (recommended)"""
for file in directory.rglob(pattern): # Recursive glob
if file.is_file():
yield file
# Batch processing with error handling
def batch_process(directory: Path, processor: Callable[[Path], None]) -> dict:
"""Process files with comprehensive error handling"""
results = {'success': 0, 'failed': 0, 'errors': []}
for file in directory.glob('*.txt'):
try:
processor(file)
results['success'] += 1
except Exception as e:
results['failed'] += 1
results['errors'].append((file.name, str(e)))
logging.error(f"Failed to process {file}: {e}")
return results
# Parallel file processing
def parallel_process_files(files: list[Path], num_workers: int = 4) -> list:
"""Process files in parallel using ThreadPoolExecutor"""
def process_file(file: Path) -> str:
with open(file, 'r', encoding='utf-8') as f:
return f.read().upper() # Example processing
with ThreadPoolExecutor(max_workers=num_workers) as executor:
results = list(executor.map(process_file, files))
return results
# Safe batch rename with rollback capability
def batch_rename_safe(directory: Path, name_func: Callable[[Path], str]) -> list:
"""Rename files with ability to rollback"""
renamed_files = []
try:
for file in directory.glob('*.jpg'):
new_name = name_func(file)
new_path = file.parent / new_name
# Check if target exists
if new_path.exists():
logging.warning(f"Skipping {file.name}: target exists")
continue
file.rename(new_path)
renamed_files.append((new_path, file))
except Exception as e:
# Rollback on error
for new_path, original in renamed_files:
new_path.rename(original)
raise
return renamed_files
# Usage examples
def example_usage():
base_dir = Path('folder')
# Process files
results = batch_process(
base_dir,
lambda f: print(f"Processing {f.name}")
)
# Parallel processing
files = list(base_dir.glob('*.txt'))
processed = parallel_process_files(files)
# Safe rename with custom function
renamed = batch_rename_safe(
base_dir,
lambda f: f"image_{f.stem}_{f.stat().st_size}.jpg"
)Python02 – String Manipulation
# Common string methods
text = " Hello World "
text.strip() # Remove whitespace
text.lower() # Lowercase
text.upper() # Uppercase
text.replace('o', '0') # Replace characters
text.split() # Split into list
'-'.join(['a', 'b']) # Join list to string
# String formatting
name = "John"
age = 30
f"Name: {name}, Age: {age}" # f-strings
"Name: {}, Age: {}".format(name, age) # .format()
"Name: %s, Age: %d" % (name, age) # % operator
# String slicing
text = "Python"
text[0:3] # "Pyt"
text[::-1] # Reverse: "nohtyP"Python03 – Manipulating JSON Data
import json
# Reading JSON
with open('data.json', 'r') as f:
data = json.load(f)
# Writing JSON
with open('data.json', 'w') as f:
json.dump(data, f, indent=4)
# JSON string operations
json_string = json.dumps(data, indent=2)
data = json.loads(json_string)
# Access nested data
value = data['key']['nested_key']Python04 – Converting Between Excel, CSV, JSON
import pandas as pd
# Excel to CSV
df = pd.read_excel('file.xlsx')
df.to_csv('file.csv', index=False)
# CSV to JSON
df = pd.read_csv('file.csv')
df.to_json('file.json', orient='records', indent=2)
# JSON to Excel
df = pd.read_json('file.json')
df.to_excel('file.xlsx', index=False)
# Multiple sheets in Excel
with pd.ExcelWriter('output.xlsx') as writer:
df1.to_excel(writer, sheet_name='Sheet1')
df2.to_excel(writer, sheet_name='Sheet2')Python05 – Processing Columns in Excel
import pandas as pd
# Read Excel
df = pd.read_excel('file.xlsx')
# Select columns
df['Column_Name']
df[['Col1', 'Col2']]
# Add new column
df['New_Col'] = df['Col1'] + df['Col2']
# Apply function to column
df['Col1'] = df['Col1'].apply(lambda x: x * 2)
# Filter rows
df[df['Age'] > 25]
# Group and aggregate
df.groupby('Category')['Sales'].sum()
# Drop columns
df.drop(['Col1', 'Col2'], axis=1, inplace=True)Python06 – Building REST APIs with Flask
from flask import Flask, request, jsonify
app = Flask(__name__)
# GET request
@app.route('/api/items', methods=['GET'])
def get_items():
return jsonify({'items': [1, 2, 3]})
# POST request
@app.route('/api/items', methods=['POST'])
def create_item():
data = request.get_json()
return jsonify({'created': data}), 201
# PUT request
@app.route('/api/items/<int:id>', methods=['PUT'])
def update_item(id):
data = request.get_json()
return jsonify({'updated': id, 'data': data})
# DELETE request
@app.route('/api/items/<int:id>', methods=['DELETE'])
def delete_item(id):
return jsonify({'deleted': id})
if __name__ == '__main__':
app.run(debug=True)Python07 – Command Line Based Apps
import sys
import argparse
# Using sys.argv
if len(sys.argv) > 1:
filename = sys.argv[1]
# Using argparse
parser = argparse.ArgumentParser(description='Process files')
parser.add_argument('input', help='Input file')
parser.add_argument('-o', '--output', help='Output file')
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
# Example usage
# python script.py input.txt -o output.txt -vPython08 – Using APIs
import requests
# GET request
response = requests.get('https://api.example.com/data')
data = response.json()
# POST request
payload = {'key': 'value'}
response = requests.post('https://api.example.com/data', json=payload)
# With headers
headers = {'Authorization': 'Bearer TOKEN'}
response = requests.get('https://api.example.com/data', headers=headers)
# With parameters
params = {'search': 'python', 'limit': 10}
response = requests.get('https://api.example.com/search', params=params)
# Error handling
try:
response = requests.get('https://api.example.com/data')
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")Python09 – Guessing Games
import random
# Number guessing game
secret = random.randint(1, 100)
attempts = 0
while True:
guess = int(input("Guess (1-100): "))
attempts += 1
if guess < secret:
print("Higher!")
elif guess > secret:
print("Lower!")
else:
print(f"Correct! Attempts: {attempts}")
break
# Random choice
choices = ['rock', 'paper', 'scissors']
computer = random.choice(choices)Python10 – Regular Expressions (Regex)
import re
# Basic patterns
pattern = r'\d+' # One or more digits
pattern = r'[A-Za-z]+' # One or more letters
pattern = r'\w+' # Alphanumeric
pattern = r'\s+' # Whitespace
pattern = r'^start' # Start of string
pattern = r'end$' # End of string
# Common operations
re.search(r'pattern', text) # Find first match
re.findall(r'\d+', text) # Find all matches
re.sub(r'old', 'new', text) # Replace
re.split(r'\s+', text) # Split on pattern
# Groups
match = re.search(r'(\w+)@(\w+)', 'user@example.com')
match.group(1) # 'user'
match.group(2) # 'example'
# Email validation
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
re.match(email_pattern, email)Python11 – SQL Queries
import sqlite3
# Connect to database
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
# CREATE TABLE
cursor.execute('''
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE,
age INTEGER
)
''')
# INSERT
cursor.execute("INSERT INTO users (name, email, age) VALUES (?, ?, ?)",
('John', 'john@example.com', 30))
# SELECT
cursor.execute("SELECT * FROM users WHERE age > ?", (25,))
rows = cursor.fetchall()
# UPDATE
cursor.execute("UPDATE users SET age = ? WHERE name = ?", (31, 'John'))
# DELETE
cursor.execute("DELETE FROM users WHERE id = ?", (1,))
# JOIN
cursor.execute('''
SELECT users.name, orders.product
FROM users
JOIN orders ON users.id = orders.user_id
''')
conn.commit()
conn.close()Python12 – Merging Excel Files with Python
import pandas as pd
from pathlib import Path
# Merge multiple Excel files
files = Path('folder').glob('*.xlsx')
dfs = [pd.read_excel(f) for f in files]
merged_df = pd.concat(dfs, ignore_index=True)
merged_df.to_excel('merged.xlsx', index=False)
# Merge specific sheets
df1 = pd.read_excel('file1.xlsx', sheet_name='Sheet1')
df2 = pd.read_excel('file2.xlsx', sheet_name='Sheet1')
merged = pd.concat([df1, df2], ignore_index=True)
# Merge on columns (like SQL JOIN)
merged = pd.merge(df1, df2, on='ID', how='inner')
# how: 'inner', 'outer', 'left', 'right'Python13 – Analyzing User Input
# Get and validate input
def get_number(prompt):
while True:
try:
return float(input(prompt))
except ValueError:
print("Invalid number. Try again.")
# Multiple choice
def get_choice(options):
while True:
choice = input(f"Choose {options}: ").lower()
if choice in options:
return choice
print("Invalid choice.")
# Yes/No confirmation
def confirm(message):
response = input(f"{message} (y/n): ").lower()
return response in ['y', 'yes']
# Input validation with regex
import re
def get_email():
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
while True:
email = input("Enter email: ")
if re.match(pattern, email):
return email
print("Invalid email.")Python14 – Processing Word Documents with Python
from docx import Document
# Read Word document
doc = Document('file.docx')
# Read paragraphs
for para in doc.paragraphs:
print(para.text)
# Create new document
doc = Document()
doc.add_heading('Title', 0)
doc.add_paragraph('This is a paragraph.')
doc.add_heading('Section', 1)
doc.save('output.docx')
# Add table
table = doc.add_table(rows=3, cols=3)
table.cell(0, 0).text = 'Header 1'
# Formatting
from docx.shared import Pt, RGBColor
para = doc.add_paragraph('Formatted text')
run = para.runs[0]
run.font.size = Pt(14)
run.font.bold = True
run.font.color.rgb = RGBColor(255, 0, 0)Python15 – Processing Text Files
# Read entire file
with open('file.txt', 'r') as f:
content = f.read()
# Read line by line
with open('file.txt', 'r') as f:
for line in f:
print(line.strip())
# Read all lines to list
with open('file.txt', 'r') as f:
lines = f.readlines()
# Write to file
with open('file.txt', 'w') as f:
f.write('Hello\n')
f.write('World\n')
# Append to file
with open('file.txt', 'a') as f:
f.write('New line\n')
# Process large files efficiently
with open('large.txt', 'r') as f:
for line in f:
# Process one line at a time
process(line.strip())Python16 – Utility Web Apps with Streamlit
import streamlit as st
# Basic app
st.title('My App')
st.header('Section Header')
st.subheader('Subsection')
st.text('Simple text')
st.markdown('**Bold** and *italic*')
# Input widgets
name = st.text_input('Enter name:')
age = st.number_input('Enter age:', min_value=0, max_value=120)
choice = st.selectbox('Choose:', ['Option 1', 'Option 2'])
agree = st.checkbox('I agree')
slider_val = st.slider('Select value:', 0, 100)
# Button
if st.button('Click me'):
st.write('Button clicked!')
# File upload
uploaded = st.file_uploader('Upload file', type=['csv', 'txt'])
if uploaded:
content = uploaded.read()
# Display data
st.write(data)
st.dataframe(df)
st.table(df)Python17 – Interactive Streamlit Web Apps
import streamlit as st
# Session state
if 'counter' not in st.session_state:
st.session_state.counter = 0
if st.button('Increment'):
st.session_state.counter += 1
st.write(f"Count: {st.session_state.counter}")
# Forms
with st.form('my_form'):
name = st.text_input('Name')
age = st.number_input('Age')
submitted = st.form_submit_button('Submit')
if submitted:
st.write(f'Hello {name}, age {age}')
# Sidebar
with st.sidebar:
st.header('Settings')
option = st.selectbox('Choose:', ['A', 'B'])
# Columns
col1, col2 = st.columns(2)
with col1:
st.write('Column 1')
with col2:
st.write('Column 2')Python18 – More Interactive Streamlit Web Apps
import streamlit as st
# Tabs
tab1, tab2 = st.tabs(['Tab 1', 'Tab 2'])
with tab1:
st.write('Content 1')
with tab2:
st.write('Content 2')
# Expander
with st.expander('Click to expand'):
st.write('Hidden content')
# Progress bar
import time
progress = st.progress(0)
for i in range(100):
time.sleep(0.01)
progress.progress(i + 1)
# Spinner
with st.spinner('Loading...'):
time.sleep(2)
st.success('Done!')
# Messages
st.success('Success!')
st.error('Error!')
st.warning('Warning!')
st.info('Info!')Python19 – Data Visualization with Streamlit
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
# Line chart
st.line_chart(df)
# Bar chart
st.bar_chart(df)
# Area chart
st.area_chart(df)
# Matplotlib
fig, ax = plt.subplots()
ax.plot(df['x'], df['y'])
st.pyplot(fig)
# Map
df = pd.DataFrame({
'lat': [37.76, 37.77],
'lon': [-122.4, -122.45]
})
st.map(df)
# Plotly
import plotly.express as px
fig = px.scatter(df, x='x', y='y')
st.plotly_chart(fig)Python20 – Polars Data Analysis Library
import polars as pl
# Read data
df = pl.read_csv('file.csv')
df = pl.read_excel('file.xlsx')
# Basic operations
df.head()
df.describe()
df.shape
# Select columns
df.select(['col1', 'col2'])
df.select(pl.col('col1'))
# Filter
df.filter(pl.col('age') > 25)
# Add column
df.with_columns([
(pl.col('price') * 1.1).alias('price_with_tax')
])
# Group by
df.groupby('category').agg([
pl.col('sales').sum().alias('total_sales'),
pl.col('quantity').mean().alias('avg_quantity')
])
# Sort
df.sort('column_name', descending=True)Python21 – Data Analysis and Visualization with Polars
import polars as pl
# Join dataframes
df1.join(df2, on='id', how='inner')
# Pivot
df.pivot(values='sales', index='date', columns='product')
# Window functions
df.with_columns([
pl.col('sales').sum().over('category').alias('category_total')
])
# String operations
df.with_columns([
pl.col('name').str.to_uppercase().alias('upper_name')
])
# Date operations
df.with_columns([
pl.col('date').dt.year().alias('year'),
pl.col('date').dt.month().alias('month')
])
# Export
df.write_csv('output.csv')
df.write_excel('output.xlsx')Python22 – Mobile Apps with Kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
class MyApp(App):
def build(self):
layout = BoxLayout(orientation='vertical')
label = Label(text='Hello World')
button = Button(text='Click Me')
button.bind(on_press=self.on_button_click)
layout.add_widget(label)
layout.add_widget(button)
return layout
def on_button_click(self, instance):
print('Button clicked!')
if __name__ == '__main__':
MyApp().run()Python23 – Extracting Data from USGS API
import requests
# USGS Earthquake API
url = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'
response = requests.get(url)
data = response.json()
# Extract earthquake data
for feature in data['features']:
magnitude = feature['properties']['mag']
place = feature['properties']['place']
time = feature['properties']['time']
coords = feature['geometry']['coordinates']
print(f"M{magnitude} - {place}")
# Filter by magnitude
strong_quakes = [f for f in data['features']
if f['properties']['mag'] > 5.0]Python24 – PyQt Desktop GUI Library
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton,
QLabel, QVBoxLayout, QWidget)
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('My App')
layout = QVBoxLayout()
self.label = QLabel('Hello World')
button = QPushButton('Click Me')
button.clicked.connect(self.on_click)
layout.addWidget(self.label)
layout.addWidget(button)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
def on_click(self):
self.label.setText('Button Clicked!')
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()Python25 – Building GUIs with PyQt
from PyQt5.QtWidgets import (QLineEdit, QTextEdit, QCheckBox,
QRadioButton, QComboBox, QSpinBox,
QFileDialog, QMessageBox)
# Input widgets
line_edit = QLineEdit()
line_edit.setPlaceholderText('Enter text')
text = line_edit.text()
# Text area
text_edit = QTextEdit()
text_edit.setPlainText('Multi-line text')
# Checkbox
checkbox = QCheckBox('Option')
is_checked = checkbox.isChecked()
# Combo box
combo = QComboBox()
combo.addItems(['Option 1', 'Option 2'])
selected = combo.currentText()
# File dialog
filename, _ = QFileDialog.getOpenFileName(self, 'Open File')
# Message box
QMessageBox.information(self, 'Title', 'Message')Python26 – Building Web Apps with Flask
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
@app.route('/')
def home():
return render_template('index.html')
@app.route('/submit', methods=['POST'])
def submit():
data = request.form['field_name']
return redirect(url_for('home'))
# Template (index.html)
"""
<!DOCTYPE html>
<html>
<head><title>My App</title></head>
<body>
<h1>{{ title }}</h1>
<form action="/submit" method="post">
<input type="text" name="field_name">
<button type="submit">Submit</button>
</form>
</body>
</html>
"""
if __name__ == '__main__':
app.run(debug=True)Python27 – Directory and File Manipulation
import os
import shutil
from pathlib import Path
# Create directory
os.mkdir('folder')
os.makedirs('path/to/folder', exist_ok=True)
Path('folder').mkdir(exist_ok=True)
# List directory
os.listdir('folder')
list(Path('folder').iterdir())
# Check existence
os.path.exists('file.txt')
Path('file.txt').exists()
# Copy files
shutil.copy('source.txt', 'dest.txt')
shutil.copytree('source_dir', 'dest_dir')
# Move/Rename
shutil.move('old.txt', 'new.txt')
os.rename('old.txt', 'new.txt')
# Delete
os.remove('file.txt')
shutil.rmtree('folder')
Path('file.txt').unlink()
# File info
os.path.getsize('file.txt')
os.path.getctime('file.txt')Python28 – Command Line Interface Apps
import click
@click.command()
@click.option('--name', default='World', help='Name to greet')
@click.option('--count', default=1, help='Number of greetings')
@click.argument('output', type=click.File('w'), default='-')
def hello(name, count, output):
"""Simple greeting program"""
for _ in range(count):
click.echo(f'Hello {name}!', file=output)
if __name__ == '__main__':
hello()
# Usage: python script.py --name John --count 3Python29 – Object-Oriented Programming (OOP) Practice
# Class definition
class Person:
# Class variable
species = 'Human'
def __init__(self, name, age):
# Instance variables
self.name = name
self.age = age
# Instance method
def greet(self):
return f"Hello, I'm {self.name}"
# Class method
@classmethod
def from_birth_year(cls, name, birth_year):
return cls(name, 2024 - birth_year)
# Static method
@staticmethod
def is_adult(age):
return age >= 18
# Inheritance
class Student(Person):
def __init__(self, name, age, student_id):
super().__init__(name, age)
self.student_id = student_id
def greet(self):
return f"{super().greet()}, ID: {self.student_id}"
# Usage
person = Person('John', 30)
student = Student('Jane', 20, 'S123')Python30 – OOP Magic Methods
class MyClass:
def __init__(self, value):
self.value = value
# String representation
def __str__(self):
return f"MyClass({self.value})"
def __repr__(self):
return f"MyClass(value={self.value})"
# Comparison
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return self.value < other.value
# Arithmetic
def __add__(self, other):
return MyClass(self.value + other.value)
# Container
def __len__(self):
return len(self.value)
def __getitem__(self, index):
return self.value[index]
# Context manager
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# Cleanup
passPython31 – Matplotlib Data Visualization Library
import matplotlib.pyplot as plt
# Line plot
plt.plot([1, 2, 3], [1, 4, 9])
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.title('Title')
plt.show()
# Multiple plots
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
ax1.plot(x, y1)
ax2.plot(x, y2)
# Scatter plot
plt.scatter(x, y, c='red', marker='o')
# Bar chart
plt.bar(['A', 'B', 'C'], [10, 20, 15])
# Histogram
plt.hist(data, bins=20)
# Pie chart
plt.pie([30, 20, 50], labels=['A', 'B', 'C'], autopct='%1.1f%%')
# Save figure
plt.savefig('plot.png', dpi=300, bbox_inches='tight')Python32 – Data Visualization Dashboards with Streamlit
import streamlit as st
import pandas as pd
import plotly.express as px
st.title('Sales Dashboard')
# Load data
df = pd.read_csv('sales.csv')
# Filters
category = st.sidebar.selectbox('Category', df['category'].unique())
filtered_df = df[df['category'] == category]
# Metrics
col1, col2, col3 = st.columns(3)
col1.metric('Total Sales', f"${filtered_df['sales'].sum():,.2f}")
col2.metric('Orders', len(filtered_df))
col3.metric('Avg Order', f"${filtered_df['sales'].mean():.2f}")
# Charts
fig1 = px.line(filtered_df, x='date', y='sales', title='Sales Over Time')
st.plotly_chart(fig1, use_container_width=True)
fig2 = px.bar(filtered_df.groupby('product')['sales'].sum().reset_index(),
x='product', y='sales', title='Sales by Product')
st.plotly_chart(fig2, use_container_width=True)Python33 – Plotly Data Visualization Library
import plotly.express as px
import plotly.graph_objects as go
# Scatter plot
fig = px.scatter(df, x='x', y='y', color='category', size='value',
hover_data=['name'], title='Scatter Plot')
fig.show()
# Line chart
fig = px.line(df, x='date', y='value', title='Line Chart')
# Bar chart
fig = px.bar(df, x='category', y='value', color='group')
# Histogram
fig = px.histogram(df, x='value', nbins=30)
# Box plot
fig = px.box(df, x='category', y='value')
# Heatmap
fig = px.density_heatmap(df, x='x', y='y')
# Custom figure with go
fig = go.Figure()
fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6], mode='lines'))
fig.update_layout(title='Custom Plot', xaxis_title='X', yaxis_title='Y')Python34 – Folium Web Mapping Library
import folium
# Create map
m = folium.Map(location=[45.5236, -122.6750], zoom_start=13)
# Add marker
folium.Marker(
location=[45.5236, -122.6750],
popup='Portland, OR',
icon=folium.Icon(color='red', icon='info-sign')
).add_to(m)
# Circle marker
folium.CircleMarker(
location=[45.5244, -122.6699],
radius=50,
popup='Circle',
color='blue',
fill=True
).add_to(m)
# Save map
m.save('map.html')Python35 – Mapping with Folium
import folium
import pandas as pd
# Create map
m = folium.Map(location=[37.7749, -122.4194], zoom_start=12)
# Add multiple markers from dataframe
for idx, row in df.iterrows():
folium.Marker(
location=[row['lat'], row['lon']],
popup=row['name'],
tooltip=row['description']
).add_to(m)
# Heat map
from folium.plugins import HeatMap
heat_data = [[row['lat'], row['lon']] for idx, row in df.iterrows()]
HeatMap(heat_data).add_to(m)
# Choropleth map
m = folium.Map(location=[37.7749, -122.4194])
folium.Choropleth(
geo_data='us-states.json',
data=df,
columns=['state', 'value'],
key_on='feature.id',
fill_color='YlOrRd'
).add_to(m)Python36 – Utility Web Apps with Flask
from flask import Flask, request, jsonify, send_file
import pandas as pd
app = Flask(__name__)
# File converter
@app.route('/convert', methods=['POST'])
def convert_file():
file = request.files['file']
df = pd.read_csv(file)
output = 'output.xlsx'
df.to_excel(output, index=False)
return send_file(output, as_attachment=True)
# Text analyzer
@app.route('/analyze', methods=['POST'])
def analyze_text():
text = request.json['text']
words = len(text.split())
chars = len(text)
return jsonify({'words': words, 'characters': chars})
# Calculator
@app.route('/calculate', methods=['POST'])
def calculate():
data = request.json
result = eval(data['expression'])
return jsonify({'result': result})Python37 – OpenWeather API
import requests
API_KEY = 'your_api_key'
BASE_URL = 'http://api.openweathermap.org/data/2.5'
# Current weather
def get_current_weather(city):
url = f'{BASE_URL}/weather'
params = {'q': city, 'appid': API_KEY, 'units': 'metric'}
response = requests.get(url, params=params)
data = response.json()
return {
'temperature': data['main']['temp'],
'description': data['weather'][0]['description'],
'humidity': data['main']['humidity'],
'wind_speed': data['wind']['speed']
}
# 5-day forecast
def get_forecast(city):
url = f'{BASE_URL}/forecast'
params = {'q': city, 'appid': API_KEY, 'units': 'metric'}
response = requests.get(url, params=params)
return response.json()Python38 – Tkinter GUI Library
import tkinter as tk
from tkinter import ttk
# Create window
root = tk.Tk()
root.title('My App')
root.geometry('300x200')
# Label
label = tk.Label(root, text='Hello World', font=('Arial', 14))
label.pack(pady=10)
# Button
def on_click():
label.config(text='Button Clicked!')
button = tk.Button(root, text='Click Me', command=on_click)
button.pack()
# Entry
entry = tk.Entry(root)
entry.pack()
# Get entry value
value = entry.get()
root.mainloop()Python39 – Building Desktop GUIs with Tkinter
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Advanced GUI')
# Menu
menubar = tk.Menu(self)
file_menu = tk.Menu(menubar, tearoff=0)
file_menu.add_command(label='Open', command=self.open_file)
file_menu.add_command(label='Exit', command=self.quit)
menubar.add_cascade(label='File', menu=file_menu)
self.config(menu=menubar)
# Frame
frame = ttk.Frame(self, padding=10)
frame.grid(row=0, column=0)
# Combobox
self.combo = ttk.Combobox(frame, values=['Option 1', 'Option 2'])
self.combo.grid(row=0, column=0)
# Listbox
self.listbox = tk.Listbox(frame)
self.listbox.grid(row=1, column=0)
for item in ['Item 1', 'Item 2']:
self.listbox.insert(tk.END, item)
def open_file(self):
filename = filedialog.askopenfilename()
messagebox.showinfo('File', f'Selected: {filename}')
app = App()
app.mainloop()Python40 – Working with Binary Files
# Read binary file
with open('file.bin', 'rb') as f:
data = f.read()
# Write binary file
with open('file.bin', 'wb') as f:
f.write(b'\x00\x01\x02\x03')
# Using struct for binary data
import struct
# Pack data into binary
data = struct.pack('i', 12345) # Integer
data = struct.pack('f', 3.14) # Float
data = struct.pack('3s', b'abc') # String
# Unpack binary data
value = struct.unpack('i', data)[0]
# Read image as binary
with open('image.jpg', 'rb') as f:
image_data = f.read()Python41 – Hashing
import hashlib
# MD5 hash
text = 'Hello World'
hash_md5 = hashlib.md5(text.encode()).hexdigest()
# SHA256 hash
hash_sha256 = hashlib.sha256(text.encode()).hexdigest()
# Hash file
def hash_file(filename):
sha256_hash = hashlib.sha256()
with open(filename, 'rb') as f:
for byte_block in iter(lambda: f.read(4096), b''):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
# Password hashing with bcrypt
import bcrypt
password = b'mypassword'
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
# Check password
bcrypt.checkpw(password, hashed) # Returns TruePython42 – Working with Images
from PIL import Image
# Open image
img = Image.open('image.jpg')
# Image info
print(img.size, img.format, img.mode)
# Resize
img_resized = img.resize((800, 600))
# Crop
img_cropped = img.crop((100, 100, 400, 400))
# Rotate
img_rotated = img.rotate(90)
# Convert format
img.save('output.png')
# Convert to grayscale
img_gray = img.convert('L')
# Apply filter
from PIL import ImageFilter
img_blurred = img.filter(ImageFilter.BLUR)
# Draw on image
from PIL import ImageDraw
draw = ImageDraw.Draw(img)
draw.rectangle([50, 50, 200, 200], outline='red', width=3)
draw.text((10, 10), 'Hello', fill='white')Python43 – Beautiful Soup Web Scraping Library
from bs4 import BeautifulSoup
import requests
# Get webpage
url = 'https://example.com'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# Find elements
title = soup.find('title').text
heading = soup.find('h1').text
# Find all elements
links = soup.find_all('a')
for link in links:
print(link.get('href'))
# Find by class
items = soup.find_all('div', class_='item')
# Find by ID
content = soup.find(id='content')
# CSS selectors
elements = soup.select('.class-name')
elements = soup.select('#id-name')
elements = soup.select('div > p')
# Get text
text = soup.get_text()Python44 – Scraping Wikipedia with Beautiful Soup
from bs4 import BeautifulSoup
import requests
def scrape_wikipedia(topic):
url = f'https://en.wikipedia.org/wiki/{topic}'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# Get title
title = soup.find('h1', class_='firstHeading').text
# Get first paragraph
paragraphs = soup.find_all('p')
intro = paragraphs[0].text
# Get infobox data
infobox = soup.find('table', class_='infobox')
if infobox:
rows = infobox.find_all('tr')
data = {}
for row in rows:
header = row.find('th')
value = row.find('td')
if header and value:
data[header.text.strip()] = value.text.strip()
return {'title': title, 'intro': intro, 'data': data}Python45 – Selenium Browser Automation Library
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Initialize driver
driver = webdriver.Chrome()
driver.get('https://example.com')
# Find elements
element = driver.find_element(By.ID, 'element-id')
element = driver.find_element(By.CLASS_NAME, 'class-name')
element = driver.find_element(By.CSS_SELECTOR, '.class')
elements = driver.find_elements(By.TAG_NAME, 'a')
# Interact with elements
element.click()
element.send_keys('text')
element.send_keys(Keys.RETURN)
text = element.text
# Wait for element
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, 'id')))
# Screenshot
driver.save_screenshot('screenshot.png')
# Close
driver.quit()Python46 – Accessing PDF Content with Python
import PyPDF2
# Read PDF
with open('file.pdf', 'rb') as f:
pdf_reader = PyPDF2.PdfReader(f)
# Number of pages
num_pages = len(pdf_reader.pages)
# Extract text from page
page = pdf_reader.pages[0]
text = page.extract_text()
# Merge PDFs
pdf_merger = PyPDF2.PdfMerger()
pdf_merger.append('file1.pdf')
pdf_merger.append('file2.pdf')
pdf_merger.write('merged.pdf')
# Split PDF
with open('file.pdf', 'rb') as f:
pdf_reader = PyPDF2.PdfReader(f)
pdf_writer = PyPDF2.PdfWriter()
# Extract specific pages
pdf_writer.add_page(pdf_reader.pages[0])
with open('output.pdf', 'wb') as out:
pdf_writer.write(out)Python47 – Sending Emails from Gmail Addresses
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
# Setup
sender = 'your_email@gmail.com'
password = 'your_app_password' # Use app password
receiver = 'receiver@example.com'
# Create message
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = receiver
msg['Subject'] = 'Subject Line'
# Body
body = 'This is the email body.'
msg.attach(MIMEText(body, 'plain'))
# Attachment
filename = 'file.pdf'
with open(filename, 'rb') as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename= {filename}')
msg.attach(part)
# Send email
with smtplib.SMTP('smtp.gmail.com', 587) as server:
server.starttls()
server.login(sender, password)
server.send_message(msg)Python48 – Sending Emails from Any Email Address
import smtplib
from email.mime.text import MIMEText
# SMTP configuration for different providers
smtp_config = {
'gmail': ('smtp.gmail.com', 587),
'outlook': ('smtp-mail.outlook.com', 587),
'yahoo': ('smtp.mail.yahoo.com', 587),
'custom': ('smtp.yourdomain.com', 587)
}
def send_email(smtp_server, port, sender, password, receiver, subject, body):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = receiver
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(sender, password)
server.send_message(msg)
# Usage
send_email('smtp.gmail.com', 587, 'sender@gmail.com',
'password', 'receiver@example.com',
'Subject', 'Body text')Python49 – Automated Downloading of Files
import requests
from urllib.request import urlretrieve
# Simple download
url = 'https://example.com/file.pdf'
urlretrieve(url, 'downloaded_file.pdf')
# Download with requests
response = requests.get(url)
with open('file.pdf', 'wb') as f:
f.write(response.content)
# Download with progress
def download_file(url, filename):
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))
with open(filename, 'wb') as f:
downloaded = 0
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
downloaded += len(chunk)
progress = (downloaded / total_size) * 100
print(f'Progress: {progress:.2f}%', end='\r')
# Batch download
urls = ['url1', 'url2', 'url3']
for i, url in enumerate(urls):
filename = f'file_{i}.pdf'
download_file(url, filename)Python50 – Scheduling Execution of Python Tasks
# Using schedule library
import schedule
import time
def job():
print("Running scheduled task...")
# Schedule jobs
schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
# Run pending tasks
while True:
schedule.run_pending()
time.sleep(1)
# Using APScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
scheduler = BlockingScheduler()
# Add job
scheduler.add_job(job, 'interval', minutes=10)
scheduler.add_job(job, 'cron', day_of_week='mon-fri', hour=9)
scheduler.start()
# Using cron (Linux/Mac)
# Add to crontab: crontab -e
# 0 9 * * * /usr/bin/python3 /path/to/script.pyPythonAdvanced Patterns & Best Practices
1. Design Patterns
Singleton Pattern
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# Thread-safe singleton
import threading
class ThreadSafeSingleton:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instancePythonFactory Pattern
from abc import ABC, abstractmethod
from typing import Dict, Type
class Animal(ABC):
@abstractmethod
def speak(self) -> str:
pass
class Dog(Animal):
def speak(self) -> str:
return "Woof!"
class Cat(Animal):
def speak(self) -> str:
return "Meow!"
class AnimalFactory:
_animals: Dict[str, Type[Animal]] = {
'dog': Dog,
'cat': Cat,
}
@classmethod
def create(cls, animal_type: str) -> Animal:
animal_class = cls._animals.get(animal_type.lower())
if not animal_class:
raise ValueError(f"Unknown animal type: {animal_type}")
return animal_class()
# Usage
animal = AnimalFactory.create('dog')PythonObserver Pattern
from typing import List, Protocol
class Observer(Protocol):
def update(self, message: str) -> None: ...
class Subject:
def __init__(self):
self._observers: List[Observer] = []
def attach(self, observer: Observer) -> None:
self._observers.append(observer)
def detach(self, observer: Observer) -> None:
self._observers.remove(observer)
def notify(self, message: str) -> None:
for observer in self._observers:
observer.update(message)
class ConcreteObserver:
def __init__(self, name: str):
self.name = name
def update(self, message: str) -> None:
print(f"{self.name} received: {message}")PythonStrategy Pattern
from abc import ABC, abstractmethod
from typing import List
class SortStrategy(ABC):
@abstractmethod
def sort(self, data: List[int]) -> List[int]:
pass
class QuickSort(SortStrategy):
def sort(self, data: List[int]) -> List[int]:
if len(data) <= 1:
return data
pivot = data[len(data) // 2]
left = [x for x in data if x < pivot]
middle = [x for x in data if x == pivot]
right = [x for x in data if x > pivot]
return self.sort(left) + middle + self.sort(right)
class BubbleSort(SortStrategy):
def sort(self, data: List[int]) -> List[int]:
result = data.copy()
n = len(result)
for i in range(n):
for j in range(0, n - i - 1):
if result[j] > result[j + 1]:
result[j], result[j + 1] = result[j + 1], result[j]
return result
class Sorter:
def __init__(self, strategy: SortStrategy):
self.strategy = strategy
def sort(self, data: List[int]) -> List[int]:
return self.strategy.sort(data)
# Usage
sorter = Sorter(QuickSort())
sorted_data = sorter.sort([3, 1, 4, 1, 5, 9])Python2. Performance Optimization
Profiling
import cProfile
import pstats
from functools import wraps
import time
# Profile function
def profile_function(func):
@wraps(func)
def wrapper(*args, **kwargs):
profiler = cProfile.Profile()
profiler.enable()
result = func(*args, **kwargs)
profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(10)
return result
return wrapper
# Line profiler (requires line_profiler package)
# @profile # Uncomment when using kernprof
def slow_function():
total = 0
for i in range(1000000):
total += i
return total
# Memory profiling (requires memory_profiler)
# from memory_profiler import profile
# @profile
def memory_intensive():
big_list = [i for i in range(1000000)]
return sum(big_list)PythonOptimization Techniques
import bisect
from collections import defaultdict, Counter, deque
from functools import lru_cache
import numpy as np
# Use built-in functions (C-optimized)
data = [1, 2, 3, 4, 5]
total = sum(data) # Faster than manual loop
maximum = max(data)
# List comprehension vs loops (faster)
squares = [x**2 for x in range(1000)] # Faster
# vs
squares = []
for x in range(1000):
squares.append(x**2)
# Generator for memory efficiency
def generate_squares(n):
for i in range(n):
yield i**2
# Use appropriate data structures
# - dict/set for lookups: O(1)
# - list for iteration: O(n)
# - deque for queue operations: O(1)
lookup_set = set(range(1000000))
exists = 500000 in lookup_set # O(1)
# Binary search for sorted lists
sorted_list = list(range(1000000))
index = bisect.bisect_left(sorted_list, 500000) # O(log n)
# Memoization with lru_cache
@lru_cache(maxsize=None)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
# Use NumPy for numerical operations
arr = np.array([1, 2, 3, 4, 5])
result = arr * 2 # Vectorized operation (faster)Python3. Code Quality & Standards
Type Checking with mypy
# mypy configuration (.mypy.ini)
"""
[mypy]
python_version = 3.11
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
"""
from typing import TypedDict, NotRequired
# Typed dictionaries
class UserDict(TypedDict):
name: str
age: int
email: NotRequired[str] # Optional field
def process_user(user: UserDict) -> str:
return f"{user['name']}, {user['age']}"
# Run: mypy script.pyPythonLinting & Formatting
# Black - Code formatter (opinionated)
# Run: black script.py
# Flake8 - Linter
# Run: flake8 script.py
# Pylint - Advanced linter
# Run: pylint script.py
# isort - Import sorting
# Run: isort script.py
# Pre-commit hooks (.pre-commit-config.yaml)
"""
repos:
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
"""PythonDocumentation
def complex_function(
data: List[Dict[str, Any]],
threshold: float = 0.5,
*,
verbose: bool = False
) -> Tuple[List[Dict], List[Dict]]:
"""
Process data and split based on threshold.
Args:
data: List of dictionaries containing data points
threshold: Value to split data on (default: 0.5)
verbose: Whether to print processing info (keyword-only)
Returns:
Tuple of (accepted_data, rejected_data)
Raises:
ValueError: If threshold is not between 0 and 1
TypeError: If data is not a list of dictionaries
Example:
>>> data = [{'value': 0.7}, {'value': 0.3}]
>>> accepted, rejected = complex_function(data, 0.5)
>>> len(accepted)
1
Note:
This function modifies the input data in place.
See Also:
- simple_function: For basic processing
- advanced_function: For multi-stage processing
"""
if not 0 <= threshold <= 1:
raise ValueError("Threshold must be between 0 and 1")
# Implementation
accepted = [d for d in data if d.get('value', 0) >= threshold]
rejected = [d for d in data if d.get('value', 0) < threshold]
return accepted, rejected
# Generate docs: sphinx-apidoc, pdoc3, mkdocsPython4. Dependency Management
# pyproject.toml (PEP 518/621)
"""
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my-package"
version = "0.1.0"
description = "My awesome package"
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
"requests>=2.28.0",
"pandas>=1.5.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
]
"""
# requirements.txt
"""
requests==2.28.1
pandas>=1.5.0,<2.0.0
numpy~=1.24.0
"""
# Poetry (alternative)
"""
[tool.poetry]
name = "my-package"
version = "0.1.0"
[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.0"
[tool.poetry.dev-dependencies]
pytest = "^7.0.0"
"""
# Use virtual environments
# python -m venv venv
# source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # WindowsPython5. Security Best Practices
import secrets
import hashlib
from cryptography.fernet import Fernet
import os
from pathlib import Path
# Secure random generation
secure_token = secrets.token_urlsafe(32)
secure_number = secrets.randbelow(100)
# Password hashing (use bcrypt or argon2)
import bcrypt
def hash_password(password: str) -> bytes:
return bcrypt.hashpw(password.encode(), bcrypt.gensalt())
def verify_password(password: str, hashed: bytes) -> bool:
return bcrypt.checkpw(password.encode(), hashed)
# Encryption
def encrypt_data(data: bytes, key: bytes) -> bytes:
f = Fernet(key)
return f.encrypt(data)
def decrypt_data(encrypted: bytes, key: bytes) -> bytes:
f = Fernet(key)
return f.decrypt(encrypted)
# Generate key
encryption_key = Fernet.generate_key()
# Environment variables for secrets (NEVER hardcode)
DATABASE_PASSWORD = os.getenv('DATABASE_PASSWORD')
API_KEY = os.getenv('API_KEY')
# Input validation
import re
def validate_email(email: str) -> bool:
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
def sanitize_filename(filename: str) -> str:
"""Remove dangerous characters from filename"""
return re.sub(r'[^\w\s.-]', '', filename)
# SQL injection prevention (use parameterized queries)
import sqlite3
def safe_query(user_id: int) -> list:
conn = sqlite3.connect('db.sqlite')
cursor = conn.cursor()
# GOOD: Parameterized query
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
# BAD: String formatting
# cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
return cursor.fetchall()Python6. Concurrency & Parallelism
import threading
import multiprocessing
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import asyncio
from queue import Queue
import time
# Threading (I/O-bound tasks)
def io_bound_task(n: int) -> int:
time.sleep(1)
return n * 2
with ThreadPoolExecutor(max_workers=4) as executor:
results = list(executor.map(io_bound_task, range(10)))
# Multiprocessing (CPU-bound tasks)
def cpu_bound_task(n: int) -> int:
return sum(i * i for i in range(n))
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(cpu_bound_task, [10**6] * 4))
# Thread-safe queue
queue: Queue = Queue()
def producer():
for i in range(10):
queue.put(i)
time.sleep(0.1)
def consumer():
while True:
item = queue.get()
if item is None:
break
print(f"Processing {item}")
queue.task_done()
# Async programming
async def fetch_data(url: str) -> str:
await asyncio.sleep(1) # Simulate I/O
return f"Data from {url}"
async def main():
tasks = [fetch_data(f"url_{i}") for i in range(10)]
results = await asyncio.gather(*tasks)
return results
# Run: asyncio.run(main())
# Lock for thread safety
lock = threading.Lock()
shared_resource = 0
def increment():
global shared_resource
with lock:
temp = shared_resource
temp += 1
shared_resource = tempPython7. Database Best Practices
from contextlib import contextmanager
import sqlite3
from typing import Any, List, Tuple
from dataclasses import dataclass
# Context manager for database connections
@contextmanager
def get_db_connection(db_path: str):
conn = sqlite3.connect(db_path)
conn.row_factory = sqlite3.Row # Dict-like access
try:
yield conn
conn.commit()
except Exception:
conn.rollback()
raise
finally:
conn.close()
# Repository pattern
@dataclass
class User:
id: int
name: str
email: str
class UserRepository:
def __init__(self, db_path: str):
self.db_path = db_path
def create(self, user: User) -> int:
with get_db_connection(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
(user.name, user.email)
)
return cursor.lastrowid
def get_by_id(self, user_id: int) -> User | None:
with get_db_connection(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
row = cursor.fetchone()
if row:
return User(**dict(row))
return None
def update(self, user: User) -> None:
with get_db_connection(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute(
"UPDATE users SET name = ?, email = ? WHERE id = ?",
(user.name, user.email, user.id)
)
def delete(self, user_id: int) -> None:
with get_db_connection(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM users WHERE id = ?", (user_id,))
# SQLAlchemy ORM (recommended for complex apps)
"""
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
email = Column(String(100), unique=True)
engine = create_engine('sqlite:///db.sqlite')
Session = sessionmaker(bind=engine)
session = Session()
# CRUD operations
user = User(name='John', email='john@example.com')
session.add(user)
session.commit()
"""Python8. API Best Practices (FastAPI)
from fastapi import FastAPI, HTTPException, Depends, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel, EmailStr, validator
from typing import List, Optional
from datetime import datetime
app = FastAPI(title="My API", version="1.0.0")
# Pydantic models for validation
class UserCreate(BaseModel):
name: str
email: EmailStr
age: int
@validator('age')
def validate_age(cls, v):
if v < 0 or v > 150:
raise ValueError('Age must be between 0 and 150')
return v
class UserResponse(BaseModel):
id: int
name: str
email: str
age: int
created_at: datetime
class Config:
orm_mode = True
# Dependency injection
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security)
) -> dict:
# Verify token
token = credentials.credentials
# ... token verification logic
return {"user_id": 1, "username": "john"}
# Routes
@app.post("/users/", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(user: UserCreate):
# Create user logic
return {"id": 1, **user.dict(), "created_at": datetime.now()}
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
# Get user logic
user = get_user_from_db(user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.get("/users/", response_model=List[UserResponse])
async def list_users(
skip: int = 0,
limit: int = 100,
current_user: dict = Depends(get_current_user)
):
# List users logic
return get_users_from_db(skip=skip, limit=limit)
# Run: uvicorn main:app --reloadPythonQuick Reference: Common Patterns
File I/O (Modern)
from pathlib import Path
# Read
content = Path('file.txt').read_text(encoding='utf-8')
# Write
Path('file.txt').write_text('content', encoding='utf-8')
# JSON
import json
data = json.loads(Path('data.json').read_text())
Path('output.json').write_text(json.dumps(data, indent=2))PythonError Handling (Advanced)
from typing import Optional
import logging
def safe_divide(a: float, b: float) -> Optional[float]:
"""Returns None instead of raising exception"""
try:
return a / b
except ZeroDivisionError:
logging.error(f"Division by zero: {a} / {b}")
return None
except Exception as e:
logging.exception("Unexpected error in division")
raise
# Exception context
try:
result = risky_operation()
except SomeError as e:
raise NewError("Failed to process") from e # Chain exceptionsPythonList/Dict Comprehensions (Advanced)
# Nested comprehension with condition
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row if num % 2 == 0]
# Dict comprehension with transformation
data = {'a': 1, 'b': 2, 'c': 3}
squared = {k: v**2 for k, v in data.items() if v > 1}
# Set comprehension
unique_squares = {x**2 for x in range(10)}
# Walrus operator (Python 3.8+)
filtered = [y for x in data if (y := x * 2) > 10]PythonModern Python Features
# Structural pattern matching (Python 3.10+)
def process_command(command: str, value: Any):
match command:
case "add":
return value + 1
case "subtract":
return value - 1
case "multiply" | "times":
return value * 2
case _:
return value
# Union types (Python 3.10+)
def process(value: int | str | None) -> str:
match value:
case int(n):
return f"Number: {n}"
case str(s):
return f"String: {s}"
case None:
return "Nothing"
# Dictionary merge operator (Python 3.9+)
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
merged = dict1 | dict2 # {'a': 1, 'b': 3, 'c': 4}
# Removeprefix/removesuffix (Python 3.9+)
text = "Hello World"
text.removeprefix("Hello ") # "World"
text.removesuffix(" World") # "Hello"PythonInstallation & Setup
Essential Packages
# Core data science
pip install numpy pandas matplotlib seaborn scipy scikit-learn
# Web frameworks
pip install flask fastapi uvicorn streamlit
# Database
pip install sqlalchemy psycopg2-binary pymongo redis
# Async & HTTP
pip install aiohttp asyncio httpx requests
# Testing
pip install pytest pytest-cov pytest-asyncio hypothesis
# Code quality
pip install black flake8 mypy pylint isort pre-commit
# Documentation
pip install sphinx mkdocs pdoc3
# Utilities
pip install python-dotenv pydantic click typer rich
# File processing
pip install openpyxl python-docx PyPDF2 Pillow
# Web scraping
pip install beautifulsoup4 selenium playwright scrapy
# GUIs
pip install PyQt5 tkinter kivy
# Visualization
pip install plotly folium bokeh dash
# Data processing
pip install polars dask pyarrow
# Security
pip install cryptography bcrypt python-jose
# Task scheduling
pip install celery schedule APScheduler
# API clients
pip install tweepy google-api-python-client boto3PythonDevelopment Environment
# Create virtual environment
python -m venv venv
# Activate (Linux/Mac)
source venv/bin/activate
# Activate (Windows)
venv\Scripts\activate
# Install from requirements
pip install -r requirements.txt
# Freeze dependencies
pip freeze > requirements.txt
# Install in editable mode
pip install -e .PythonPerformance Tips
- Use built-in functions – They’re implemented in C and faster
- List comprehensions – Faster than loops for list creation
- Generators – Memory efficient for large datasets
__slots__– Reduce memory for classes with many instances- NumPy/Pandas – For numerical operations
- Caching – Use
@lru_cachefor expensive computations - Profile first – Don’t optimize without profiling
- Right data structure – dict/set for lookups, deque for queues
- Avoid global variables – Local variable access is faster
- String concatenation – Use
''.join()for multiple strings
Note: This cheatsheet covers Python 3.9+ features. For production code, always use type hints, proper error handling, logging, and testing.
Discover more from Altgr Blog
Subscribe to get the latest posts sent to your email.
