From Basic to Advanced - The Ultimate Guide
Comprehensive reference covering Python basics, Scikit-learn, Flask, SQLAlchemy, Scrapy, NumPy, Pandas, Django, Pygame, Pymunk and advanced concepts
Python is dynamically typed, meaning you don't need to declare variable types.
# Basic data types
integer_var = 42
float_var = 3.14159
string_var = "Hello, Python!"
boolean_var = True
none_var = None
# Collections
list_var = [1, 2, 3, "four", 5.0] # Mutable sequence
tuple_var = (1, 2, 3) # Immutable sequence
dict_var = {"name": "Alice", "age": 25} # Key-value pairs
set_var = {1, 2, 3, 3, 2} # Unique elements: {1, 2, 3}
# Type conversion
str(42) # "42"
int("42") # 42
float("3.14") # 3.14
list("hello") # ['h', 'e', 'l', 'l', 'o']
# If-elif-else statements
temperature = 25
if temperature < 0:
print("Freezing")
elif 0 <= temperature < 20:
print("Cold")
elif 20 <= temperature < 30:
print("Comfortable")
else:
print("Hot")
# For loops
for i in range(5): # 0 to 4
print(i)
# While loop
count = 0
while count < 5:
print(count)
count += 1
# List comprehension
squares = [x**2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Basic function
def greet(name):
"""Return a greeting message"""
return f"Hello, {name}!"
# Function with default arguments
def power(base, exponent=2):
"""Raise base to the power of exponent (default 2)"""
return base ** exponent
# Variable number of arguments
def sum_all(*args):
"""Sum all arguments"""
return sum(args)
# Lambda function
square = lambda x: x * x
# Function annotations
def add(a: int, b: int) -> int:
"""Add two integers and return the result"""
return a + b
class Animal:
# Class attribute
kingdom = "Animalia"
# Initializer
def __init__(self, name, species):
self.name = name
self.species = species
# Instance method
def description(self):
return f"{self.name} is a {self.species}"
# Another instance method
def speak(self, sound):
return f"{self.name} says {sound}"
# Inheritance
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "Canis familiaris")
self.breed = breed
# Override method
def speak(self, sound="Woof"):
return super().speak(sound)
# Create instances
dog = Dog("Buddy", "Golden Retriever")
print(dog.description()) # Buddy is a Canis familiaris
print(dog.speak()) # Buddy says Woof
# Writing to a file
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a second line.\n")
# Reading from a file
with open('example.txt', 'r') as file:
content = file.read()
print(content)
# Reading line by line
with open('example.txt', 'r') as file:
for line in file:
print(line.strip()) # strip() removes newline characters
# Working with JSON
import json
data = {'name': 'Alice', 'age': 25, 'city': 'New York'}
# Write JSON
with open('data.json', 'w') as file:
json.dump(data, file)
# Read JSON
with open('data.json', 'r') as file:
loaded_data = json.load(file)
print(loaded_data)
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# Load dataset
iris = load_iris()
X, y = iris.data, iris.target
# Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Feature scaling
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# Train model
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# Predict and evaluate
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix
# Support Vector Classifier
svc = SVC(kernel='rbf', C=1.0, gamma='scale')
svc.fit(X_train, y_train)
# Predictions
y_pred = svc.predict(X_test)
# Evaluation
print(classification_report(y_test, y_pred))
print(confusion_matrix(y_test, y_pred))
# Cross-validation
from sklearn.model_selection import cross_val_score
scores = cross_val_score(svc, X, y, cv=5)
print(f"Cross-validation scores: {scores}")
print(f"Mean accuracy: {scores.mean():.2f}")
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# Load dataset
diabetes = load_diabetes()
X, y = diabetes.data, diabetes.target
# Split data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Train model
model = LinearRegression()
model.fit(X_train, y_train)
# Predict and evaluate
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse:.2f}")
print(f"R-squared: {r2:.2f}")
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
# Generate sample data
X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
# K-means clustering
kmeans = KMeans(n_clusters=4)
kmeans.fit(X)
y_kmeans = kmeans.predict(X)
# Plot clusters
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75)
plt.title("K-means Clustering")
plt.show()
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.preprocessing import PolynomialFeatures
# Create pipeline
pipe = Pipeline([
('scaler', StandardScaler()),
('pca', PCA(n_components=2)),
('poly', PolynomialFeatures(degree=2)),
('classifier', RandomForestClassifier())
])
# Fit pipeline
pipe.fit(X_train, y_train)
# Evaluate
accuracy = pipe.score(X_test, y_test)
print(f"Pipeline accuracy: {accuracy:.2f}")
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
@app.route('/')
def home():
return "Hello, Flask!"
@app.route('/greet/<name>')
def greet(name):
return f"Hello, {name}!"
@app.route('/form', methods=['GET', 'POST'])
def form():
if request.method == 'POST':
username = request.form['username']
return redirect(url_for('greet', name=username))
return '''
<form method="POST">
Username: <input type="text" name="username">
<input type="submit" value="Submit">
</form>
'''
if __name__ == '__main__':
app.run(debug=True)
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<nav>
<a href="{{ url_for('home') }}">Home</a>
</nav>
<div class="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
<!-- templates/index.html -->
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome!</h1>
<p>Current time: {{ current_time }}</p>
{% endblock %}
from flask import Flask, jsonify, request
app = Flask(__name__)
tasks = [
{'id': 1, 'title': 'Learn Flask', 'done': False},
{'id': 2, 'title': 'Build API', 'done': False}
]
@app.route('/api/tasks', methods=['GET'])
def get_tasks():
return jsonify({'tasks': tasks})
@app.route('/api/tasks', methods=['POST'])
def create_task():
if not request.json or not 'title' in request.json:
return jsonify({'error': 'Bad request'}), 400
task = {
'id': tasks[-1]['id'] + 1,
'title': request.json['title'],
'done': False
}
tasks.append(task)
return jsonify({'task': task}), 201
@app.route('/api/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
task = next((t for t in tasks if t['id'] == task_id), None)
if not task:
return jsonify({'error': 'Not found'}), 404
task['title'] = request.json.get('title', task['title'])
task['done'] = request.json.get('done', task['done'])
return jsonify({'task': task})
if __name__ == '__main__':
app.run(debug=True)
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return f"User('{self.username}', '{self.email}')"
# Create tables
with app.app_context():
db.create_all()
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
user = User(username=username, email=email)
db.session.add(user)
db.session.commit()
return redirect(url_for('home'))
return render_template('register.html')
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
login_manager = LoginManager(app)
class User(UserMixin, db.Model):
# ... previous fields ...
password = db.Column(db.String(60), nullable=False)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user = User.query.filter_by(email=request.form['email']).first()
if user and check_password_hash(user.password, request.form['password']):
login_user(user)
return redirect(url_for('dashboard'))
return render_template('login.html')
@app.route('/dashboard')
@login_required
def dashboard():
return render_template('dashboard.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('home'))
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# Database setup
engine = create_engine('sqlite:///example.db')
Base = declarative_base()
# Define model
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __repr__(self):
return f"<User(name='{self.name}', email='{self.email}')>"
# Create tables
Base.metadata.create_all(engine)
# Create session
Session = sessionmaker(bind=engine)
session = Session()
# Add new user
new_user = User(name='Alice', email='alice@example.com')
session.add(new_user)
session.commit()
# Query users
users = session.query(User).all()
for user in users:
print(user.name, user.email)
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
title = Column(String)
content = Column(String)
user_id = Column(Integer, ForeignKey('users.id'))
author = relationship("User", back_populates="posts")
User.posts = relationship("Post", order_by=Post.id, back_populates="author")
# Create a user with posts
user = User(name='Bob', email='bob@example.com')
user.posts = [
Post(title='First Post', content='Hello World!'),
Post(title='Second Post', content='SQLAlchemy is awesome!')
]
session.add(user)
session.commit()
# Query with relationships
user = session.query(User).filter_by(name='Bob').first()
for post in user.posts:
print(post.title, post.content)
# Basic queries
users = session.query(User).all() # All users
user = session.query(User).filter_by(name='Alice').first() # First user named Alice
# Filtering
from sqlalchemy import or_
users = session.query(User).filter(
or_(User.name == 'Alice', User.email.like('%example%'))
).all()
# Ordering
users = session.query(User).order_by(User.name).all()
# Aggregation
from sqlalchemy import func
count = session.query(func.count(User.id)).scalar()
print(f"Total users: {count}")
# Pagination
page = 1
per_page = 10
users = session.query(User).order_by(User.id).offset((page-1)*per_page).limit(per_page).all()
# Install Alembic
# pip install alembic
# Initialize Alembic
# alembic init alembic
# Configure alembic.ini
# sqlalchemy.url = sqlite:///example.db
# Create migration
# alembic revision --autogenerate -m "Add phone number to User"
# The generated migration file will look like:
'''
def upgrade():
op.add_column('users', sa.Column('phone', sa.String(), nullable=True))
def downgrade():
op.drop_column('users', 'phone')
'''
# Apply migration
# alembic upgrade head
# Hybrid properties
from sqlalchemy.ext.hybrid import hybrid_property
class User(Base):
# ... other columns ...
first_name = Column(String)
last_name = Column(String)
@hybrid_property
def full_name(self):
return f"{self.first_name} {self.last_name}"
@full_name.expression
def full_name(cls):
return cls.first_name + ' ' + cls.last_name
# Events
from sqlalchemy import event
@event.listens_for(User, 'before_insert')
def before_insert_listener(mapper, connection, target):
print(f"About to insert user: {target.name}")
# Composite types
from sqlalchemy import Composite
from sqlalchemy.ext.declarative import composite
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __composite_values__(self):
return self.x, self.y
class Vertex(Base):
__tablename__ = 'vertices'
id = Column(Integer, primary_key=True)
x = Column(Integer)
y = Column(Integer)
point = composite(Point, x, y)
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'https://quotes.toscrape.com/page/1/',
]
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').get(),
'author': quote.css('small.author::text').get(),
'tags': quote.css('div.tags a.tag::text').getall(),
}
next_page = response.css('li.next a::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, self.parse)
# Run spider from script
from scrapy.crawler import CrawlerProcess
process = CrawlerProcess(settings={
'FEED_FORMAT': 'json',
'FEED_URI': 'quotes.json'
})
process.crawl(QuotesSpider)
process.start()
# Define items
import scrapy
class QuoteItem(scrapy.Item):
text = scrapy.Field()
author = scrapy.Field()
tags = scrapy.Field()
# In spider
class QuotesSpider(scrapy.Spider):
# ... previous code ...
def parse(self, response):
for quote in response.css('div.quote'):
item = QuoteItem()
item['text'] = quote.css('span.text::text').get()
item['author'] = quote.css('small.author::text').get()
item['tags'] = quote.css('div.tags a.tag::text').getall()
yield item
# Pipeline for processing items
class CleanQuotePipeline:
def process_item(self, item, spider):
item['text'] = item['text'].strip('“”')
return item
# Enable pipeline in settings.py
# ITEM_PIPELINES = {
# 'myproject.pipelines.CleanQuotePipeline': 300,
# }
# Random user agent middleware
from scrapy import signals
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
import random
class RandomUserAgentMiddleware(UserAgentMiddleware):
def __init__(self, user_agent):
super().__init__()
self.user_agents = user_agent
@classmethod
def from_crawler(cls, crawler):
o = cls(crawler.settings.get('USER_AGENT_LIST'))
crawler.signals.connect(o.spider_opened, signal=signals.spider_opened)
return o
def process_request(self, request, spider):
request.headers['User-Agent'] = random.choice(self.user_agents)
# Enable in settings.py
# DOWNLOADER_MIDDLEWARES = {
# 'myproject.middlewares.RandomUserAgentMiddleware': 400,
# }
# USER_AGENT_LIST = [
# 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
# 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...',
# # more user agents
# ]
# Export to different formats
# Run spider with output options
# scrapy crawl quotes -O quotes.json
# scrapy crawl quotes -O quotes.csv
# scrapy crawl quotes -O quotes.xml
# Custom exporter
from scrapy.exporters import JsonItemExporter
class CustomJsonExporter(JsonItemExporter):
def serialize_field(self, field, name, value):
if name == 'text':
return value.strip('“”')
return super().serialize_field(field, name, value)
# In settings.py
# FEED_EXPORTERS = {
# 'json': 'myproject.exporters.CustomJsonExporter',
# }
# Splash for JavaScript rendering
import scrapy
from scrapy_splash import SplashRequest
class JSSpider(scrapy.Spider):
name = 'js'
def start_requests(self):
yield SplashRequest(
url='https://example.com',
callback=self.parse,
args={'wait': 2} # Wait for JavaScript to execute
)
def parse(self, response):
yield {
'title': response.css('title::text').get(),
'content': response.css('div.content::text').get()
}
# Required settings
# SPLASH_URL = 'http://localhost:8050'
# DOWNLOADER_MIDDLEWARES = {
# 'scrapy_splash.SplashCookiesMiddleware': 723,
# 'scrapy_splash.SplashMiddleware': 725,
# 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
# }
# SPIDER_MIDDLEWARES = {
# 'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
# }
# DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
import numpy as np
# Create arrays
arr1 = np.array([1, 2, 3, 4, 5]) # 1D array
arr2 = np.array([[1, 2, 3], [4, 5, 6]]) # 2D array
zeros = np.zeros((3, 4)) # 3x4 array of zeros
ones = np.ones((2, 2, 2)) # 2x2x2 array of ones
identity = np.eye(3) # 3x3 identity matrix
random_arr = np.random.rand(3, 3) # 3x3 random array (0-1)
range_arr = np.arange(0, 10, 2) # array([0, 2, 4, 6, 8])
linspace = np.linspace(0, 1, 5) # 5 numbers from 0 to 1: [0., 0.25, 0.5, 0.75, 1.]
# Special arrays
empty = np.empty((2, 3)) # Uninitialized array
full = np.full((2, 2), 7) # 2x2 array filled with 7
# Basic operations
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # [5 7 9]
print(a * b) # [4 10 18] (element-wise)
print(np.dot(a, b)) # Dot product: 32
# Matrix operations
matrix = np.array([[1, 2], [3, 4]])
print(matrix.T) # Transpose
print(np.linalg.inv(matrix)) # Inverse matrix
print(np.linalg.det(matrix)) # Determinant
# Universal functions
print(np.sqrt(a)) # Square root
print(np.exp(a)) # Exponential
print(np.sin(a)) # Sine
print(np.log(a)) # Natural logarithm
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Basic indexing
print(arr[0, 1]) # 2 (first row, second column)
print(arr[:, 1]) # [2 5 8] (all rows, second column)
print(arr[1:3, 0:2]) # [[4 5] [7 8]] (subarray)
# Boolean indexing
mask = arr > 5
print(mask) # [[False False False] [False False True] [True True True]]
print(arr[mask]) # [6 7 8 9]
# Fancy indexing
print(arr[[0, 2], :]) # First and third rows
print(arr[:, [1, 2]]) # Second and third columns
# Operations between arrays of different shapes
a = np.array([1, 2, 3])
b = 2
print(a * b) # [2 4 6]
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
row = np.array([10, 20, 30])
print(matrix + row) # Adds row to each row of matrix
# More broadcasting
a = np.array([[1], [2], [3]])
b = np.array([10, 20, 30])
print(a + b) # [[11 21 31], [12 22 32], [13 23 33]]
# Solving linear equations
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b) # [2., 3.]
# Eigenvalues and eigenvectors
eigenvalues, eigenvectors = np.linalg.eig(A)
# Matrix decomposition
Q, R = np.linalg.qr(A) # QR decomposition
U, S, V = np.linalg.svd(A) # Singular value decomposition
# Statistics
data = np.random.randn(100, 3) # 100 samples, 3 features
print(np.mean(data, axis=0)) # Mean of each feature
print(np.std(data, axis=0)) # Standard deviation
print(np.corrcoef(data.T)) # Correlation matrix
import pandas as pd
import numpy as np
# Series (1D)
s = pd.Series([1, 3, 5, np.nan, 6, 8], name='Numbers')
# DataFrame (2D)
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David'],
'Age': [25, 30, 35, 40],
'City': ['NY', 'Paris', 'London', 'Tokyo']
}
df = pd.DataFrame(data)
# Display
print(df.head()) # First 5 rows
print(df.tail(2)) # Last 2 rows
print(df.describe()) # Statistics
print(df.info()) # Summary
# Column selection
print(df['Name']) # Single column
print(df[['Name', 'Age']]) # Multiple columns
# Row selection
print(df.iloc[0]) # First row by index
print(df.loc[0:2]) # Rows 0 to 2
print(df[df['Age'] > 30]) # Filter rows
# Setting values
df.loc[0, 'Age'] = 26 # Change specific value
df['Salary'] = [50000, 60000, 70000, 80000] # Add column
# Handling missing data
df.loc[1, 'Age'] = None # Introduce missing value
print(df.isnull()) # Check for missing values
df_clean = df.dropna() # Drop rows with missing values
df_filled = df.fillna({'Age': df['Age'].mean()}) # Fill with mean
# Removing duplicates
df = pd.DataFrame({'A': [1, 1, 2, 2], 'B': ['a', 'b', 'a', 'b']})
df_no_dup = df.drop_duplicates()
# String operations
df['Name'] = df['Name'].str.upper()
df['Name'] = df['Name'].str.replace('A', 'X')
# Group by and aggregate
df = pd.DataFrame({
'Department': ['Sales', 'Sales', 'IT', 'IT', 'HR'],
'Employee': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'Salary': [60000, 50000, 80000, 75000, 55000]
})
grouped = df.groupby('Department')
print(grouped.mean()) # Average salary by department
print(grouped.agg({'Salary': ['mean', 'min', 'max', 'count']})) # Multiple stats
# Pivot tables
pivot = df.pivot_table(values='Salary', index='Department', aggfunc=['mean', 'count'])
# Date range
dates = pd.date_range('20250101', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
# Time-based operations
df['Month'] = df.index.month
df['DayOfWeek'] = df.index.dayofweek
# Resampling
df.resample('M').mean() # Monthly means
df.rolling(window=3).mean() # Rolling 3-day average
# Timezone handling
df = df.tz_localize('UTC')
df = df.tz_convert('US/Eastern')
# Install Django
# pip install django
# Create project
# django-admin startproject mysite
# Project structure:
# mysite/
# ├── manage.py
# └── mysite/
# ├── __init__.py
# ├── settings.py
# ├── urls.py
# └── wsgi.py
# Create app
# python manage.py startapp blog
# Run development server
# python manage.py runserver
# blog/models.py
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
# Register model in admin
# blog/admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)
# After creating models:
# python manage.py makemigrations
# python manage.py migrate
# Function-based view
from django.shortcuts import render
from .models import Post
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
# Class-based view
from django.views.generic import ListView, DetailView
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
class PostDetailView(DetailView):
model = Post
# mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
]
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.PostListView.as_view(), name='blog-home'),
path('post/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
]
# blog/templates/blog/home.html
{% extends "blog/base.html" %}
{% block content %}
{% for post in posts %}
<article>
<h2><a href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
<p>By {{ post.author }} on {{ post.date_posted|date:"F d, Y" }}</p>
<p>{{ post.content }}</p>
</article>
{% endfor %}
{% endblock %}
# blog/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
# blog/views.py
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'blog/register.html', {'form': form})
@login_required
def profile(request):
return render(request, 'blog/profile.html')
# Simple decorator
def my_decorator(func):
def wrapper():
print("Before function is called")
func()
print("After function is called")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
# say_hello() will print:
# Before function is called
# Hello!
# After function is called
# Decorator with arguments
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
# Class decorator
class CountCalls:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f"Call {self.num_calls} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
# Simple generator
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
counter = count_up_to(5)
for num in counter:
print(num) # Prints 1, 2, 3, 4, 5
# Generator expression
squares = (x*x for x in range(10))
for square in squares:
print(square)
# Sending values to generator
def accumulator():
total = 0
while True:
value = yield total
if value is None:
break
total += value
acc = accumulator()
next(acc) # Start generator
print(acc.send(10)) # 10
print(acc.send(20)) # 30
print(acc.send(5)) # 35
# Using context manager (with statement)
with open('file.txt', 'r') as file:
content = file.read()
# File automatically closed here
# Class-based context manager
class ManagedFile:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
with ManagedFile('hello.txt', 'w') as f:
f.write('Hello, world!')
# Function-based context manager
from contextlib import contextmanager
@contextmanager
def managed_file(name, mode):
try:
f = open(name, mode)
yield f
finally:
f.close()
with managed_file('hello.txt', 'w') as f:
f.write('Hello again!')
# Simple metaclass example
class Meta(type):
def __new__(cls, name, bases, dct):
# Add a class attribute
dct['created_by'] = 'Meta'
# Ensure all methods are uppercase
uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
return super().__new__(cls, name, bases, uppercase_attr)
class MyClass(metaclass=Meta):
def my_method(self):
print("This is my method")
obj = MyClass()
obj.MY_METHOD() # Note the uppercase method name
print(MyClass.created_by) # 'Meta'
# Singleton pattern with metaclass
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
pass
a = Singleton()
b = Singleton()
print(a is b) # True
import asyncio
# Coroutine
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print("Started")
# Run coroutines sequentially
await say_after(1, 'Hello')
await say_after(2, 'World')
# Run coroutines concurrently
task1 = asyncio.create_task(say_after(1, 'Hello'))
task2 = asyncio.create_task(say_after(2, 'World'))
await task1
await task2
print("Finished")
# Run event loop
asyncio.run(main())
# Async HTTP requests
import aiohttp
async def fetch_url(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
'https://python.org',
'https://github.com',
'https://example.com'
]
tasks = [fetch_url(url) for url in urls]
pages = await asyncio.gather(*tasks)
for url, content in zip(urls, pages):
print(f"{url}: {len(content)} bytes")
asyncio.run(main())