В Python есть модуль
itertools с кучей мощных инструментов 👇
from itertools import count
for i in count(1):
print(i)
👉 Вывод:
1
2
3
...
count(1) создаёт бесконечный генератор чисел начиная с 1📌 Можно указать шаг:
from itertools import count
for i in count(0, 5):
print(i)
👉 Результат:
0
5
10
15
...
🔥 Полезно для:
— генерации ID
— бесконечных циклов
— работы с потоками данных
⚠️ Осторожно: цикл реально бесконечный 😄
#python #itertools
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
🧙♂️Секреты f-строк: выражения, форматирование и даже вызов функций внутри f-строки
Ты думал, f-строки — это просто
А что если я скажу, что туда можно засовывать функции, арифметику и даже условия?
Вот мощный разбор, как выжать максимум из f-строк в Python👇
🟢 1. Арифметика прямо в строке
🟢 Внутри фигурных скобок можно писать полноценные выражения.
➡️ Да хоть
🟢 2. Функции внутри f-строки
🟢 Вызов функций? Да. Лямбды? Тоже можно. Даже
🟢 3. Условия и тернарные выражения
🟢 Отлично работает с любыми
🟢 4. Форматирование чисел по-человечески
➡️
➡️
🟢 5. Форматирование по ширине и выравниванию
🟢 Работает с числами и строками. Полезно в логах и таблицах.
🟢 6. Форматирование как hex, bin, oct
👍
👍
👍
🟢 7. Вложенные f-строки и шаблоны
🟢 Иногда полезно, но лучше избегать слишком сложной вложенности.
💡 Запомни
✅ f-строки — это не просто вставка переменных
✅ Используй форматирование, условия, вызовы функций
✅ Удобно для логов, отчётов, динамического UI, и шаблонов CLI
🗣️ Хочешь пост про
Ты думал, f-строки — это просто
f"Hello {name}"?А что если я скажу, что туда можно засовывать функции, арифметику и даже условия?
Вот мощный разбор, как выжать максимум из f-строк в Python
a, b = 10, 3
print(f"Сумма: {a + b}, Разность: {a - b}")
f"Результат: {(a * b) ** 2}" — это законно.def shout(name):
return name.upper() + "!"
print(f"Привет, {shout('Алиса')}")
f"{sorted([3,1,2])}" работает.age = 20
print(f"{'Совершеннолетний' if age >= 18 else 'Несовершеннолетний'} пользователь")
if ... else внутри {}.value = 12345.6789
print(f"{value:.2f}") # 12345.68
print(f"{value:,.2f}") # 12,345.68
:.2f — два знака после запятой:, — добавляет разделитель тысячname = "Alice"
print(f"{name:>10}") # справа
print(f"{name:<10}") # слева
print(f"{name:^10}") # по центру
num = 42
print(f"{num:b}") # 101010
print(f"{num:x}") # 2a
b — двоичнаяx — шестнадцатеричнаяo — восьмеричнаяuser = {"name": "Eva", "points": 120}
print(f"{user['name']} набрала {f'{user['points'] * 2}'} очков")format() против f-строк, или как делать шаблоны с f-строками? Предложи тему — сделаем!Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤1
Минимальный бот — буквально в несколько строк 👇
from telegram import Update
from telegram.ext import ApplicationBuilder, MessageHandler, filters, ContextTypes
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text(update.message.text)
app = ApplicationBuilder().token("TOKEN").build()
app.add_handler(MessageHandler(filters.TEXT, echo))
app.run_polling()
📌 Установка:
pip install python-telegram-bot
💡 Что делает бот:
— получает сообщение
— отправляет его обратно
🔥 Дальше можно добавить:
— команды
— кнопки
— базы данных
— AI / API
🚀 Отличный старт для своих Telegram-проектов
#python #telegram #bot
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍1
👟
Активировал окружение — и весь мир пакетов идёт в твою папку, а не в систему.
📦 Шаг 1 — создай окружение в корне проекта
➡️ Появится папка
🔑 Шаг 2 — активируй окружение
➡️ Подсказка терминала сменится на
⚙️ Шаг 3 — обнови pip (сначала всегда так)
➡️ Берёшь свежую версию установщика, меньше странных ошибок.
📥 Шаг 4 — ставь библиотеки
➡️ Всё уезжает в
🔎 Шаг 5 — смотри, что внутри
➡️ Видишь только пакеты твоего окружения, не всей машины.
🧾 Шаг 6 — фиксируй зависимости
➡️ Снимок версий. Его же можно отдать коллегам или CI.
🚚 Шаг 7 — восстановление на другой машине
➡️ Получишь те же версии пакетов, что и у автора.
🧪 Проверка — пакет реально в
➡️ Должен увидеть путь к твоему
🧹 Шаг 8 — удаление/выход
➡️
🛠 Быстрые фишки (когда что-то идёт не так)
➡️ Унификация через
🗂 Бонус — не коммить
➡️ Окружение — локальное. В репо нужен только
🗣️ Запомни:
pip + venv: ставим библиотеки изолированно — и это работаетvenv делает песочницу для проекта.pip ставит пакеты внутрь неё.Активировал окружение — и весь мир пакетов идёт в твою папку, а не в систему.
# Windows
py -m venv .venv
# macOS / Linux
python3 -m venv .venv
.venv — там свой Python и свой pip.# PowerShell
.\.venv\Scripts\Activate.ps1
# cmd
.\.venv\Scripts\activate.bat
# macOS / Linux
source .venv/bin/activate
(.venv) — ты внутри.python -m pip install --upgrade pip
pip install requests
pip install "uvicorn[standard]" fastapi
.venv. Глобальная система не трогается.🔎 Шаг 5 — смотри, что внутри
pip list
pip show requests
🧾 Шаг 6 — фиксируй зависимости
pip freeze > requirements.txt
# в новом клоне проекта
python -m venv .venv
# активируй (как в Шаге 2)
pip install -r requirements.txt
venvpython -c "import requests, sys; print(sys.prefix)"
.venv. Значит всё изолировано.pip uninstall requests
deactivate
deactivate возвращает тебя в глобальную среду.# pip "не находится" — запускай через интерпретатор
python -m pip --version
# несколько Python — выбери конкретный
# Windows:
py -3.11 -m venv .venv
# macOS / Linux:
python3.11 -m venv .venv
# PowerShell ругается на Activate.ps1:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
python -m pip и явный выбор версии решают 90% проблем.venvecho .venv/ >> .gitignore
requirements.txt.venv — граница проекта, pip — грузовик с пакетами.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Списки – это изменяемые последовательности, обычно используемые для хранения однотипных данных (хотя Python не запрещает хранить в них данные разных типов). Представлены классом
list.Кортежи – это неизменяемые последовательности, обычно используемые, чтобы хранить разнотипные данные. Представлены классом
tuple.На уровне языка отличаются тем, что в кортеж нельзя добавить или убрать элемент. На уровне интерпретатора различий нет. Обе коллекции представлены массивом указателей на структуру
PyObject.Существуют специальные функции для работы со списками. Они вызываются методами списка. Ниже приведены наиболее часто используемые:
# Создаем исходный список
lst = [1, 2, 3]
# append(x): добавляет элемент в конец списка
lst.append(4)
# Теперь lst = [1, 2, 3, 4]
# extend(iterable): расширяет список, добавляя элементы из итерируемого объекта
lst.extend([5, 6])
# Теперь lst = [1, 2, 3, 4, 5, 6]
# insert(i, x): вставляет элемент x на позицию i
lst.insert(0, 'start')
# Теперь lst = ['start', 1, 2, 3, 4, 5, 6]
# remove(x): удаляет первое вхождение элемента x
lst.remove(3)
# Теперь lst = ['start', 1, 2, 4, 5, 6]
# pop([i]): удаляет и возвращает элемент на позиции i (по умолчанию последний)
last = lst.pop()
# last = 6, а lst = ['start', 1, 2, 4, 5]
# sort(): сортирует список на месте
lst = [3, 1, 4, 1, 5, 9, 2]
lst.sort()
# Теперь lst = [1, 1, 2, 3, 4, 5, 9]
# reverse(): разворачивает список на месте
lst.reverse()
# Теперь lst = [9, 5, 4, 3, 2, 1, 1]
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
В Python можно передать список как отдельные аргументы с помощью
* 👇
def add(a, b, c):
print(a + b + c)
nums = [1, 2, 3]
add(*nums)
👉 Результат:
6
add(*nums)
Python превращает это в:
add(1, 2, 3)
📌 Работает и с кортежами:
coords = (10, 20)
print(*coords)
🔥 Очень полезно при:
— работе с функциями
— динамических данных
— распаковке API-ответов
🚀
*args и распаковка - одна из самых удобных фишек Python#python #фишки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2
enumerate() добавляет счётчик к итерации.fruits = ["🍎", "🍌", "🍇"]
for i, fruit in enumerate(fruits):
print(i, fruit)
0 🍎
1 🍌
2 🍇
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Иногда нужно быстро создать QR‑код: для ссылки, текста, визитки или даже Wi‑Fi‑пароля. Python справляется с этим буквально за пару строк.
Давай разберём, как это делается и что внутри происходит.
pip install qrcode[pil]
qrcode. В скобках [pil] — сразу тянет Pillow для работы с изображениями.import qrcode
img = qrcode.make("https://example.com")
img.save("qrcode.png")
make сразу создаёт изображение, которое можно сохранить или отдать пользователю.Обычно хочется чуть больше контроля: размер, плотность, уровень защиты от ошибок, цвета.
Для этого создаём QR‑код «вручную»:
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data("Hello, QR!")
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
img.save("custom_qr.png")
version — размер сетки (1 — минимальный);error_correction — сколько данных можно потерять и всё ещё прочитать код;box_size и border — масштаб и рамку.А если хочется добавить логотип или иконку — тоже просто:
Создаём QR‑код с высоким уровнем коррекции ошибок и «вклеиваем» логотип по центру:
from PIL import Image
logo = Image.open("logo.png")
qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
qr.add_data("https://mysite.com")
qr.make(fit=True)
qr_img = qr.make_image(fill_color="black", back_color="white").convert("RGB")
pos = (
(qr_img.size[0] - logo.size[0]) // 2,
(qr_img.size[1] - logo.size[1]) // 2,
)
qr_img.paste(logo, pos)
qr_img.save("qr_with_logo.png")
Высокий уровень коррекции (
ERROR_CORRECT_H) позволяет восстанавливать данные даже при частичном перекрытии.Просто текст → картинка → готово.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🔥2
Каждый Python-разработчик использует
pip, но далеко не все понимают, насколько критична дисциплина в управлении зависимостями. Ошибки здесь = боль на проде, в CI и при сборке.pip install some-library # ❌
python -m venv venv
source venv/bin/activate
pip install some-library
Если ты не фиксируешь версии — ты играешь в лотерею.
pip install requests
Через месяц выйдет новая мажорная версия — и твой код может отвалиться.
pip install requests==2.31.0
pip freeze > requirements.txt
pip install -U some-lib # по умолчанию может подтянуть несовместимости
--upgrade-strategy only-if-needed, если хочешь избегать каскадных обновлений.Иногда
pip старый, и ты получаешь ошибки вроде "metadata generation failed".pip install -U pip
pip install pip-tools
Работает как
pip freeze, но человечно:# requirements.in
requests==2.31.0
flask>=2.0
pip-compile requirements.in # генерирует requirements.txt с зависимостями
pip-tools следит за всем остальным.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤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❤1🤔1
В Python у тебя есть мощный способ скрыть логику за обычным доступом к атрибутам — и имя ему
@property.Пример:
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def area(self):
return math.pi * self._radius ** 2
Теперь:
c = Circle(3)
print(c.area) # 28.27...
area выглядит как поле, но за ним — код. Удобно, безопасно и читаемо.1. Когда значение вычисляется "на лету"
@property
def is_active(self):
return self.last_seen > datetime.now() - timedelta(minutes=5)
user.is_active читается как флаг, но всегда актуален.2. Когда хочешь валидировать данные при установке
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if value < 0:
raise ValueError("Возраст не может быть отрицательным")
self._age = value
person.age = -1 — но это вызовет ошибку, как и должно.3. Когда хочешь спрятать внутренности, не меняя интерфейс
Сначала у тебя было:
user.is_admin # булево поле
А потом ты передумал и решил вычислять его по ролям:
@property
def is_admin(self):
return "admin" in self.roles
user.is_admin останутся рабочими, но теперь они динамичные.@property делает твой код гибким: интерфейс остаётся, а реализацию можно менять. Это инкапсуляция, но по-питоновски.Ты можешь добавить к setter'у ещё и deleter:
@x.deleter
def x(self):
del self._x
Но чаще всего нужны только
getter и setter.@property — это не украшение. Это способ скрыть логику, проверки, кэширование, не портя интерфейс.Ты получаешь читаемый API, не жертвуя гибкостью.
ORM, модели, бизнес-логика, интерфейсы SDK, динамические флаги, защитные проверки. Везде, где важно: "пусть выглядит просто, но работает как надо".
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
requests + BeautifulSoup: просто, быстро, эффективноЕсли тебе нужно вытянуть данные с HTML-страницы — это классика.
requests тянет страницу, BeautifulSoup разбирает её в структуру, которую легко обрабатывать.import requests
from bs4 import BeautifulSoup
url = "https://example.com"
resp = requests.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
soup — это объект, с которым можно работать как с DOM-деревом.title = soup.find("h1").text
links = [a["href"] for a in soup.find_all("a") if "href" in a.attrs]find() — первый найденный элемент, find_all() — список всех. Атрибуты доступны как у словаря.items = soup.select("div.card > a.link")select() — поддерживает любые CSS-селекторы. Гибко и читаемо.for img in soup.select("img"):
print(img.get("src"), img.get("alt"))get() безопаснее прямого доступа: не упадёт, если атрибута нет.headers = {"User-Agent": "Mozilla/5.0"}
r = requests.get(url, headers=headers)User-Agent. Добавляй его для стабильности.requests + BeautifulSoup — это основа для быстрого парсинга HTML.Подходит для большинства задач: просто, мощно, читаемо. Но не забудь уважать
robots.txt и лимитировать частоту запросов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
• copy() создает поверхностную копию объекта (ссылки на вложенные элементы сохраняются).
• deepcopy() создает полную независимую копию объекта.
import copy
a = [[1, 2], [3, 4]]
b = copy.copy(a)
c = copy.deepcopy(a)
a[0][0] = 99
print(b) # [[99, 2], [3, 4]] (изменилось)
print(c) # [[1, 2], [3, 4]] (осталось прежним)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
is и ==Многие путают
is и ==, но их предназначение разное:•
is проверяет, являются ли два объекта одной и той же сущностью в памяти.•
== проверяет, равны ли их значения.
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a is b) # True (указывает на тот же объект)
print(a == b) # True (списки одинаковые)
print(a is c) # False (разные объекты)
print(a == c) # True (одинаковое содержимое)
is для проверки, ссылаются ли переменные на один объект, а == — для сравнения значений.Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2
Когда не нужен полноценный PostgreSQL, а просто надо где-то хранить данные — SQLite идеально.
.db-файлеimport sqlite3
conn = sqlite3.connect("users.db") # создаёт файл, если нет
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
age INTEGER
)
""")
conn.commit()
users — без серверов, Docker и настроек.cursor.execute("INSERT INTO users (username, age) VALUES (?, ?)", ("alice", 30))
conn.commit()? — это защита от SQL-инъекций.cursor.execute("SELECT * FROM users")
for row in cursor.fetchall():
print(row)cursor.execute("UPDATE users SET age = ? WHERE username = ?", (31, "alice"))
cursor.execute("DELETE FROM users WHERE age < ?", (18,))
conn.commit()conn.close()
Или так:
with sqlite3.connect("users.db") as conn:
...SQLite — идеальный вариант для прототипов, локальных тулз, ботов, скриптов и парсеров.
Поддерживает SQL, транзакции, индексы — и всё в одном файле.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
Если вы часто пишете
print("var =", var), чтобы проверить значение переменной, то этот трюк сэкономит вам кучу времени.Начиная с Python 3.8, в f-строках можно использовать знак равно =.
user = "Alex"
age = 25
print(f"user = {user}, age = {age}")
# Вывод: user = Alex, age = 25
Просто добавьте = в конце переменной внутри фигурных скобок. Python сам подставит имя переменной и её значение.
user = "Alex"
age = 25
print(f"{user=}, {age=}")
# Вывод: user='Alex', age=25
Это работает даже с выражениями:
print(f"{2 + 2 = }")
# Вывод: 2 + 2 = 4
Мелочь, а код для отладки пишется в два раза быстрее! 🚀
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3
try:
do_something()
except:
pass
⛔️ Это плохая практика, которая уничтожает отладку, ломает контроль потока и маскирует реальные ошибки.
-
KeyboardInterrupt — Ctrl+C не сработает, ты не сможешь остановить процесс.-
SystemExit — sys.exit() не завершит программу.-
SyntaxError, MemoryError, ImportError — всё будет съедено.Если внутри блока
try падает непредсказуемая ошибка, а ты её не логируешь — ты даже не узнаешь, что код работает неправильно.
try:
complex_logic()
except:
pass # ничего не видно, баг скрыт
Ты можешь:
- Ловить
AttributeError, потому что опечатался.- Не инициализировать переменную.
- Получать
KeyError, IndexError, ValueError — и никогда об этом не узнаешь.
try:
result = do_network_call()
except TimeoutError:
print("Превышено время ожидания")
Если ты не знаешь, какие ошибки может выбросить функция — выясни. Это важно.
import logging
try:
open("somefile.txt")
except FileNotFoundError as e:
logging.warning(f"Файл не найден: {e}")
Это поможет в отладке, особенно если ты на проде. Можно подключить
sentry, rollbar, loguru — что угодно, лишь бы не терять ошибки в пустоте.
try:
optional_feature()
except SomeError:
pass # ok to fail — не критично
Будущий ты (или твой тиммейт) скажет спасибо.
try:
...
except Exception:
pass
🧨
Exception — тоже широкая сеть. Иногда это допустимо (например, в retry-декораторе), но по умолчанию — нет.Ctrl+C, exit(). Иногда (но редко!) тебе нужно поймать всё — например, при логгировании в многопоточном приложении или глобальном хендлере ошибок:
try:
...
except Exception:
logger.exception("Что-то пошло не так")
Но всегда логируй, и никогда не делай
pass без причины.Backend, парсеры, ETL-пайплайны, API, CLI-инструменты — везде, где ошибка не должна оставаться в тени.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
with: Чистый код и надёжное управление ресурсамиЕщё одна мощная и идиоматичная конструкция в Python — это менеджеры контекста и оператор
with. Они кардинально упрощают работу с ресурсами, которые требуют обязательной "очистки" после использования, например, файлы, сетевые соединения или блокировки потоков.Представьте, что вы открываете файл для записи. Крайне важно его потом закрыть, иначе данные могут не сохраниться, а файловый дескриптор останется занят. Классический, но многословный способ гарантировать закрытие — использовать
try...finally:
f = open('my_file.txt', 'w')
try:
f.write('Важные данные!')
# ... тут может произойти ошибка
finally:
f.close() # Закроется в любом случае
Работает, но выглядит громоздко. Python предлагает элегантную альтернативу с
with:
with open('my_file.txt', 'w') as f:
f.write('Важные данные!')
# ... тут тоже может произойти ошибка
# Как только блок `with` завершается (нормально или из-за ошибки),
# Python АВТОМАТИЧЕСКИ вызывает f.close()!
В чём магия with?
Объекты, используемые с
with (как тот, что возвращает open()), реализуют так называемый "протокол менеджера контекста". У них есть специальные методы (__enter__ и __exit__). Оператор with вызывает __enter__ при входе в блок и гарантированно вызывает __exit__ при выходе из блока, передавая туда информацию об исключениях, если они были. Именно в __exit__ и происходит освобождение ресурса (закрытие файла).Оператор
with — это стандарт де-факто для управления ресурсами в Python. Он делает код не только короче, но и значительно безопаснее и понятнее.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3❤1👍1
Начиная с Python 3.10,
match/case позволяет не просто сравнивать, но разбирать структуры объектов.class Point:
def __init__(self, x, y): self.x, self.y = x, y
def handle(p):
match p:
case Point(x=0, y=y):
print(f"На оси Y: y={y}")
case Point(x=x, y=0):
print(f"На оси X: x={x}")
case Point():
print("Внутри плоскости")
handle(Point(0, 5))
Работает благодаря
__match_args__ — специальному атрибуту:class Point:
__match_args__ = ("x", "y")
match/case гораздо шире if — особенно при парсинге AST, JSON, конфигураций и DSL.Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
🚰 Стриминг больших данных через генераторы и
Когда данных слишком много — миллионы строк в файле, бесконечные события или поток логов — держать всё в памяти нельзя. Тут спасают генераторы и ключевое слово
📦 Чтение файла построчно
➡️ Память не переполняется: читается и отдаётся по строке.
🔗 Комбинация генераторов через yield from
➡️
⚡️ Обработка пайплайнами
➡️ Логика разбивается на звенья, и каждое обрабатывает поток данных лениво.
🌀 Бесконечные источники
➡️ Генератор выдаёт значения бесконечно, но потребитель сам решает, когда остановиться.
📑 Вложенные пайплайны с
➡️
🚀 Генераторы + итераторы стандартной библиотеки
➡️ Вместо списка в миллион чисел получаешь поток, из которого берёшь только нужное.
🗣️ Запомни: генераторы — это ленивые конвейеры данных, yield from связывает их в цепочку. Такой подход позволяет обрабатывать гигабайты без переполнения памяти и писать код, который дышит как поток.
yield fromКогда данных слишком много — миллионы строк в файле, бесконечные события или поток логов — держать всё в памяти нельзя. Тут спасают генераторы и ключевое слово
yield from, позволяющее строить цепочки ленивых итераторов.def read_file(path):
with open(path, "r") as f:
for line in f:
yield line.strip()
for row in read_file("bigdata.txt"):
print(row)
def numbers():
yield from range(5)
yield from range(10, 15)
print(list(numbers()))
yield from разворачивает подгенераторы и прокидывает их значения наружу.def read_lines(path):
with open(path) as f:
yield from f
def filter_errors(lines):
for line in lines:
if "ERROR" in line:
yield line
errors = filter_errors(read_lines("app.log"))
for e in errors:
print(e)
🌀 Бесконечные источники
import time
def ticker():
while True:
yield time.time()
time.sleep(1)
for t in ticker():
print(t)
📑 Вложенные пайплайны с
yield fromdef split_words(lines):
for line in lines:
yield from line.split()
data = ["hello world", "big data stream"]
for word in split_words(data):
print(word)
yield from красиво разрывает вложенные итерации без двойных циклов.from itertools import islice
def stream():
for i in range(1000000):
yield i
print(list(islice(stream(), 5)))
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
__call__ и __getitem__ — красиво, читаемо, PythonicХочешь, чтобы твой код выглядел как язык сам по себе?
Python позволяет строить мини-языки внутри кода — без библиотек, просто на магии dunder-методов.
__call__Он делает объект вызываемым, как функцию:
class Hello:
def __call__(self, name):
return f"Привет, {name}!"
h = Hello()
print(h("Мир")) # Привет, Мир!
Полезно, когда хочется сделать объекты лаконичными. Можно даже прокидывать параметры как в обычной функции.
__getitem__Позволяет обращаться к объекту через квадратные скобки:
class SecretBox:
def __getitem__(self, key):
return f"🔒 Внутри: {key}"
box = SecretBox()
print(box["password"]) # 🔒 Внутри: password
Ты можешь использовать это для красивого синтаксиса без точек и скобок.
class SQL:
def __call__(self, table):
return f"SELECT * FROM {table}"
def __getitem__(self, field):
return f'"{field}"'
q = SQL()
print(q("users")) # SELECT * FROM users
print(q["email"]) # "email"
Теперь у нас объект, который и вызывает таблицу, и красиво оформляет поля.
class API:
def __init__(self, base):
self.base = base
def __getitem__(self, endpoint):
return f"{self.base}/{endpoint}"
def __call__(self, endpoint, **params):
query = "&".join(f"{k}={v}" for k, v in params.items())
return f"{self.base}/{endpoint}?{query}"
api = API("https://api.server")
print(api["users"]) # https://api.server/users
print(api("users", id=5, active=True)) # https://api.server/users?id=5&active=True
Такой подход часто используют в клиентах к REST API, чтобы код выглядел как естественный DSL.
class K:
def __getitem__(self, key):
return lambda d: d.get(key)
k = K()
data = {"name": "Neo", "role": "Hacker"}
print(k["name"](data)) # Neo
print(k["role"](data)) # Hacker
Так строятся мини-функции доступа к полям. Особенно круто в map/filter.
__call__ и __getitem__ — это способ превратить скучные объекты в выразительный синтаксис. Так строятся мини-языки прямо в Python: понятные, компактные и без лишнего шума.Please open Telegram to view this post
VIEW IN TELEGRAM
❤1