Media is too big
VIEW IN TELEGRAM
В этом видео автор объясняет, как работать с модулем os в Python для взаимодействия с операционной системой.
Разбирается выполнение команд через терминал, навигация по файловой системе, работа с путями и управление файлами. Всё показано на простых примерах, которые легко повторить самостоятельно.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3⚡2
Async ORM в Python: SQLModel/Tortoise 🆚 SQLAlchemy
Синхронные ORM вроде SQLAlchemy блокируют потоки на время запросов к БД — в асинхронных приложениях это убивает всю пользу asyncio. Async ORM работают на корутинах и не блокируют event loop, позволяя обрабатывать тысячи одновременных подключений.
🔄 SQLAlchemy: синхронный подход (блокирующий)
➡️ Каждый запрос занимает поток. В async-приложениях нужны тред-пулы, что усложняет архитектуру.
⚡️ SQLModel: асинхронная обёртка над SQLAlchemy
➡️ Полная совместимость с SQLAlchemy + асинхронность. Идеально для миграции.
🐢 Tortoise ORM: нативный async-подход
➡️ Вдохновлен Django ORM — простой и понятный синтаксис.
📊 Сравнение производительности
➡️ Async ORM в 5-7 раз быстрее при высокой нагрузке благодаря отсутствию блокировок.
🛠 Работа с отношениями: SQLModel
➡️ Полная поддержка отношений как в SQLAlchemy + Pydantic валидация.
🛠 Работа с отношениями: Tortoise
➡️ Простой Django-like синтаксис с автоматическими обратными связями.
🔧 Экосистема и сообщество
🌐 Использование с FastAPI
➡️ Идеальная интеграция с современными async-фреймворками.
🗣️ Запомни: Выбирай Tortoise для новых async-проектов за его простоту и производительность.
Синхронные ORM вроде SQLAlchemy блокируют потоки на время запросов к БД — в асинхронных приложениях это убивает всю пользу asyncio. Async ORM работают на корутинах и не блокируют event loop, позволяя обрабатывать тысячи одновременных подключений.
# ❌ Блокирует поток на время выполнения запроса
from sqlalchemy.orm import Session
def get_users_sync():
with Session(engine) as session:
users = session.query(User).all() # Поток заблокирован
return users
# ✅ Не блокирует event loop
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
async def get_users_async():
async with AsyncSession(engine) as session:
result = await session.exec(select(User)) # Освобождает loop
return result.all()
# ✅ Специально разработан для асинхронности
from tortoise.models import Model
from tortoise import fields
class User(Model):
name = fields.CharField(max_length=255)
email = fields.CharField(max_length=255)
async def get_users_native():
return await User.all() # Чистый async API
# Тест: 1000 одновременных запросов
# SQLAlchemy + threads: ~15 сек, 1.2 GB RAM
# SQLModel: ~2.8 сек, 620 MB RAM
# Tortoise: ~2.3 сек, 512 MB RAM
🛠 Работа с отношениями: SQLModel
class Team(SQLModel, table=True):
id: int | None = Field(primary_key=True)
name: str
users: List["User"] = Relationship(back_populates="team")
class User(SQLModel, table=True):
team_id: int | None = Field(foreign_key="team.id")
team: Optional[Team] = Relationship(back_populates="users")
🛠 Работа с отношениями: Tortoise
class Team(Model):
name = fields.CharField(max_length=255)
users: fields.ReverseRelation["User"]
class User(Model):
name = fields.CharField(max_length=255)
team: fields.ForeignKeyRelation[Team] = fields.ForeignKeyField(
"models.Team", related_name="users"
)
⚡️ Миграции и инструменты🟢 SQLAlchemy: Требует Alembic, сложная настройка🟢 SQLModel: Работает через Alembic, наследует сложности SQLAlchemy🟢 Tortoise: Встроенная система миграций, простая настройка
🟢 SQLAlchemy: Огромное сообщество, все возможные расширения🟢 SQLModel: Молодой, но растущий проект, полная совместимость🟢 Tortoise: Зрелый async-ориентированный фреймворк
# SQLModel интеграция
from fastapi import FastAPI
from sqlmodel.ext.asyncio.session import AsyncSession
app = FastAPI()
@app.get("/users")
async def get_users(session: AsyncSession = Depends(get_session)):
result = await session.exec(select(User))
return result.all()
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍2
import - механизм подключения модулейВ Python
import используется для подключения модулей (файлов с кодом) в текущую программу.1. Импорт всего модуля
import math
print(math.sqrt(16)) # 4.0
2. Импорт с псевдонимом (alias)
import numpy as np
print(np.pi) # 3.141592653589793
3. Импорт конкретных объектов
from math import sqrt, pi
print(sqrt(25)) # 5.0
print(pi) # 3.141592653589793
4. Импорт всех объектов (*) ❗ (не рекомендуется)
from math import *
print(sin(0)) # 0.0
⚠️ Минус: может вызвать конфликты имён.
5. Импорт из пользовательского модуля (my_module.py)
import my_module
my_module.hello()
Если модуль в другой папке, нужно добавить его в
sys.path:
import sys
sys.path.append("path/to/module")
import my_module
Python ищет модуль в следующем порядке:
1️⃣ Стандартные модули (
math, random, os)2️⃣ Текущая директория (папка, где запускается скрипт)
3️⃣ Пути из
sys.pathЕсли модуль не найден, возникает
ModuleNotFoundError.import позволяет использовать готовый код и организовать программу, разбивая её на модули.Please open Telegram to view this post
VIEW IN TELEGRAM
⚡1👍1
HTTP/3 работает поверх QUIC (UDP). Меньше задержек, параллельные стримы, нет head-of-line блокировки. Для Python это новая эра веб-сервисов.
from aioquic.asyncio.client import connect
async with connect("example.com", 443, alpn_protocols=["h3"]) as client:
stream_id = client.get_next_available_stream_id()
client.send_headers(stream_id, [(":method", "GET"), (":path", "/")])
client.send_eof(stream_id)
📡 Сервер на aioquic
from aioquic.asyncio import serve
from aioquic.h3.connection import H3_ALPN
async def handler(stream_id, request):
return [(b":status", b"200")], b"Hello QUIC!"
await serve("0.0.0.0", 4433, configuration=my_tls_config,
alpn_protocols=H3_ALPN, stream_handler=handler)
QUIC = несколько потоков внутри одного соединения.
id1 = client.get_next_available_stream_id()
id2 = client.get_next_available_stream_id()
client.send_headers(id1, [...])
client.send_headers(id2, [...])
QUIC всегда шифрован.
Пока через uvicorn-h3 (экспериментально).
uvicorn app:app --http h3 --port 4433
🟢 API с большим количеством параллельных запросов🟢 real-time (чаты, стримы)🟢 мобильные клиенты с нестабильной сетью
❌ Минусы
🔴 Поддержка в браузерах уже есть, но в Python всё ещё эксперимент.🔴 aioquic — низкоуровневый, нужно писать руками.🔴 Поддержка в фреймворках только зарождается.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥2❤1
Графы — не про математику, а про связи. Пользователи, друзья, транзакции, сервисы — всё это графы. Python и современные БД делают их работу простой и мощной.
Создадим и изучим связи между объектами:
import networkx as nx
G = nx.Graph()
G.add_edges_from([('Alice', 'Bob'), ('Bob', 'Eve'), ('Alice', 'Eve')])
print(nx.shortest_path(G, 'Alice', 'Eve'))
print(nx.degree_centrality(G))
import matplotlib.pyplot as plt
nx.draw(G, with_labels=True, node_color='lightblue', node_size=1500)
plt.show()
GraphQL от Facebook — не база, а язык запросов к API.
query = """
{
user(id: "1") {
name
friends {
name
}
}
}
"""
from ariadne import QueryType, make_executable_schema, graphql_sync
type_defs = """
type Query {
hello: String!
}
"""
query = QueryType()
@query.field("hello")
def resolve_hello(_, info):
return "GraphQL + Python!"
schema = make_executable_schema(type_defs, query)
Python-драйвер для Neo4j:
from neo4j import GraphDatabase
driver = GraphDatabase.driver("bolt://localhost:7687")
with driver.session() as session:
result = session.run("MATCH (a)-[r]->(b) RETURN a,b LIMIT 5")
for record in result:
print(record)
MATCH (user:Person)-[:FRIEND]->(friend)
WHERE user.name = "Alice"
RETURN friend.name
Анализируешь связи в NetworkX, сохраняешь их в Neo4j, а отдаёшь клиенту через GraphQL API.
Полный цикл: анализ → хранение → доступ.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤2⚡2
DevOps — это не только YAML и Terraform. Python — идеальный клей между инфраструктурой, API и конфигами. Он управляет тем, что не умеет Ansible, и дополняет Terraform там, где HCL бессилен.
Когда тебе нужно сгенерировать
.tf на лету или вызывать Terraform из пайплайна:import subprocess, json
vars = {"region": "eu-west-1", "env": "prod"}
with open("vars.tf.json", "w") as f:
json.dump(vars, f)
subprocess.run(["terraform", "apply", "-auto-approve"])
Каждый Ansible-модуль — это обычный Python-скрипт.
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec={"msg": {"required": True, "type": "str"}}
)
module.exit_json(changed=False, msg=f"Hello {module.params['msg']}!")
if __name__ == "__main__":
main()
Python — король SDK. AWS, GCP, Azure, GitLab, Kubernetes — всё управляется через API.
import boto3
ec2 = boto3.client('ec2')
for i in ec2.describe_instances()['Reservations']:
print(i['Instances'][0]['InstanceId'])
import json
inventory = {
"all": {
"hosts": ["web1", "web2"],
"vars": {"ansible_user": "ubuntu"}
}
}
print(json.dumps(inventory))
Python идеально вписывается в пайплайны:
🟢 валидирует .tf перед применением,🟢 вызывает Ansible с нужными параметрами,🟢 парсит логи и метрики.
import subprocess
subprocess.run(["ansible-playbook", "deploy.yml", "-e", "env=staging"])
import requests
resp = requests.get("https://my-service/health")
if resp.status_code != 200:
print("⚠️ Service down!")
🔵 Terraform хорош для декларации, но не для логики.🔵 Ansible конфигурирует, но не анализирует.🔵 Python делает и то, и другое: управляет, проверяет, комбинирует.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥2❤1
yield и зачем он реально нужен в Pythonyield — это не return. Он не завершает функцию, а паузит её и отдаёт результат по частям.
def gen():
yield 1
yield 2
yield 3
for x in gen():
print(x)
1, 2, 3 — не сразу, а по одному.Функция работает до первого `yield`, потом «засыпает» и продолжает дальше.
🧾 Чтение большого файла без нагрузки
def read_lines(path):
with open(path) as f:
for line in f:
yield line.strip()
for line in read_lines("huge.log"):
print(line)
Если файл весит 10 ГБ — всё равно работает.
Никаких
readlines(), которые жрут память.
def counter():
n = 0
while True:
yield n
n += 1
for i in counter():
if i > 5:
break
print(i)
yield тут не обойтись.Можно генерировать бесконечный поток, но обрабатывать его как обычный список.
def even_only(numbers):
for n in numbers:
if n % 2 == 0:
yield n
nums = [1, 2, 3, 4, 5, 6]
for x in even_only(nums):
print(x)
filter(), а свой контролируемый фильтр. Гибко и понятно.yield — это когда ты генерируешь данные на лету.Ты не ждёшь весь список, не держишь всё в памяти — просто отдаёшь, когда нужно.
Нужен потоковый режим?
yield — лучший друг.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤3
Media is too big
VIEW IN TELEGRAM
В этом видео автор показывает, как создавать функции в Python: как объявлять их, передавать аргументы и использовать возвращаемые значения.
Разъясняется, зачем нужны функции: они позволяют разбивать код на логические блоки, упрощать повторное использование и улучшать читаемость.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥3❤2
AI-инструменты теперь реально помогают Python-разработчикам: рефакторят, комментируют и ловят ошибки быстрее, чем линтер. Но как ими пользоваться с умом, а не превращать проект в тестовую свалку?
Наивно:
def calc(x, y):
return x*y + x/y - x**y + y/x
def calc(x, y):
if y == 0:
raise ValueError("y не может быть нулём")
return (x * y) + (x / y) - pow(x, y) + (y / x)
Наивно:
def get_data(a):
return json.loads(a)
def get_data(a: str) -> dict:
"""Парсит JSON-строку в словарь"""
return json.loads(a)
Наивно:
data=[1,2,3,4,5]
print(sum([i for i in data if i>2]))
data = [1, 2, 3, 4, 5]
print(sum(i for i in data if i > 2))
Наивно:
def add(a,b): return a+b
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
Наивно:
result = func1(func2(func3(data)))
temp = func3(data)
temp = func2(temp)
result = func1(temp)
AI-комментарий:
# Этот код группирует пользователей по стране и считает активных
Наивно:
os.system(f"rm -rf {user_input}")subprocess.run(["rm", "-rf", user_input], check=True)
AI может за тебя создать CRUD, REST API, Dockerfile, CI pipeline — по описанию.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9😁4👍3🔥1
Media is too big
VIEW IN TELEGRAM
В этом видео автор показывает, как строить логику приложения на Python через использование циклов.
Разбирается, когда и как использовать `for` и `while`, как контролировать ход выполнения, организовывать условия внутри циклов и выстраивать структуру программы для решения конкретных задач.
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡3🔥3❤1
enumerate() добавляет счётчик к итерации.fruits = ["🍎", "🍌", "🍇"]
for i, fruit in enumerate(fruits):
print(i, fruit)
0 🍎
1 🍌
2 🍇
Please open Telegram to view this post
VIEW IN TELEGRAM
🍌8❤5👍3🔥1👀1
sequence[start:stop:step]
🔹
start – начальный индекс (по умолчанию 0).🔹
stop – конечный индекс (не включается!).🔹
step – шаг (по умолчанию 1).
lst = [0, 1, 2, 3, 4, 5]
print(lst[1:4]) # [1, 2, 3] (элементы с индекса 1 по 3)
print(lst[:3]) # [0, 1, 2] (с начала до индекса 2)
print(lst[::2]) # [0, 2, 4] (каждый второй элемент)
print(lst[::-1]) # [5, 4, 3, 2, 1, 0] (разворот списка)
⚡ Итог: срезы позволяют легко работать с последовательностями без циклов и лишнего кода!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2
Когда pandas начинает задыхаться на гигабайтах данных — не надо переписывать код.
Просто меняешь библиотеку — и Python начинает считать на всех ядрах и даже на кластере.
import pandas as pd
df = pd.read_csv("data.csv")
df.groupby("city").sum()
🧩 Dask подключает все ядра
import dask.dataframe as dd
df = dd.read_csv("data.csv")
df.groupby("city").sum().compute()
Всё летит параллельно.
from dask.distributed import Client
client = Client("tcp://scheduler:8786")
Каждая нода тянет свой кусок данных.
import modin.pandas as pd
df = pd.read_csv("data.csv")
df.groupby("city").sum()
Многоядерность включается автоматически.
🧠 Dask + ML = масштаб
from dask_ml.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X, y)
Больше данных — та же логика.
dask-scheduler &
dask-worker tcp://localhost:8786
localhost:8787 — видишь граф задач, загрузку CPU, память.dask-ctl deploy kubernetes --replicas 8
Kubernetes, AWS, GCP — всё поддерживается.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍4🔥2❤🔥1
В Python можно распаковывать коллекции в аргументы или структуры — это мощно.
def f(*args, **kwargs):
print(args, kwargs)
f(1, 2, x=10) # (1, 2), {'x': 10}
nums = [1, 2, 3]
print(*nums) # 1 2 3
params = {"sep": " | "}
print(1, 2, 3, **params) # 1 | 2 | 3
a, *middle, b = [1, 2, 3, 4, 5]
print(middle) # [2, 3, 4]
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3🔥3
Когда тебе нужно не просто «читать» блокчейн, а управлять смарт-контрактами — Web3.py становится твоим ключом. Ни лишней магии, просто Python и прямой доступ к Ethereum (или совместимым сетям).
📡 Подключение к сети
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://mainnet.infura.io/v3/<token>"))
print(w3.is_connected())
balance = w3.eth.get_balance("0x742d35Cc6634C0532925a3b844Bc454e4438f44e")
print(w3.from_wei(balance, 'ether'))📦 Отправка транзакции
tx = {
'to': '0xRecipientAddress',
'value': w3.to_wei(0.01, 'ether'),
'gas': 21000,
'gasPrice': w3.to_wei('50', 'gwei'),
'nonce': w3.eth.get_transaction_count(sender),
}
signed = w3.eth.account.sign_transaction(tx, private_key)
w3.eth.send_raw_transaction(signed.rawTransaction)abi = json.load(open("contract.abi"))
address = "0xContractAddress"
contract = w3.eth.contract(address=address, abi=abi)value = contract.functions.getData().call()
print(value)
tx = contract.functions.setData(42).build_transaction({
'from': sender,
'nonce': w3.eth.get_transaction_count(sender),
'gas': 200000,
'gasPrice': w3.to_wei('40', 'gwei')
})
signed_tx = w3.eth.account.sign_transaction(tx, private_key)
w3.eth.send_raw_transaction(signed_tx.rawTransaction)events = contract.events.DataChanged.create_filter(fromBlock='latest')
for e in events.get_all_entries():
print(e.args)
block = w3.eth.get_block('latest')
print(block['number'], block['miner'])msg = "Verify ownership"
signed_msg = w3.eth.account.sign_message(encode_defunct(text=msg), private_key)
print(signed_msg.signature.hex())
from eth_account.messages import encode_defunct
signer = w3.eth.account.recover_message(encode_defunct(text=msg), signature=signed_msg.signature)
print(signer)
Комбинируешь Web3.py с FastAPI:
@app.get("/balance/{addr}")
def get_balance(addr):
return {"balance": w3.from_wei(w3.eth.get_balance(addr), 'ether')}Поднимаешь Ethereum-ноду в Docker и подключаешь к Web3.py.
Инфраструктура, тесты, деплой — всё автоматизируется питоновским кодом.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Media is too big
VIEW IN TELEGRAM
В этом видео автор рассказывает, где используется Python и какие реальные задачи он помогает решать — от веб-разработки и анализа данных до машинного обучения и автоматизации процессов.
Показываются основные направления, в которых язык особенно силён, и примеры, как Python используется в крупных проектах и компаниях.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👎1
Когда Python начинает тормозить на тяжёлых вычислениях — не надо бросаться в C. Rust решает проблему безопасно и быстро, а PyO3 делает мост между ними почти без боли.
import rustlib
print(rustlib.sum_numbers([1, 2, 3, 4, 5]))
use pyo3::prelude::*;
#[pyfunction]
fn sum_numbers(nums: Vec<i64>) -> i64 {
nums.iter().sum()
}
#[pymodule]
fn rustlib(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_numbers, m)?)?;
Ok(())
}
maturin develop
#[pyfunction]
fn fib(n: u64) -> u64 {
match n {
0 => 0,
1 => 1,
_ => fib(n-1) + fib(n-2),
}
}
PyO3 сам управляет ссылками, не нужно мучиться с GIL и утечками.
Rust-функции безопасно возвращают значения прямо в Python.
#[pyfunction]
async fn download(url: String) -> PyResult<String> {
Ok(reqwest::get(&url).await?.text().await?)
}
use numpy::{PyArray1, IntoPyArray};
#[pyfunction]
fn double(arr: &PyArray1<f64>) -> Py<PyArray1<f64>> {
let data = arr.as_slice().unwrap();
let doubled: Vec<f64> = data.iter().map(|x| x * 2.0).collect();
Python::with_gil(|py| doubled.into_pyarray(py).to_owned())
}Парсинг, криптография, машинное обучение, обработка JSON — всё, где Python не справляется, Rust добивает.
Cargo + maturin интегрируются в CI/CD.
Сборка Rust-модулей в .whl пакеты — нативно, быстро, кроссплатформенно.
from rustlib import fib
print(fib(35))
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥4👍2
Когда скрипт превращается в утилиту — ты становишься ближе к DevOps-богу.
Больше никаких
print("enter value:"). Теперь у тебя интерактив, цвет, автодополнение и команды как в Git.name = input("Введите имя: ")
print(f"Привет, {name}!")from rich.console import Console
from rich.table import Table
console = Console()
table = Table(title="Users")
table.add_column("ID", style="cyan")
table.add_column("Name", style="green")
table.add_row("1", "Alice")
table.add_row("2", "Bob")
console.print(table)
from rich.progress import track
import time
for _ in track(range(5), description="Processing..."):
time.sleep(0.5)
from prompt_toolkit import prompt
from prompt_toolkit.completion import WordCompleter
langs = WordCompleter(["Python", "Go", "Rust", "Java"])
lang = prompt("Выбери язык: ", completer=langs)
print(f"Твой выбор: {lang}")
from prompt_toolkit.validation import Validator, ValidationError
validator = Validator.from_callable(
lambda t: t.isdigit(),
error_message="Нужно число!",
)
age = prompt("Возраст: ", validator=validator)
import typer
app = typer.Typer()
@app.command()
def greet(name: str):
print(f"Привет, {name}!")
@app.command()
def add(x: int, y: int):
print(x + y)
if __name__ == "__main__":
app()
python app.py greet Alice или python app.py add 2 3 — чисто и понятно.python app.py --help
--help, --version, и описание аргументов.from rich.console import Console
import typer
console = Console()
app = typer.Typer()
@app.command()
def fancy(name: str):
console.print(f"[bold green]Привет, {name}![/bold green]")
if __name__ == "__main__":
app()
@app.command()
def choose():
from prompt_toolkit import prompt
color = prompt("Твой любимый цвет: ")
console.print(f"[{color}]Вот как выглядит твой цвет![/]")
poetry build
pip install dist/mycli-0.1.0-py3-none-any.whl
mycli fancy Alice
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡5❤3
Media is too big
VIEW IN TELEGRAM
В этом видео автор разбирает, почему Python называют лучшим языком для новичков и с какими трудностями можно столкнуться на практике.
Обсуждаются ключевые преимущества языка — простота, универсальность, широкий выбор библиотек, а также его слабые стороны — скорость, зависимость от интерпретатора и ограничения при масштабных проектах.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2🖕1
Когда код повторяется или хочется динамики без копипаста, Python умеет писать сам себя. AST и метапрограммирование — ключ к мощным и компактным решениям.
def make_adder(x):
return lambda y: x + y
add5 = make_adder(5)
print(add5(10))
🛠 Изменение классов после определения
class A: pass
A.new_attr = 42
print(A.new_attr)
📜 Использование type для создания классов
MyClass = type("MyClass", (object,), {"x": 10})
print(MyClass().x)import ast
tree = ast.parse("a = 1 + 2")
print(ast.dump(tree))
code = compile(tree, filename="<ast>", mode="exec")
exec(code)
print(a)
def log_calls(fn):
def wrapper(*args, **kwargs):
print(f"Calling {fn.__name__}")
return fn(*args, **kwargs)
return wrapper
@log_calls
def foo(): pass
foo()
class Meta(type):
def __new__(cls, name, bases, dct):
dct["hello"] = lambda self: print("Hello")
return super().__new__(cls, name, bases, dct)
class A(metaclass=Meta): pass
A().hello()
📦 Генерация кода для API
for i in range(3):
exec(f"def func{i}(): print('Function {i}')")
func1()
def make_test(n):
code = f"def test_{n}(): return {n} * 2"
exec(code)
make_test(5)
print(test_5())
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4
Когда код начинает напоминать магические заклинания, а бизнес хочет «писать на языке предметной области» — пора сделать DSL.
Domain-Specific Language в Python — это не парсер, не компилятор, а читаемый API, который звучит как человеческий язык.
create_user("alice", "admin", True, "2025-10-27")user = (UserBuilder()
.named("alice")
.with_role("admin")
.active(True)
.created_today())
class UserBuilder:
def __init__(self):
self.user = {}
def named(self, name):
self.user["name"] = name; return self
def with_role(self, role):
self.user["role"] = role; return self
def active(self, flag):
self.user["active"] = flag; return self
def created_today(self):
self.user["created"] = "2025-10-27"; return self
self — и цепочка становится мини-языком.infra = (Server("app")
.runs("nginx")
.exposes(80)
.depends_on("db"))Ни YAML, ни JSON — только Python, но читается как Terraform.
def pipeline():
source("data.csv")
filter("age > 18")
transform("normalize")
output("report.json")
model = (train()
.on("dataset.csv")
.using("RandomForest")
.tune(max_depth=10)
.evaluate("accuracy"))
class DSL:
def __enter__(self): print("start")
def __exit__(self, *a): print("end")
with DSL():
do("something")
class Rule:
def __getitem__(self, key):
return f"IF {key} THEN alert"
rule = Rule()
print(rule["cpu > 90%"])
🧩 9. Декораторы как ключевые слова DSL
@task("extract")
def extract_data(): ...
@task("transform")
def transform_data(): ...q = SELECT("name", "age").FROM("users").WHERE("age > 18").ORDER_BY("name")given(user="admin").when(login).then(see_dashboard)
🧩 12. Генерация собственного синтаксиса
from textx import metamodel_from_str
grammar = '''
Model: statements*=Statement;
Statement: name=ID '=' value=INT;
'''
meta = metamodel_from_str(grammar)
model = meta.model_from_str("x = 5\ny = 10")
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍3🔥1