<!-- Свое видео --><videowidth="320"height="240"controlsautoplayloopmutedposter="thumb.jpg"><sourcesrc="movie.mp4"></video><!-- YouTube --><iframewidth="320"height="200"src="https://youtube.com/embed/ID"allowfullscreen></iframe>
🖥️ PREVIEW
▶ ⏸ 🔊 ⚙️
▶
YouTube Iframe
Атрибут
Значения
Описание
controls
controls
Показать кнопки плеера
autoplay
autoplay
Автозапуск (требует muted)
loop
loop
Зациклить видео
poster
"image.jpg"
Обложка до загрузки
Аудио <audio>Media
Вставка аудио файлов с элементами управления воспроизведением.
CODE
<!-- Аудио плеер --><audiocontrolsautoplayloopmutedpreload="auto"><sourcesrc="audio.mp3"type="audio/mpeg"><sourcesrc="audio.ogg"type="audio/ogg"><sourcesrc="audio.wav"type="audio/wav">
Ваш браузер не поддерживает аудио.
</audio><!-- С субтитрами --><audiocontrols><sourcesrc="podcast.mp3"><trackkind="captions"src="subs.vtt"srclang="ru"></audio>
Все 22 типа полей ввода с атрибутами и визуальными примерами.
CODE
<formaction="/submit"method="POST"enctype="multipart/form-data"autocomplete="on"novalidate><!-- Текстовые поля --><inputtype="text"name="username"placeholder="Имя"required><inputtype="email"name="email"placeholder="Email"><inputtype="password"name="pass"minlength="6"><inputtype="tel"name="phone"pattern="[0-9]{10}"><inputtype="url"name="website"><inputtype="search"name="query"><!-- Числовые поля --><inputtype="number"name="age"min="0"max="100"><inputtype="range"name="volume"min="0"max="100"><!-- Дата и время --><inputtype="date"name="birthdate"><inputtype="time"name="meeting"><inputtype="datetime-local"name="event"><inputtype="month"name="billing"><inputtype="week"name="delivery"><!-- Выбор --><inputtype="color"name="favorite"><inputtype="file"name="document"accept=".pdf,.doc"><inputtype="checkbox"name="subscribe"><inputtype="radio"name="gender"value="male"><!-- Скрытые и кнопки --><inputtype="hidden"name="token"value="abc123"><inputtype="submit"value="Отправить"><inputtype="reset"value="Сброс"><inputtype="button"value="Кнопка"><inputtype="image"src="submit.png"><!-- Другие элементы --><selectname="city"><optionvalue="msk">Москва</option></select><textareaname="message"rows="4"></textarea><buttontype="submit">Отправить</button><datalistid="browsers"><optionvalue="Chrome"></datalist><outputname="result">0</output><progressvalue="70"max="100"></progress><metervalue="0.6"min="0"max="1"></meter><fieldset><legend>Группа полей</legend></fieldset></form>
✅ Скрытый контент теперь виден! Это работает без JavaScript.
Дополнительная СемантикаStructure
Фигуры, цитаты, время, адреса и другие семантические элементы.
CODE
<!-- Фигура с подписью --><figure><imgsrc="photo.jpg"alt="Фото"><figcaption>Подпись к фото</figcaption></figure><!-- Цитаты --><blockquotecite="url">Цитата</blockquote><q>Короткая цитата</q><!-- Время и адрес --><timedatetime="2024-01-01">1 января</time><address>Контакты автора</address><!-- Код и преформатирование --><pre>Сохраняет пробелы</pre><kbd>Ctrl+C</kbd><samp>Вывод программы</samp>
🖥️ PREVIEW
IMG
Подпись к фото
"Цитата с
blockquote"
🕐
⌨️
Ctrl+C📍
Москва
Встраивание КонтентаMedia
Встраивание внешнего контента, карт и объектов.
CODE
<!-- Iframe --><iframesrc="https://example.com"width="600"height="400"title="Описание"loading="lazy"sandbox="allow-scripts"></iframe><!-- Карта изображения --><imgsrc="map.png"usemap="#map"><mapname="map"><areashape="rect"coords="0,0,100,100"></map><!-- Canvas --><canvasid="myCanvas"width="200"height="100"></canvas><!-- SVG --><svgwidth="100"height="100"><circlecx="50"cy="50"r="40"/></svg>
🖥️ PREVIEW
🖼️ Iframe Placeholder
SVG Circle
Canvas
Атрибут
Значения
Описание
sandbox
"allow-scripts""allow-same-origin"
Ограничения для iframe
loading
"lazy""eager"
Ленивая загрузка
shape
"rect""circle""poly"
Форма области карты
...
SEO & Meta тегиSEO
Ключевые метатеги для SEO, соцсетей и правильного отображения сайта.
CODE
<head><title>Заголовок страницы</title><metaname="description"content="Краткое описание страницы"><metaname="keywords"content="html, css, js, python"><metaname="robots"content="index,follow"><!-- Open Graph --><metaproperty="og:title"content="Заголовок для соцсетей"><metaproperty="og:description"content="Описание для соцсетей"><metaproperty="og:image"content="https://site.com/preview.png"><!-- Canonical URL --><linkrel="canonical"href="https://site.com/page"></head>
🖥️ PREVIEW
Заголовок страницы
— site.com
https://site.com/page
Краткое описание страницы…
Заголовок для соцсетей
Описание для соцсетей
Canvas для рисованияGraphics
HTML5 элемент для программного рисования графики, анимаций и игр.
Асинхронное программирование и HTTP-запросы в современном JavaScript.
JAVASCRIPT
// async function: объявляет функцию, которая может использовать await и ВСЕГДА возвращает Promiseasync function fetchUserData(userId) {
// try: блок для кода, который может выбросить исключениеtry {
// await: ОСТАНАВЛИВАЕТ выполнение, пока fetch не вернёт ответ (без блокировки остального потока)const response = await fetch(`https://api.example.com/users/${userId}`);
// response.ok: проверяем что статус 2xx (200-299), иначе ошибка на сервереif (!response.ok) {
// throw выбросит ошибку, которую поймает catch блок нижеthrow newError(`HTTP error! status: ${response.status}`);
}
// response.json(): парсит тело ответа как JSON, возвращает Promiseconst userData = await response.json();
return userData;
} // catch: ловит ошибки из try (либо сетевые, либо выброшенные нами через throw)catch (error) {
console.error('Ошибка загрузки:', error);
throw error;
}
}
// Использование async функции: вызов должен быть внутри async функции или использовать .catch()async function loadUser() {
try {
// await: ждём результата fetchUserData (функция вернёт Promise, await распаковывает значение)const user = await fetchUserData(123);
console.log('Пользователь:', user);
} catch (error) {
console.error('Не удалось загрузить пользователя');
}
}
// Fetch с опциями: POST запрос с headers и bodyconst postData = await fetch('/api/posts', {
method: 'POST', // HTTP метод (по умолчанию GET)headers: {
'Content-Type': 'application/json'// сервер, содержимое - JSON
},
body: JSON.stringify({ title: 'Новый пост', content: 'Текст' }) // конвертируем объект в JSON строку
});
🖥️ PREVIEW
async/await делает асинхронный код читаемым, как синхронный.
Комментарий: Fetch API заменил XMLHttpRequest для HTTP-запросов.
# if-elif-else
age = 18if age < 13:
print("Ребенок")
elif age < 18:
print("Подросток")
else:
print("Взрослый")
# for циклfor i inrange(5):
print(i) # 0, 1, 2, 3, 4for i, val inenumerate(fruits):
print(i, val)
# while цикл
count = 0while count < 5:
print(count)
count += 1# break/continue/passfor i inrange(10):
if i == 5:
breakif i % 2 == 0:
continuepass# Пустая операция# List comprehension
squares = [x**2for x inrange(10)]
evens = [x for x inrange(10) if x % 2 == 0]
# Dict comprehension
squares_dict = {x: x**2for x inrange(5)}
🖥️ OUTPUT
range(5): 0, 1, 2, 3, 4
squares: [0, 1, 4, 9, 16, ...]
evens: [0, 2, 4, 6, 8]
Функции и методыFunctions
PYTHON
# Обычная функцияdefgreet(name):
returnf"Hello, {name}!"# Функция с параметрами по умолчаниюdefpower(base, exp=2):
return base ** exp
# Lambda функция
add = lambda x, y: x + y
# *args и **kwargsdefsum_all(*args):
returnsum(args)
defprint_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
# Аннотации типовdefadd(a: int, b: int) -> int:
return a + b
print(greet("Alice")) # Hello, Alice!print(power(2, 3)) # 8print(add(5, 3)) # 8print(sum_all(1, 2, 3)) # 6
Параметр
Описание
*args
Произвольное число позиционных
**kwargs
Произвольное число именованных
default
Параметр по умолчанию
: type
Аннотация типа параметра
-> type
Аннотация типа возврата
JSON и HTTP‑запросыWeb
PYTHON
import json
import requests # pip install requests# Словарь → JSON‑строка
data = {"name": "Alice", "age": 25}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
# JSON‑строка → словарь
parsed = json.loads(json_str)
# Простой GET‑запрос
resp = requests.get("https://api.example.com/user/1", timeout=5)
if resp.status_code == 200:
user = resp.json()
print(user["name"])
# POST с JSON‑телом
payload = {"title": "Hello", "body": "World"}
resp = requests.post("https://api.example.com/posts", json=payload, timeout=5)
print(resp.status_code)
🖥️ OUTPUT
json.dumps → { "name": "Alice", "age": 25 }
GET /user/1 → 200 OK, user["name"] = "Alice"
POST /posts → 201 Created
Классы и ООПOOP
PYTHON
classPerson:
# Конструкторdef__init__(self, name, age):
self.name = name
self.age = age
# Метод экземпляраdefgreet(self):
returnf"Hi, I'm {self.name}"# Метод класса@classmethoddeffrom_birth_year(cls, name, year):
age = 2024 - year
return cls(name, age)
# Статический метод@staticmethoddefis_adult(age):
return age >= 18# Строковое представлениеdef__str__(self):
returnf"{self.name}, {self.age} лет"# Свойство через @property@propertydefinfo(self):
returnf"{self.name} ({self.age})"# Создание объекта
person = Person("Alice", 25)
print(person.greet()) # Hi, I'm Aliceprint(person) # Alice, 25 летprint(person.info) # Alice (25)
# Чтение файлаwithopen("file.txt", "r", encoding="utf-8") as f:
content = f.read()
lines = f.readlines()
line = f.readline()
# Запись в файлwithopen("file.txt", "w", encoding="utf-8") as f:
f.write("Hello, World!")
f.writelines(["Line 1\n", "Line 2\n"])
# Добавлениеwithopen("file.txt", "a") as f:
f.write("\nNew line")
# Режимы открытия# "r" - чтение (по умолчанию)# "w" - запись (перезаписывает)# "a" - добавление в конец# "r+" - чтение и запись# "b" - бинарный режим# "x" - создание (ошибка если существует)# Работа с путемimport os
os.path.exists("file.txt")
os.path.isfile("file.txt")
os.path.isdir("folder")
os.remove("file.txt")
os.mkdir("folder")
Режим
Описание
r
Чтение (файл должен существовать)
w
Запись (создает или перезаписывает)
a
Добавление в конец
r+
Чтение и запись
b
Бинарный режим
x
Создание нового файла
Обработка исключенийError
PYTHON
try:
result = 10 / 0except ZeroDivisionError as e:
print(f"Ошибка: {e}")
except Exception as e:
print(f"Другая ошибка: {e}")
else:
print("Все хорошо")
finally:
print("Всегда выполняется")
# Вызов исключенияraise ValueError("Неверное значение")
# Создание своего исключенияclassMyError(Exception):
pass# Контекстный менеджерwithopen("file.txt") as f:
content = f.read()
# assertassert x > 0, "x должен быть положительным"
Исключение
Описание
ValueError
Неверное значение
TypeError
Неверный тип
KeyError
Ключ не найден в словаре
IndexError
Индекс вне диапазона
FileNotFoundError
Файл не найден
ZeroDivisionError
Деление на ноль
ImportError
Ошибка импорта
AttributeError
Атрибут не найден
Модули и импортыModules
PYTHON
# Импорт модуляimport math
print(math.sqrt(16)) # 4.0# Импорт конкретных функцийfrom datetime import datetime, date
# Импорт с алиасомimport numpy as np
# Импорт всегоfrom module import *
# Собственный модульfrom mymodule import my_function
# Установка пакетов# pip install package_name# pip install -r requirements.txt# Популярные модулиimport os # Операционная системаimport sys # Системные параметрыimport json # Работа с JSONimport re # Регулярные выраженияimport random # Случайные числаimport time # Время и задержкиimport pathlib # Пути к файлам
Итератор — это объект, который возвращает следующий элемент по запросу через next().
Генератор — удобный способ создать итератор с помощью yield.
Это полезно, когда не нужно хранить в памяти всю последовательность сразу: только текущий элемент.
Используйте генераторы для больших списков, потоковой обработки, файлов и последовательностей, которые создаются по требованию.
PYTHON
# Итератор
my_list = [1, 2, 3]
my_iter = iter(my_list)
next(my_iter) # 1next(my_iter) # 2# Генератор: возвращает числа по одному, экономя памятьdefcount_up_to(n):
count = 1while count <= n:
yield count
count += 1for num in count_up_to(5):
print(num) # 1 2 3 4 5# Генераторное выражение: ленивый квадрат
squares = (x**2for x inrange(10))
# первое значение берётся только при необходимостиprint(next(squares)) # 0# itertools: генераторы для бесконечных и комбинированных последовательностейfrom itertools import count, cycle, chain
for i in count(0, 2):
print(i) # 0, 2, 4...
🖥️ PREVIEW
⚡ Зачем использовать генераторы
Память: генератор не создает весь список сразу, он генерирует элементы по одному.
Когда: чтение больших файлов, работа с потоками, бесконечные последовательности и сложные вычисления.
Выгода: меньше памяти, быстрее старт, проще код для ленивых вычислений.
HTTP-запросы (requests)HTTP
Библиотека requests для простых REST‑API запросов и работы с JSON.
GET /users → 200 OK
[{ "id": 1, "name": "Vlad" }, ...]
POST /users → 201 CREATED
venv и pipEnv
Создание виртуального окружения и установка сторонних пакетов.
PYTHON
# Создать виртуальное окружение
python -m venv venv
# Активация (Windows)
venv\Scripts\activate
# Активация (macOS/Linux)
source venv/bin/activate
# Установка пакетов
pip install requests flask
# Заморозить зависимости
pip freeze > requirements.txt
# Установка из файла
pip install -r requirements.txt
🖥️ PREVIEW
project/
├─ venv/
├─ app.py
└─ requirements.txt
SQLite3 база данныхDB
Использование встроенной SQLite для хранения данных без отдельного сервера.
PYTHON
import sqlite3
# Подключение к файлу БД
conn = sqlite3.connect("app.db")
cursor = conn.cursor()
# Создание таблицы
cursor.execute(
"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)"
)
# Вставка данных
cursor.execute(
"INSERT INTO users (name, age) VALUES (?, ?)",
("Vlad", 25),
)
conn.commit()
# Чтение
cursor.execute("SELECT name, age FROM users")
rows = cursor.fetchall()
for name, age in rows:
print(name, age)
conn.close()
🖥️ PREVIEW
id
name
age
1
Vlad
25
2
Nadejda
e
23
Декораторы в PythonAdvanced
Функции, модифицирующие поведение других функций. Используются для логирования, кеширования, аутентификации.
PYTHON
import functools
import time
# ДЕКОРАТОР БЕЗ ПАРАМЕТРОВ: функция, которая принимает функцию и возвращает её обёрткуdef timer(func):
# @functools.wraps(func): копирует метаданные оригинальной функции (__name__, __doc__ и т.д.)
@functools.wraps(func)
# wrapper(*args, **kwargs): внутренняя функция, которая может принять ЛЮБЫЕ аргументыdef wrapper(*args, **kwargs):
start = time.time()
# func(*args, **kwargs): вызываем оригинальную функцию с переданными аргументами
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f}s")
return result
# ВАЖНО: возвращаем wrapper, а не result! (wrapper становится новой функцией)return wrapper
# ДЕКОРАТОР С ПАРАМЕТРАМИ: вложенные функции (repeat(times) -> decorator -> wrapper)def repeat(times):
# times запоминается в замыкании (closure) для использования в wrapperdef decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# Цикл повторяет вызов функции заданное количество разfor _ inrange(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
# Использование: @timer и @repeat(3) - это синтаксический сахар для slow_function = timer(slow_function)
@timer
def slow_function():
time.sleep(1)
# @repeat(3): сначала вызывается repeat(3), потом результат (decorator) применяется к greet
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
# slow_function теперь это wrapper, который отмеряет время выполнения оригинальной функции
slow_function() # Выведет: slow_function took 1.00s# greet теперь это wrapper, который вызывает оригинальную greet 3 раза
greet("World") # Выведет "Hello, World!" три раза
🖥️ OUTPUT
slow_function took 1.00s
Hello, World! Hello, World! Hello, World!
Декоратор
Назначение
@functools.wraps
Сохраняет метаданные оригинальной функции
@property
Создает геттеры/сеттеры
@staticmethod
Статические методы класса
SQLAlchemy Полная Справка
Объектно-реляционный менеджер SQLAlchemy: настройка, модели, сессии, CRUD и связи.
Установка и подключение SQLAlchemySetup
Подготовка проекта, создание движка и сессии.
PYTHON
# Установка SQLAlchemy и адаптера БД
pip install sqlalchemy psycopg2-binary
# Подключение к базе и создание сессии
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL, echo=True) # Лог SQL-запросов
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# Функция для получения сессии
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
🖥️ PREVIEW
SQLAlchemy создает единый движок для всех моделей.
SessionLocal управляет транзакциями и жизненным циклом соединения.
Модель SQLAlchemy и таблицаModels
Создание модели через Declarative Base и представление таблицы.
PYTHON
# Описание модели пользователя
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Boolean
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
email = Column(String, unique=True, index=True)
is_active = Column(Boolean, default=True)
# Удобный метод для отображения моделиdef __repr__(self):
return f"<User id={self.id} name={self.name}>"
🖥️ PREVIEW
Модель User становится таблицей users с колонками id, name, email, is_active.
CRUD сессии SQLAlchemyCRUD
Примеры создания, чтения, обновления и удаления через сессию.
PYTHON
# Создание нового пользователя
user = User(name="Anna", email="anna@example.com")
db.add(user) # Добавление в транзакцию
db.commit() # Сохранение в базе
db.refresh(user) # Обновление объекта полями из БД# Чтение данных
user = db.query(User).filter(User.email == "anna@example.com").first()
# Обновление записи
user.name = "Anna Ivanova"
db.commit()
# Удаление записи
db.delete(user)
db.commit()
🖥️ PREVIEW
db.commit сохраняет изменения, db.refresh обновляет объект из базы.
db.query(User) возвращает объекты модели User.
Связи и отношенияRelations
Пример связи One-to-Many между Users и Articles.
PYTHON
# Связь One-to-Many
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class Article(Base):
__tablename__ = "articles"
id = Column(Integer, primary_key=True)
title = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey("users.id"))
user = relationship("User", back_populates="articles")
User.articles = relationship("Article", back_populates="user", cascade="all, delete-orphan")
🖥️ PREVIEW
Каждый Article связан с одним User, а User может иметь множество статей.
Back_populates обеспечивает синхронные объекты на обеих сторонах отношения.
SQLAlchemy + FastAPIFastAPI
Повтор примера интеграции SQLAlchemy в FastAPI.
PYTHON
# Настройка движка и сессии
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Float
from fastapi import Depends
DATABASE_URL = "postgresql://user:pass@localhost/dbname"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# Модель SQLAlchemyclass Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
price = Column(Float)
# Функция зависимости для FastAPI
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/products")
async defget_products(db: Session = Depends(get_db)):
return db.query(Product).all()
@app.post("/products")
async defcreate_product(name: str, price: float, db: Session = Depends(get_db)):
product = Product(name=name, price=price)
db.add(product)
db.commit()
db.refresh(product)
return product
🖥️ PREVIEW
FastAPI использует Depends для получения SQLAlchemy-сессии в роуте.
db.commit сохраняет объект, db.refresh заполняет поля из БД.
SQLAlchemy + FlaskFlask
Повтор примера работы с Flask-SQLAlchemy и моделями.
PYTHON
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://user:pass@localhost/db'
db = SQLAlchemy(app)
# Определение моделейclass User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
# Операции с БД
@app.route('/create-user', methods=['POST'])
def create_user():
user = User(username='john', email='john@example.com')
db.session.add(user)
db.session.commit()
return jsonify({'id': user.id})
@app.route('/users')
def get_users():
users = User.query.all()
return jsonify([{'id': u.id, 'username': u.username} for u in users])
@app.route('/user/<int:user_id>')
def get_user(user_id):
user = User.query.get_or_404(user_id)
return jsonify({'id': user.id, 'username': user.username})
🖥️ PREVIEW
Flask-SQLAlchemy использует db.session для транзакций.
User.query и db.session упрощают запросы к данным.
SQL Полная Справка
Полный путь от базовых запросов до аналитики, транзакций, оптимизации и практик
проектирования БД
CREATE TABLE и связиDDL
SQL
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
city TEXT
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
total DECIMAL(10,2),
created_at DATE,
FOREIGN KEY (user_id) REFERENCES users(id)
);
🖥️ PREVIEW
Таблица
Колонки
Ключи
users
id, name, city
PK: id
orders
id, user_id, total, created_at
PK: id, FK: user_id → users.id
INSERT / UPDATE / DELETEDML
SQL
INSERT INTO users (id, name, city) VALUES
(1, 'Vlad', 'Moscow'),
(2, 'Nadia', 'Kazan');
UPDATE users
SET city = 'Saint Petersburg'WHERE id = 2;
DELETE FROM users
WHERE id = 99;
🖥️ PREVIEW
Изменение данных в таблице без
изменения структуры.
Rows affected: 2 INSERT, 1 UPDATE, 0 DELETE
JOIN: объединение таблицJOIN
SQL
SELECT u.name, o.total, o.created_at
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE o.total >= 1000
ORDER BY o.created_at DESC;
🖥️ PREVIEW
name
total
created_at
Vlad
1990.00
2026-04-10
Nadia
1250.00
2026-04-11
Агрегации и GROUP BYAnalytics
SQL
SELECT user_id,
COUNT(*) AS orders_count,
SUM(total) AS total_sum,
AVG(total) AS avg_total
FROM orders
GROUP BY user_id
HAVINGSUM(total) > 1500;
🖥️ PREVIEW
user_id
orders_count
total_sum
avg_total
1
3
4200.00
1400.00
Индексы и производительностьPerf
SQL
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);
EXPLAIN QUERY PLANSELECT * FROM orders WHERE user_id = 1;
🖥️ PREVIEW
SEARCH orders USING INDEX idx_orders_user_id (user_id=?)
Индекс сокращает полный скан таблицы и
ускоряет фильтрацию по `user_id`.
Типы JOIN (полная карта)JOIN
SQL
-- INNER JOINSELECT u.name, o.total
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- LEFT JOINSELECT u.name, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- CROSS JOINSELECT u.name, p.period
FROM users u
CROSS JOIN (SELECT'Q1'AS period UNION ALL SELECT'Q2') p;
🖥️ PREVIEW
INNER: пересечение, LEFT: все из
левой, CROSS: декартово произведение.
CTE и рекурсияAdvanced
SQL
WITH RECURSIVE nums(n) AS (
-- БАЗОВЫЙ CASE (anchor): начальное условие рекурсии - генерируем первую строкуSELECT 1
-- UNION ALL: объединяем базовый case с рекурсивным (ВАЖНО: ALL, а не UNION - иначе дубли удалятся!)UNION ALL-- РЕКУРСИВНЫЙ CASE: берём предыдущий результат и добавляем 1, ПОКА n < 5 (условие выхода)SELECT n + 1 FROM nums WHERE n < 5
)
SELECT * FROM nums;
-- NON-RECURSIVE CTE (просто сохраняем подзапрос для переиспользования):WITH top_orders AS (
SELECT * FROM orders WHERE total >= 1000
)
SELECT * FROM top_orders;
🖥️ PREVIEW
n
1
2
3
4
5
Оконные функцииWindow
SQL
-- Оконные функции: вычисления над группами строк БЕЗ коллапса (в отличие от GROUP BY)SELECT
user_id,
total,
-- ROW_NUMBER(): порядковый номер в окне (1,2,3...) даже если значения одинаковыеROW_NUMBER() OVER (PARTITION BY user_id ORDER BY total DESC) AS rn,
-- LAG(): получить значение из предыдущей строки в окне (для трендов, сравнения с предыдущим заказом)LAG(total) OVER (PARTITION BY user_id ORDER BY created_at) AS prev_total
-- PARTITION BY: разделить результаты на группы по user_id (отдельное окно для каждого юзера)FROM orders;
🖥️ PREVIEW
user_id=1, total=1990, rn=1, prev_total=960
Подзапросы и EXISTSSubquery
SQL
SELECT name
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id AND o.total > 1000
);
SELECT name
FROM users
WHERE id IN (
SELECT user_id FROM orders
);
🖥️ PREVIEW
name
Vlad
Nadia
Транзакции и ACIDTCL
SQL
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
-- при ошибке:ROLLBACK;
🖥️ PREVIEW
Atomicity: обе операции применяются
вместе или откатываются вместе.
VIEW, TRIGGER, PROCEDUREDB Objects
SQL
CREATE VIEW active_users ASSELECT id, name FROM users WHERE id > 0;
CREATE TRIGGER trg_orders_ai
AFTER INSERT ON orders
BEGININSERT INTO logs(message) VALUES ('order inserted');
END;
Денормализация допустима для аналитики
и ускорения чтения.
Операции над наборамиSet Ops
SQL
SELECT name FROM users_moscow
UNIONSELECT name FROM users_kazan;
SELECT name FROM active_users
INTERSECTSELECT name FROM paid_users;
SELECT name FROM all_users
EXCEPTSELECT name FROM blocked_users;
SELECT
name,
CASEWHEN age < 18 THEN'minor'WHEN age >= 18 THEN'adult'ELSE'unknown'ENDAS age_group,
COALESCE(city, 'N/A') AS city_safe
FROM users;
🖥️ PREVIEW
`CASE` добавляет условные категории
прямо в выборке, `COALESCE` подставляет значение вместо `NULL`.
UPSERT (INSERT OR UPDATE)DML
SQL
INSERT INTO users (id, name, city)
VALUES (1, 'Vlad', 'Moscow')
ON CONFLICT (id)
DO UPDATE SET
name = EXCLUDED.name,
city = EXCLUDED.city;
🖥️ PREVIEW
UPSERT полезен для синхронизации: если
строка есть — обновляем, если нет — создаем.
Изменение схемы без потерьMigration
SQL
ALTER TABLE users ADD COLUMN phone TEXT;
UPDATE users SET phone = 'unknown'WHERE phone IS NULL;
ALTER TABLE users ALTER COLUMN phone SET NOT NULL;
-- безопасное переименованиеALTER TABLE users RENAME COLUMN city TO location;
🖥️ PREVIEW
Правильная миграция: добавить колонку,
заполнить данные, затем усиливать ограничения.
SQL Cheat SheetReference
QUICK REFERENCE
-- 1) DDL: сначала создаем структуруCREATE TABLE table_name (
id INTEGER PRIMARY KEY,
col1 TEXT NOT NULL,
col2 INTEGER,
UNIQUE (col1),
CHECK (col2 >= 0),
DEFAULT 0
);
ALTER TABLE table_name ADD COLUMN created_at DATE;
CREATE INDEX idx_table_col1 ON table_name(col1);
-- 2) DML: заполняем и изменяем данныеINSERT INTO table_name (col1, col2) VALUES ('A', 10);
UPDATE table_name SET col2 = 20 WHERE col1 = 'A';
DELETE FROM table_name WHERE col1 = 'B';
-- 3) DQL: правильный порядок SELECTSELECT col1, SUM(col2) AS total
FROM table_name
WHERE col2 > 0
GROUP BY col1
HAVINGSUM(col2) >= 10
ORDER BY total DESCLIMIT 10;
-- 4) TCL: оборачиваем критичные изменения в транзакциюBEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- или ROLLBACK;-- 5) DCL: права доступаGRANT SELECT, INSERT ON table_name TO analyst_user;
REVOKE INSERT ON table_name FROM analyst_user;
🖥️ PREVIEW
Как писать SQL по шагам: DDL (структура) → DML (данные) → DQL (чтение)
→ TCL (безопасность изменений) → DCL (доступы).
Комментарий: блок SELECT в шпаргалке расположен в корректном синтаксическом
порядке:
SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT.
Комментарий: транзакции (BEGIN/COMMIT/ROLLBACK) используйте для денежных и
критичных операций, чтобы избежать частично примененных изменений.
Оконные функцииAdvanced
Функции, работающие с окнами строк. Позволяют вычислять агрегаты без группировки.
SQL
SELECT
name,
salary,
department,
-- ROW_NUMBER(): простой порядковый номер (1,2,3,4) - каждой строке свой номерROW_NUMBER() OVER (ORDER BY salary DESC) AS overall_rank,
-- RANK(): пропускает номера при одинаковых значениях (1,2,2,4 - скачок через 3)RANK() OVER (ORDER BY salary DESC) AS rank_with_ties,
-- DENSE_RANK(): не пропускает номера (1,2,2,3 - нет скачков)DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank,
-- AVG(salary) OVER (PARTITION BY department): средняя зарплата ПО ОТДЕЛУ (разное значение для каждого отдела)AVG(salary) OVER (PARTITION BY department) AS dept_avg,
-- LAG(salary, 1): берёт значение из предыдущей строки (полезно для сравнения с предыдущим рядом)LAG(salary) OVER (ORDER BY hire_date) AS prev_salary
FROM employees;
🖥️ PREVIEW
name
salary
dept_avg
overall_rank
Alice
100000
95000
1
Bob
95000
95000
2
Charlie
95000
95000
2
Комментарий: ROW_NUMBER уникален, RANK пропускает позиции при равенстве, DENSE_RANK нет.
Функция
Описание
ROW_NUMBER()
Уникальный номер строки
RANK()
Ранг с пропусками
LAG()/LEAD()
Доступ к предыдущим/следующим строкам
PostgreSQL Полная Справка
От установки до production: типы, индексы, JSONB, транзакции, администрирование,
мониторинг и оптимизация
Установка и подключениеSetup
PSQL
-- Подключение к серверу
psql -h localhost -p 5432 -U postgres -d app_db
-- Проверка версии и текущей БДSELECT version();
SELECT current_database();
-- Создание пользователя и БДCREATE ROLE app_user WITH LOGIN PASSWORD'StrongPass123';
CREATE DATABASE app_db OWNER app_user;
🖥️ PREVIEW
Сервер PostgreSQL запущен, база
`app_db` и роль `app_user` готовы для приложения.
Комментарий: сначала создается
отдельная роль приложения, затем база назначается владельцу — это безопаснее, чем
работать под `postgres` в проде.
Типы данных PostgreSQLTypes
SQL
CREATE TABLE events (
id BIGSERIAL PRIMARY KEY,
event_uuid UUID NOT NULL,
title TEXT NOT NULL,
price NUMERIC(10,2),
tags TEXT[],
payload JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
🖥️ PREVIEW
Тип
Где применять
UUID
публичные идентификаторы
JSONB
гибкая структура данных
TIMESTAMPTZ
даты/время с часовым поясом
Комментарий: выбор
правильных типов влияет на производительность, точность данных и корректную работу с
часовыми поясами.
Ограничения и целостностьSchema
SQL
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
age INT CHECK (age >= 13),
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
total NUMERIC(10,2) CHECK (total >= 0)
);
🖥️ PREVIEW
`CHECK`, `UNIQUE` и `FK` защищают
данные от некорректных значений и «висячих» связей.
Комментарий: ограничения лучше
задавать в БД, а не только в коде приложения — это последняя линия защиты целостности.
Индексы и EXPLAIN ANALYZEPerf
SQL
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_events_payload_gin ON events USING GIN(payload);
CREATE INDEX idx_orders_paid_partial ON orders(id) WHERE total > 0;
EXPLAIN ANALYZESELECT * FROM orders WHERE user_id = 42;
🖥️ PREVIEW
Index Scan using idx_orders_user_id on orders (actual time=0.08..0.15 rows=18 loops=1)
Комментарий: `EXPLAIN
ANALYZE` показывает реальный план и время — используйте его для проверки, что запрос
действительно идет по индексу.
JSONB: хранение и поискJSONB
SQL
-- JSONB: тип данных PostgreSQL для хранения JSON документов с индексацией-- payload->>'status': извлекает значение (как text) по ключу 'status'SELECT id, payload->>'status'AS status
FROM events
-- @>: оператор "содержит": проверяет содержит ли payload JSON объект {"priority":"high"}-- Этот запрос очень быстр, если есть GIN индекс на payload!WHERE payload @> '{"priority":"high"}'::jsonb;
-- jsonb_set(): безопасно обновляет конкретный путь в JSON без полной перезаписиUPDATE events
SET payload = jsonb_set(payload, '{status}', '"processed"'::jsonb)
-- {status}: JSON путь (как в объекте: payload['status'] в коде)-- ВАЖНО: используем jsonb_set вместо полной перезаписи! (atomicity, MVCC)WHERE id = 1;
🖥️ PREVIEW
JSONB позволяет хранить
полуструктурированные данные и быстро фильтровать их с GIN-индексами.
Комментарий: оператор `@>` проверяет
вхождение JSON-объекта, а `jsonb_set` безопасно обновляет конкретный путь без полной
перезаписи документа.
CTE и оконные функцииAnalytics
SQL
-- CTE (Common Table Expression) в PostgreSQL: вспомогательный SELECT, на который можно ссылатьсяWITH monthly AS (
-- Подзапрос CTE: вычисляем сумму заказов (revenue) за каждый месяц для каждого пользователяSELECT user_id, date_trunc('month', created_at) AS m, SUM(total) AS revenue
FROM orders
-- GROUP BY: группируем по user_id и месяцу (m), SUM - агрегирует по этим группамGROUP BY user_id, m
)
SELECT user_id, m, revenue,
-- RANK() OVER (PARTITION BY user_id ORDER BY revenue DESC): ранг дохода внутри каждого user_id-- PARTITION BY: разделяет результаты на окна по user_id (отдельный ранг для каждого пользователя)-- ORDER BY revenue DESC: ранжируем в порядке убывания доходаRANK() OVER (PARTITION BY user_id ORDER BY revenue DESC) AS revenue_rank
-- Источник: используем CTE monthly вместо подзапроса (более читаемо!)FROM monthly;
🖥️ PREVIEW
user_id
month
revenue
rank
1
2026-04
2950.00
1
Комментарий: CTE
делает сложный запрос читаемым, а оконная функция дает ранг без потери исходных строк.
Транзакции и уровни изоляцииACID
SQL
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
-- при ошибке: ROLLBACK;
🖥️ PREVIEW
Для финансовых операций используйте
транзакции и корректный уровень изоляции, чтобы избежать гонок и грязных чтений.
Комментарий: `REPEATABLE READ`
фиксирует снимок данных внутри транзакции и снижает риск непредсказуемых результатов.
Роли, права, backup/restoreAdmin
ADMIN
CREATE ROLE readonly NOLOGIN;
GRANT CONNECT ON DATABASE app_db TO readonly;
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
-- Политика построчного доступа (RLS)ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY orders_owner_policy ON orders
USING (user_id = current_setting('app.user_id')::bigint);
-- Резервная копия и восстановление
pg_dump -Fc -U postgres -d app_db -f app_db.dump
pg_restore -U postgres -d app_db_new app_db.dump
🖥️ PREVIEW
Минимальные права по ролям +
регулярный `pg_dump` — базовая стратегия безопасной эксплуатации PostgreSQL.
Комментарий: RLS ограничивает строки
на уровне БД, даже если в приложении где-то пропущена проверка доступа.
Расширения PostgreSQLExtensions
SQL
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS citext;
CREATE TABLE accounts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email CITEXT UNIQUE NOT NULL
);
🖥️ PREVIEW
`pgcrypto` дает безопасный UUID, а
`citext` делает email-поля регистронезависимыми.
Комментарий: расширения включаются
отдельно в каждой базе и должны быть учтены в миграциях.
Партиционирование таблицScale
SQL
CREATE TABLE logs (
id BIGSERIAL,
created_at DATE NOT NULL,
payload JSONB
) PARTITION BY RANGE (created_at);
CREATE TABLE logs_2026_04 PARTITION OF logs
FOR VALUES FROM ('2026-04-01') TO ('2026-05-01');
🖥️ PREVIEW
Данные автоматически раскладываются по
партициям; старые партиции можно архивировать или удалять отдельно.
Комментарий: партиционирование
особенно полезно для больших time-series таблиц и политики retention.
Materialized ViewReporting
SQL
CREATE MATERIALIZED VIEW mv_monthly_revenue ASSELECT date_trunc('month', created_at) AS month, SUM(total) AS revenue
FROM orders
GROUP BY month;
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_revenue;
🖥️ PREVIEW
Материализованное представление хранит
предрасчитанный результат и ускоряет аналитические дашборды.
Комментарий: `CONCURRENTLY` позволяет
обновлять view без долгой блокировки чтения (при наличии уникального индекса).
VACUUM, ANALYZE, AutovacuumMaintenance
SQL
VACUUM orders;
ANALYZE orders;
VACUUM (VERBOSE, ANALYZE) orders;
-- Проверка активности autovacuumSELECT relname, n_live_tup, n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;
🖥️ PREVIEW
`VACUUM` чистит мертвые версии строк,
`ANALYZE` обновляет статистику для оптимизатора.
Комментарий: без актуальной статистики
планировщик может выбрать медленный план даже при наличии индексов.
Мониторинг и диагностикаObservability
SQL
SELECT pid, usename, state, wait_event_type, query
FROM pg_stat_activity
WHERE state <> 'idle';
SELECT locktype, relation::regclass, mode, granted
FROM pg_locks
WHERE relation IS NOT NULL;
🖥️ PREVIEW
Через `pg_stat_activity` видно долгие
запросы, через `pg_locks` — блокировки, мешающие транзакциям.
Комментарий: это первый шаг при
жалобах на “тормозит БД” и “все зависло”.
Алгоритмы Полная Справка
От Big O и базовых структур до графов, динамического программирования и практики
собеседований
Big O и оценка сложностиBase
REFERENCE
O(1)-- доступ по индексуO(log n)-- бинарный поискO(n)-- линейный проходO(n log n)-- эффективные сортировкиO(n^2)-- двойные циклы, bubble/selectionO(2^n)-- полный перебор подмножествO(n!)-- перестановки
🖥️ PREVIEW
Комментарий: Big O сравнивает
масштабируемость алгоритмов при росте входных данных, а не абсолютное время в
миллисекундах.
Массивы, HashMap, два указателяPatterns
PYTHON + JS
# Python: Two Sum (O(n))def two_sum(nums, target):
seen = {}
for i, x inenumerate(nums):
if target - x in seen:
return [seen[target - x], i]
seen[x] = i
// JS: max sum subarray of size k (sliding window)function maxWindowSum(arr, k) {
let sum = 0, best = -Infinity;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
if (i >= k) sum -= arr[i - k];
if (i >= k - 1) best = Math.max(best, sum);
}
return best;
}
🖥️ PREVIEW
Комментарий: HashMap помогает перейти
от O(n²) к O(n), а sliding window убирает повторные вычисления в подмассивах.
СортировкиSorting
PYTHON
def merge_sort(arr):
iflen(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
out = []
i = j = 0while i < len(left) and j < len(right):
if left[i] <= right[j]:
out.append(left[i]); i += 1else:
out.append(right[j]); j += 1return out + left[i:] + right[j:]
🖥️ PREVIEW
Алгоритм
Сложность
Стабильность
Merge Sort
O(n log n)
Да
Quick Sort
O(n log n) avg
Нет
Heap Sort
O(n log n)
Нет
Бинарный поискSearch
JAVASCRIPT
function binarySearch(arr, target) {
let l = 0, r = arr.length - 1;
while (l <= r) {
const m = (l + r) >> 1;
if (arr[m] === target) return m;
if (arr[m] < target) l = m + 1;
else r = m - 1;
}
return -1;
}
🖥️ PREVIEW
Комментарий: бинарный поиск работает
только на отсортированных данных и делит область поиска пополам на каждом шаге.
Стек и очередьDS
PYTHON
from collections import deque
# Stack (LIFO)
stack = []
stack.append(10)
stack.append(20)
top = stack.pop() # 20# Queue (FIFO)
q = deque([1, 2])
q.append(3)
first = q.popleft() # 1
🖥️ PREVIEW
Комментарий: стек часто применяют для
парсинга/скобок/DFS, очередь — для BFS и задач с обработкой по порядку.
Связные списки и указателиLinkedList
PYTHON
def reverse_list(head):
prev = None
cur = head
while cur:
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
return prev
# Floyd cycle detection: slow/fast pointers
🖥️ PREVIEW
Комментарий: техника slow/fast
pointers позволяет находить цикл без дополнительной памяти O(1).
Деревья и обходыTree
JAVASCRIPT
function inorder(root, out = []) {
if (!root) return out;
inorder(root.left, out);
out.push(root.val);
inorder(root.right, out);
return out;
}
🖥️ PREVIEW
Обход
Порядок
Применение
Preorder
Root-Left-Right
Сериализация
Inorder
Left-Root-Right
Отсортированный вывод BST
Postorder
Left-Right-Root
Удаление/сворачивание дерева
Графовые алгоритмыGraph
PYTHON
import heapq
def dijkstra(graph, start):
dist = {v: float('inf') for v in graph}
dist[start] = 0
pq = [(0, start)]
while pq:
d, v = heapq.heappop(pq)
if d != dist[v]:
continuefor to, w in graph[v]:
nd = d + w
if nd < dist[to]:
dist[to] = nd
heapq.heappush(pq, (nd, to))
return dist
🖥️ PREVIEW
Комментарий: Дейкстра ищет кратчайшие
пути в графе с неотрицательными весами через приоритетную очередь.
Рекурсия и BacktrackingSearch
PYTHON
def subsets(nums):
res = []
def dfs(i, path):
if i == len(nums):
res.append(path[:]); return
dfs(i + 1, path)
path.append(nums[i])
dfs(i + 1, path)
path.pop()
dfs(0, [])
return res
🖥️ PREVIEW
Комментарий: backtracking перебирает
дерево решений с откатом, что подходит для комбинаций, перестановок и constraint-задач.
Динамическое программированиеDP
JAVASCRIPT
-- Динамическое программирование (DP): сохранение результатов подзадач, чтобы избежать пересчетаfunction fibDP(n) {
-- Базовый случай: F(0)=0, F(1)=1if (n <= 1) return n;
-- dp[i] будет хранить результат для i-го числа Фибоначчи (табуляция)const dp = Array(n + 1).fill(0);
-- Инициализация: F(1) = 1
dp[1] = 1;
-- Итеративное заполнение: F(i) = F(i-1) + F(i-2) (строим решение снизу вверх)for (let i = 2; i <= n; i++) {
-- Каждый результат вычисляется ровно один раз и хранится в dp
dp[i] = dp[i - 1] + dp[i - 2];
}
-- Временная сложность: O(n) вместо O(2^n) для наивной рекурсии!return dp[n];
}
🖥️ PREVIEW
Комментарий: DP сокращает
экспоненциальный перебор за счет хранения результатов подзадач (memoization/tabulation).
Жадные алгоритмыGreedy
PYTHON
-- Жадный алгоритм для max non-overlapping intervals (выбираем максимум не пересекающихся интервалов)def max_non_overlap(intervals):
-- Сортируем интервалы по конечной точке (ключевой шаг жадного выбора!)
intervals.sort(key=lambda x: x[1])
-- end: конец последнего выбранного интервала (инициализируем -бесконечность)
end = -10**9-- cnt: количество выбранных интервалов
cnt = 0-- Жадный выбор: берём интервал, если его начало >= конца последнего выбранногоfor l, r in intervals:
if l >= end:
-- Интервалы не пересекаются, добавляем его
cnt += 1
end = r
return cnt
🖥️ PREVIEW
Комментарий: greedy берет локально
лучшее решение; работает, только если задача обладает свойством жадного выбора.
Строковые алгоритмыStrings
PYTHON
-- KMP prefix function: для каждой позиции i вычисляет длину наибольшего префикса-суффиксаdef prefix_function(s):
-- pi[i] = длина наибольшего собственного префикса s[0..i], который также суффикс
pi = [0] * len(s)
for i inrange(1, len(s)):
-- j: текущая позиция для сравнения (начинаем с конца предыдущего совпадения)
j = pi[i - 1]
-- Если s[i] != s[j], откатываемся к предыдущему совпадениюwhile j > 0and s[i] != s[j]:
-- j = pi[j-1]: переходим к следующему более короткому префиксу-суффиксу
j = pi[j - 1]
-- Если символы совпали, увеличиваем длину совпаденияif s[i] == s[j]:
j += 1
pi[i] = j
-- Результат: массив pi используется в KMP для поиска за O(n+m) без отката!return pi
🖥️ PREVIEW
Комментарий: префикс-функция — основа
KMP для поиска подстроки за O(n + m) без отката по тексту.
Roadmap по алгоритмамRoadmap
🖥️ PREVIEW
Этап
Темы
Цель
1
Big O, массивы, hashmap, two pointers
Уверенная база
2
Сортировки, бинарный поиск, стек/очередь
Шаблоны задач
3
Деревья, графы, DFS/BFS, shortest path
Средний+ уровень
4
DP, greedy, backtracking, string algorithms
Сложные задачи
Комментарий: эффективная практика —
решать 2-3 задачи в день с обязательным разбором сложности и альтернативных решений.
Сегментное деревоData Structures
Структура данных для эффективных запросов на диапазонах и обновлений элементов.
PYTHON
class SegmentTree:
def __init__(self, arr):
self.n = len(arr)
self.tree = [0] * (4 * self.n)
self.build(arr, 0, 0, self.n - 1)
def build(self, arr, node, start, end):
if start == end:
self.tree[node] = arr[start]
return
mid = (start + end) // 2
self.build(arr, 2*node+1, start, mid)
self.build(arr, 2*node+2, mid+1, end)
self.tree[node] = self.tree[2*node+1] + self.tree[2*node+2]
def query(self, node, start, end, l, r):
if r < start or end < l:
return0if l <= start and end <= r:
return self.tree[node]
mid = (start + end) // 2
left = self.query(2*node+1, start, mid, l, r)
right = self.query(2*node+2, mid+1, end, l, r)
return left + right
# Использование
arr = [1, 3, 5, 7, 9, 11]
st = SegmentTree(arr)
print(st.query(0, 0, 5, 1, 3)) # Сумма с 1 по 3: 3+5+7=15
🖥️ PREVIEW
Сегментное дерево позволяет выполнять запросы суммы/минимума на диапазоне за O(log n).
Комментарий: подходит для задач с частыми обновлениями и запросами на диапазонах.
Операция
Сложность
Build
O(n)
Query
O(log n)
Update
O(log n)
FastAPI Полная Справка
Современный асинхронный фреймворк для создания REST API с автоматической документацией
Установка и запускSetup
Установка FastAPI и ASGI сервера Uvicorn
BASH
# Установка FastAPI и Uvicorn
pip install fastapi uvicorn[standard]
# Опционально: для работы с БД
pip install sqlalchemy psycopg2-binary pydantic
# Запуск сервера
uvicorn main:app --reload
# На production
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
🖥️ PREVIEW
Сервер запущен на http://localhost:8000
Документация доступна на http://localhost:8000/docs (Swagger)
ReDoc доступен на http://localhost:8000/redoc
Основные методы и роутыRouting
GET, POST, PUT, DELETE запросы с параметрами пути и query
PYTHON
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# GET - получение данных
@app.get("/items")
async defget_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
# GET с параметром пути
@app.get("/items/{item_id}")
async defget_item(item_id: int):
return {"item_id": item_id}
# Модель Pydanticclass Item(BaseModel):
name: str
price: float
is_offer: bool = None# POST - создание
@app.post("/items")
async defcreate_item(item: Item):
return {"created": item}
# PUT - обновление
@app.put("/items/{item_id}")
async defupdate_item(item_id: int, item: Item):
return {"updated": item_id, "item": item}
# DELETE - удаление
@app.delete("/items/{item_id}")
async defdelete_item(item_id: int):
return {"deleted": item_id}
🖥️ PREVIEW
Автоматическая валидация данных через Pydantic
Интерактивная документация в /docs
Поддержка асинхронного кода с async/await
Зависимости и AuthenticationSecurity
Внедрение зависимостей и аутентификация через JWT токены
PYTHON
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
security = HTTPBearer()
SECRET_KEY = "your-secret-key"# Функция зависимостиasync defget_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
try:
token = credentials.credentials
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
user_id = payload.get("sub")
if user_id isNone:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
return user_id
except jwt.InvalidTokenError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
# Использование зависимости
@app.get("/me")
async defget_me(user_id: str = Depends(get_current_user)):
return {"user_id": user_id}
# Middleware для логирования
@app.middleware("http")
async deflog_requests(request, call_next):
response = await call_next(request)
return response
🖥️ PREVIEW
Зависимости автоматически внедряются в функции
JWT токены для безопасной передачи данных
Middleware для кроссплатформенной обработки
Работа с БД и SQLAlchemyDatabase
Интеграция с SQLAlchemy ORM
PYTHON
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Float
DATABASE_URL = "postgresql://user:pass@localhost/dbname"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# Модель SQLAlchemyclass Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
price = Column(Float)
# Использование в FastAPIdef get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/products")
async defget_products(db: Session = Depends(get_db)):
return db.query(Product).all()
@app.post("/products")
async defcreate_product(name: str, price: float, db: Session = Depends(get_db)):
product = Product(name=name, price=price)
db.add(product)
db.commit()
db.refresh(product)
return product