PytStart | Программирование на Python
4.28K subscribers
23 photos
26 videos
57 links
Python: примеры кода, уроки, статьи

Купить рекламу: https://telega.in/c/pytstart

✍️По всем вопросам: @Pascal4eg
Download Telegram
🐍 Как сделать бесконечный счётчик без переменных

В 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"Hello {name}"?
А что если я скажу, что туда можно засовывать функции, арифметику и даже условия?

Вот мощный разбор, как выжать максимум из f-строк в Python 👇

🟢 1. Арифметика прямо в строке
a, b = 10, 3
print(f"Сумма: {a + b}, Разность: {a - b}")

🟢 Внутри фигурных скобок можно писать полноценные выражения.
➡️ Да хоть f"Результат: {(a * b) ** 2}" — это законно.

🟢2. Функции внутри f-строки
def shout(name):
return name.upper() + "!"

print(f"Привет, {shout('Алиса')}")

🟢 Вызов функций? Да. Лямбды? Тоже можно. Даже f"{sorted([3,1,2])}" работает.

🟢3. Условия и тернарные выражения
age = 20
print(f"{'Совершеннолетний' if age >= 18 else 'Несовершеннолетний'} пользователь")

🟢 Отлично работает с любыми if ... else внутри {}.

🟢4. Форматирование чисел по-человечески
value = 12345.6789
print(f"{value:.2f}") # 12345.68
print(f"{value:,.2f}") # 12,345.68

➡️ :.2f — два знака после запятой
➡️ :, — добавляет разделитель тысяч

🟢5. Форматирование по ширине и выравниванию
name = "Alice"
print(f"{name:>10}") # справа
print(f"{name:<10}") # слева
print(f"{name:^10}") # по центру

🟢 Работает с числами и строками. Полезно в логах и таблицах.

🟢 6. Форматирование как hex, bin, oct
num = 42
print(f"{num:b}") # 101010
print(f"{num:x}") # 2a

👍 b — двоичная
👍 x — шестнадцатеричная
👍 o — восьмеричная

🟢 7. Вложенные f-строки и шаблоны
user = {"name": "Eva", "points": 120}
print(f"{user['name']} набрала {f'{user['points'] * 2}'} очков")

🟢 Иногда полезно, но лучше избегать слишком сложной вложенности.

💡 Запомни
f-строки — это не просто вставка переменных
Используй форматирование, условия, вызовы функций
Удобно для логов, отчётов, динамического UI, и шаблонов CLI

🗣️ Хочешь пост про format() против f-строк, или как делать шаблоны с f-строками? Предложи тему — сделаем!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51
🐍 Как сделать простой Telegram-бот на Python

Минимальный бот — буквально в несколько строк 👇

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
👟 pip + venv: ставим библиотеки изолированно — и это работает

venv делает песочницу для проекта.
pip ставит пакеты внутрь неё.
Активировал окружение — и весь мир пакетов идёт в твою папку, а не в систему.

📦 Шаг 1 — создай окружение в корне проекта
# Windows
py -m venv .venv
# macOS / Linux
python3 -m venv .venv

➡️ Появится папка .venv — там свой Python и свой pip.

🔑 Шаг 2 — активируй окружение
# PowerShell
.\.venv\Scripts\Activate.ps1
# cmd
.\.venv\Scripts\activate.bat
# macOS / Linux
source .venv/bin/activate

➡️ Подсказка терминала сменится на (.venv) — ты внутри.

⚙️ Шаг 3 — обнови pip (сначала всегда так)
python -m pip install --upgrade pip

➡️Берёшь свежую версию установщика, меньше странных ошибок.

📥 Шаг 4 — ставь библиотеки
pip install requests
pip install "uvicorn[standard]" fastapi

➡️ Всё уезжает в .venv. Глобальная система не трогается.

🔎 Шаг 5 — смотри, что внутри
pip list
pip show requests

➡️ Видишь только пакеты твоего окружения, не всей машины.

🧾 Шаг 6 — фиксируй зависимости
pip freeze > requirements.txt

➡️ Снимок версий. Его же можно отдать коллегам или CI.

🚚 Шаг 7 — восстановление на другой машине
# в новом клоне проекта
python -m venv .venv
# активируй (как в Шаге 2)
pip install -r requirements.txt

➡️ Получишь те же версии пакетов, что и у автора.

🧪 Проверка — пакет реально в venv
python -c "import requests, sys; print(sys.prefix)"

➡️ Должен увидеть путь к твоему .venv. Значит всё изолировано.

🧹 Шаг 8 — удаление/выход
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% проблем.

🗂 Бонус — не коммить venv
echo .venv/ >> .gitignore

➡️ Окружение — локальное. В репо нужен только requirements.txt.

🗣️ Запомни: venv — граница проекта, pip — грузовик с пакетами.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41
🖥 Чем список отличается от кортежа?

Списки – это изменяемые последовательности, обычно используемые для хранения однотипных данных (хотя 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
👍52
🖥 Что делает enumerate() в Python?

3️⃣ enumerate() добавляет счётчик к итерации.

fruits = ["🍎", "🍌", "🍇"]
for i, fruit in enumerate(fruits):
print(i, fruit)


📌 Вывод:
0 🍎  
1 🍌
2 🍇



🗣 Используется, когда нужен индекс при переборе: списки, строки, циклы в UI и CLI.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
📱 Генерируем QR‑коды в Python: просто, гибко, наглядно

Иногда нужно быстро создать QR‑код: для ссылки, текста, визитки или даже Wi‑Fi‑пароля. Python справляется с этим буквально за пару строк.
Давай разберём, как это делается и что внутри происходит.

pip install qrcode[pil]

➡️ Устанавливаем библиотеку qrcode. В скобках [pil] — сразу тянет Pillow для работы с изображениями.

import qrcode

img = qrcode.make("https://example.com")
img.save("qrcode.png")

➡️ Базовый случай: генерация QR‑кода для любой строки. Метод 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) позволяет восстанавливать данные даже при частичном перекрытии.


🗣️ Запомни: QR‑код — это обычное изображение, а Python — отличная среда, чтобы сгенерировать их сотнями или добавить фирменный стиль прямо в коде.
Просто текст → картинка → готово.
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥2
👩‍💻 `pip` — не просто "установить пакет"

Каждый Python-разработчик использует pip, но далеко не все понимают, насколько критична дисциплина в управлении зависимостями. Ошибки здесь = боль на проде, в CI и при сборке.

🔍 1. Никогда не устанавливай пакеты глобально

pip install some-library  # 


➡️ Это засоряет системный Python, может конфликтовать с другими проектами и ломает dev-среду.

✔️ Всегда используй виртуальное окружение:

python -m venv venv
source venv/bin/activate
pip install some-library


➡️ Чистота, изоляция, контроль.


🔐 2. Зафиксируй зависимости

Если ты не фиксируешь версии — ты играешь в лотерею.

pip install requests


Через месяц выйдет новая мажорная версия — и твой код может отвалиться.

✔️ Делай так:

pip install requests==2.31.0


А ещё лучше:

pip freeze > requirements.txt


➡️ И ты всегда знаешь, что работает. И на проде, и у коллег.

📦 3. Используй `--upgrade-strategy eager` с умом

pip install -U some-lib  # по умолчанию может подтянуть несовместимости


➡️ Это может внезапно обновить половину стека. Используй --upgrade-strategy only-if-needed, если хочешь избегать каскадных обновлений.

🛠 4. Обновление pip — не каприз

Иногда pip старый, и ты получаешь ошибки вроде "metadata generation failed".

✔️ Просто:

pip install -U pip


➡️ Новые версии pip реально решают кучу проблем с установкой.

⚙️ 5. Хочешь порядок? Используй `pip-tools`

pip install pip-tools


Работает как pip freeze, но человечно:

# requirements.in
requests==2.31.0
flask>=2.0


pip-compile requirements.in  # генерирует requirements.txt с зависимостями


➡️ Ты контролируешь high-level зависимости, pip-tools следит за всем остальным.

🗣️ Запомни: pip — это твой фундамент. Если ты не управляешь зависимостями осознанно, ты рано или поздно огребаешь. Особенно в команде.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72👏1
🔁 Как работает yield и зачем он реально нужен в Python

yield — это не 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
👍71🤔1
👩‍💻 `@property`: не просто синтаксический сахар

В 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 выглядит как поле, но за ним — код. Удобно, безопасно и читаемо.

🔥 Где полезно использовать `property`:

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() — список всех. Атрибуты доступны как у словаря.

👍 CSS-селекторы вместо find()
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
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
👍41
👩‍💻 Разница между copy() и deepcopy()

• 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]] (осталось прежним)


🗣️ Используйте deepcopy(), если хотите избежать изменения оригинальных данных.
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
👩‍💻 SQLite в Python: база прямо в файл, без сервера

Когда не нужен полноценный 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()

➡️ Всё как в обычном SQL. Просто — и работает.

Закрытие соединения
conn.close()

Или так:
with sqlite3.connect("users.db") as conn:
...


🗣️Запомни:
SQLite — идеальный вариант для прототипов, локальных тулз, ботов, скриптов и парсеров.
Поддерживает SQL, транзакции, индексы — и всё в одном файле.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2
🖥 Ленивый дебаг с f-строками

Если вы часто пишете 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/except пожирает всё


try:
do_something()
except:
pass


⛔️ Это плохая практика, которая уничтожает отладку, ломает контроль потока и маскирует реальные ошибки
.


🤯 Почему это опасно?

🟢 1. Ловит всё подряд:
- KeyboardInterrupt — Ctrl+C не сработает, ты не сможешь остановить процесс.
- SystemExitsys.exit() не завершит программу.
- SyntaxError, MemoryError, ImportError — всё будет съедено.

➡️ Такой код не просто "ловит ошибки" — он прячется от них.

🟢 2. Трудно отлаживать

Если внутри блока try падает непредсказуемая ошибка, а ты её не логируешь — ты даже не узнаешь, что код работает неправильно.


try:
complex_logic()
except:
pass # ничего не видно, баг скрыт


Ты можешь:
- Ловить AttributeError, потому что опечатался.
- Не инициализировать переменную.
- Получать KeyError, IndexError, ValueError — и никогда об этом не узнаешь.

Как правильно?

📌 1. Лови только нужные исключения:


try:
result = do_network_call()
except TimeoutError:
print("Превышено время ожидания")


Если ты не знаешь, какие ошибки может выбросить функция — выясни. Это важно.

📌 2. Логируй исключения:


import logging

try:
open("somefile.txt")
except FileNotFoundError as e:
logging.warning(f"Файл не найден: {e}")


Это поможет в отладке, особенно если ты на проде. Можно подключить sentry, rollbar, loguru — что угодно, лишь бы не терять ошибки в пустоте.

📌 3. Хочешь "молчаливое" поведение? — добавь комментарий, зачем:


try:
optional_feature()
except SomeError:
pass # ok to fail — не критично


Будущий ты (или твой тиммейт) скажет спасибо.

📌 4. Никогда не делай так:


try:
...
except Exception:
pass


🧨 Exception — тоже широкая сеть. Иногда это допустимо (например, в retry-декораторе), но по умолчанию — нет.

🚨 Запомни:

🟢 `except:` — ловит всё , даже Ctrl+C, exit().
🟢 `except Exception:` без логов — багов не видно, теряется контекст.
🟢`pass` в except — молча глушит ошибку , никаких действий.

Лучше: перехватывай конкретные ошибки, логируй, не скрывай баги.

📌 Когда можно ловить всё?

Иногда (но редко!) тебе нужно поймать всё — например, при логгировании в многопоточном приложении или глобальном хендлере ошибок:


try:
...
except Exception:
logger.exception("Что-то пошло не так")


Но всегда логируй, и никогда не делай pass без причины.

🗣 Грамотная работа с ошибками — одна из черт хорошего инженера. Код должен быть предсказуемым, отлаживаемым и честным: если ошибка есть — мы о ней узнаём.

📍 Где применяется:
Backend, парсеры, ETL-пайплайны, API, CLI-инструменты — везде, где ошибка не должна оставаться в тени.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🖥 Python и 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
🔥31👍1
🧬 Структурные шаблоны (match/case) с объектами – не только для строк и чисел!

Начиная с 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
👍21
🚰 Стриминг больших данных через генераторы и 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)

➡️ Память не переполняется: читается и отдаётся по строке.

🔗 Комбинация генераторов через yield from
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 from
def 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)))

➡️ Вместо списка в миллион чисел получаешь поток, из которого берёшь только нужное.

🗣️ Запомни: генераторы — это ленивые конвейеры данных, yield from связывает их в цепочку. Такой подход позволяет обрабатывать гигабайты без переполнения памяти и писать код, который дышит как поток.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
👩‍💻 DSL в Python через __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

Ты можешь использовать это для красивого синтаксиса без точек и скобок.

🤝 Комбинируем в DSL
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"

Теперь у нас объект, который и вызывает таблицу, и красиво оформляет поля.

🧪 Более мощный пример: API-доступ
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