Kodduu Python
1.08K subscribers
310 photos
28 videos
186 links
Научись программировать на Python на интересных примерах

Самый быстрый курс https://stepik.org/a/187914
Самый нескучный курс https://stepik.org/a/185238

Во вопросам сотрудничества: @AlexErf
Download Telegram
Мини версия игры Boxing 👊


import pygame,sys,random,math
pygame.init()
W,H=640,480
s=pygame.display.set_mode((W,H))
c=pygame.time.Clock()
f=pygame.font.SysFont(None,24)
ph,eh=100,100
cdp,atk=0,0
pf=[{'r':60,'x':W//2-120,'y':H-80,'st':0},{'r':60,'x':W//2+120,'y':H-80,'st':0}]
ef=[{'r':40,'x':W//2-60,'y':H//2+120,'st':0},{'r':40,'x':W//2+60,'y':H//2+120,'st':0}]
fx,fy,ft,t=0,0,0,0
fsx,fsy,shx,shy=0,0,0,0
pl,pr={'x':0,'y':0},{'x':0,'y':0}
scs,pscs=[],[]
def dr():
ox,oy=shx,shy
s.fill((0,0,0))
pygame.draw.rect(s,(255,0,0),(50+ox,30+oy,ph*2,20))
pygame.draw.rect(s,(0,255,0),(W-250+ox,30+oy,eh*2,20))
cx,cy=W//2+fx+fsx+ox,H//2+fy+fsy+oy
pygame.draw.circle(s,(255,220,200),(cx,cy),120)
for sx,sy,l,a in scs:
ex,ey=cx+sx+math.cos(a)*l,cy+sy+math.sin(a)*l
pygame.draw.line(s,(150,0,0),(cx+sx,cy+sy),(ex,ey),2)
exs,eys=fx//5,fy//5
el,er=(cx-40+exs,cy-40+eys),(cx+40+exs,cy-40+eys)
pygame.draw.circle(s,(0,0,0),el,20);pygame.draw.circle(s,(0,0,0),er,20)
pygame.draw.circle(s,(255,255,255),(int(el[0]+pl['x']),int(el[1]+pl['y'])),5)
pygame.draw.circle(s,(255,255,255),(int(er[0]+pr['x']),int(er[1]+pr['y'])),5)
pygame.draw.rect(s,(0,0,0),(cx-50+exs,cy+40+eys,100,20))
for q in ef:pygame.draw.circle(s,(200,50,50),(q['x']+ox,q['y']+oy),q['r'])
for q in pf:pygame.draw.circle(s,(200,200,200),(q['x']+ox,q['y']+oy),q['r'])
for sx,sy,l,a in pscs:
ex,ey=sx+math.cos(a)*l,sy+math.sin(a)*l
pygame.draw.line(s,(255,50,50),(sx,sy),(ex,ey),3)
s.blit(f.render(f"P:{ph} E:{eh}",1,(255,255,255)),(W//2-40+ox,5+oy))
pygame.display.flip()
def punch():
global fsx,fsy,scs
q=random.choice(pf);q.update({'r':90,'x':W//2+random.randint(-40,40),'y':H//2+random.randint(-40,40),'st':1})
fsx,fsy=random.randint(-q['r'],q['r']),random.randint(-q['r']//2,q['r']//2)
scs.append((random.randint(-100,100),random.randint(-100,100),random.randint(10,40),random.uniform(0,6.28)))
def eatk():
global ph,shx,shy,pscs
q=random.choice(ef);q.update({'r':120,'y':H//2+30,'st':1})
ph=max(0,ph-q['r']//10)
shx,shy=random.randint(-q['r']//2,q['r']//2),random.randint(-q['r']//2,q['r']//2)
for _ in range(random.randint(1,3)):
sx,sy,l,ang=random.randint(0,W),random.randint(0,H),random.randint(80,200),random.uniform(-.5,.5)
pscs.append((sx,sy,l,ang))
while 1:
for e in pygame.event.get():
if e.type==pygame.QUIT:pygame.quit();sys.exit()
if e.type==pygame.KEYDOWN and e.key==pygame.K_SPACE and cdp==0:punch();cdp=20
if cdp>0:cdp-=1
if t==0:ft={'x':random.choice([-30,0,30]),'y':random.choice([-20,0,10])};t=random.randint(20,40)
else:fx+=(ft['x']-fx)//10;fy+=(ft['y']-fy)//10;t-=1
fsx//=2;fsy//=2;shx//=2;shy//=2
pl['x']+=(-fx//5-pl['x'])//5;pl['y']+=(-fy//5-pl['y'])//5
pr['x']+=(-fx//5-pr['x'])//5;pr['y']+=(-fy//5-pr['y'])//5
for i,q in enumerate(pf):
if q['st']:q['r']-=5;q['y']+=4
else:
ix=W//2-120 if i==0 else W//2+120
if q['r']<60:q['r']+=2
if q['y']<H-80:q['y']+=2
q['x']+=(ix-q['x'])//5
if q['st'] and q['r']<=30:
eh=max(0,eh-max(5,25-q['r']));q['st']=0
for i,q in enumerate(ef):
if q['st']:q['r']-=3;q['y']+=2
else:
ix=W//2-60 if i==0 else W//2+60
if q['r']<40:q['r']+=2
if q['y']<H//2+120:q['y']+=2
q['x']+=(ix-q['x'])//5
if q['st'] and q['r']<=40:q['st']=0
atk+=1
if atk>60:eatk();atk=0
dr()
if ph<=0 or eh<=0:
m="Win!"if eh<=0 else"Lose!"
s.fill((0,0,0));s.blit(f.render(m,1,(255,255,255)),(W//2-20,H//2));pygame.display.flip();pygame.time.wait(2000)
ph,eh=100,100;pf=[{'r':60,'x':W//2-120,'y':H-80,'st':0},{'r':60,'x':W//2+120,'y':H-80,'st':0}]
ef=[{'r':40,'x':W//2-60,'y':H//2+120,'st':0},{'r':40,'x':W//2+60,'y':H//2+120,'st':0}]
fx,fy,ft,t,fsx,fsy,shx,shy,pl,pr,scs,pscs,atk=0,0,{'x':0,'y':0},0,0,0,0,0,{'x':0,'y':0},{'x':0,'y':0},[],[],0
c.tick(30)


Подпишись 👉🏻 @KodduuPython 🤖
This media is not supported in your browser
VIEW IN TELEGRAM
Демо 👆👆👆

Подпишись 👉🏻 @KodduuPython 🤖
В Python 3.14 теперь можно ветвить логику прямо по типам (type-based branching),
а не только по значениям.
Это стало возможным благодаря `match` + `type` pattern matching и новым возможностям typing — например, TypeIs и TypeGuard.

### ⚙️ Пример: ветвление по типу аргумента


from typing import TypeGuard

def is_str(x: object) -> TypeGuard[str]:
return isinstance(x, str)

def process(x: int | str):
if is_str(x):
# здесь x уже гарантированно str
print(f"Строка: {x.upper()}")
else:
# а здесь — int
print(f"Число: {x * 2}")

process("hi")
process(10)


📌 Как это работает:

* TypeGuard сообщает анализатору типов (mypy, Pyright, IDE),
что если условие is_str(x) истинно — то дальше x считается str.
* Таким образом, мы получаем ветвление логики по типу
без ручных isinstance() проверок везде.
* Python 3.14 поддерживает это *официально* в стандартном typing.


🛠 всё работает "из коробки" на Python 3.14+

Подпишись 👉🏻 @KodduuPython 🤖
🔥 Python 3.14: Free-threading и реальное многопоточность без GIL


import sys, threading, time

def worker(n):
s = 0
for i in range(n):
s += i*i
return s

def benchmark(n, threads):
ts = []
for _ in range(threads):
t = threading.Thread(target=worker, args=(n,))
ts.append(t)
t.start()
for t in ts:
t.join()

if __name__ == "__main__":
print("GIL enabled:", sys._is_gil_enabled())
start = time.time()
benchmark(10_000_000, 4)
end = time.time()
print("Time:", end-start)


📌 Что важно:

* В Python 3.14 есть официальная поддержка free-threaded build (CPython без GIL) ([Python documentation][1])
* Если собрать интерпретатор с параметром --disable-gil, или установить free-threaded образ на Windows/macOS, sys._is_gil_enabled() покажет что GIL отключён ([Python documentation][1])
* В этом режиме CPU-bound задачи через потоки реально параллелятся, что даёт значительное ускорение на многопроцессорных машинах ([InfoWorld][2])

🛠 Необходимо: собрать/установить free-threaded CPython--disable-gil`) или использовать официальный билд, поддерживающий GIL офф :contentReference[oaicite:3]{index=3}`.

Подпишись 👉🏻 @KodduuPython 🤖
2
⚙️ Новый интерпретатор в Python 3.14 — +30 % скорости без магии 🚀


import time

def compute(n: int) -> int:
return sum(i * i for i in range(n))

def benchmark():
start = time.perf_counter()
for _ in range(10):
compute(2_000_000)
return time.perf_counter() - start

if __name__ == "__main__":
t = benchmark()
print(f" Выполнено за: {t:.3f} сек")


📌 Что происходит:
Этот простой код идеально показывает ускорение от нового интерпретатора в Python 3.14.
Теперь for, sum и арифметика выполняются через новую таблицу компактных C-функций,
вместо огромного `switch`-цикла внутри байткода.

💡 Результат:
— +10-30 % прироста скорости на CPU-интенсивных задачах без изменения исходников.
— Улучшено управление кадрами, кеш инструкций и прогноз ветвлений.

🛠 Просто установи Python 3.14+ — никаких зависимостей или изменений кода.

Подпишись 👉🏻 @KodduuPython 🤖
Forwarded from AIGENTTO
Clusteroid для автокластеризации документов в RAG

В RAG часто бывает набор различных документов из разных департаментов компании. Нужно либо использовать разделение на кластеры по департаментам, что часто бывает неточным (например, в HR хранится много разных по типу и содержанию документов), либо сортировать их самостоятельно. Либо же сложить всё вместе в одну кучу.

Третий вариант — самый плохой, так как получится много схожей семантики, и процесс retrieve будет работать плохо (будет попадать много нерелевантных чанков). Первый вариант обычно приемлем, но по сути сводится ко второму: нужен человек, который вручную качественно сортировал бы документы по секциям и пересортировывал при изменениях и добавлениях.

Существуют библиотеки, например, SpaCy, которые могут делать разметку (NER), но без качественной настройки под конкретную тему они работают плохо.

Поэтому мы разработали собственный кластеризатор Clusteroid, который выложили в open source. Он умеет кластеризовать с помощью K-Means или HDBSCAN.

Подпишись 👉🏻 @aigentto 🤖
2
🧩 Python 3.14: Отложенная оценка аннотаций (PEP 649)


class User:
name: "str"
age: "int"

def greet(u: "User") -> "str":
return f"Hi, {u.name}! You’re {u.age}."

print(greet.__annotations__)


📌 Что изменилось:
Раньше Python выполнял аннотации при загрузке модуля,
и если типы были объявлены позже (например, класс `User`),
возникала ошибка NameError.

В Python 3.14 аннотации хранятся в ленивом виде
они не вычисляются, пока реально не понадобятся.
Теперь можно писать аннотации даже на ещё не объявленные типы
или динамически создавать их без from __future__ import annotations.

Плюсы:

* Больше не нужно импортировать всё ради аннотаций.
* Быстрее стартует программа (аннотации не тратят CPU).
* IDE и типизаторы работают точнее — аннотации доступны при необходимости.

🛠 Работает из коробки в Python 3.14+, без флагов и дополнительных библиотек.

Подпишись 👉🏻 @KodduuPython 🤖
👍2
🔥 Python 3.14: экспериментальный JIT-компилятор для “горячего кода”


import time

def hot_func(n: int) -> int:
s = 0
for i in range(n):
s += (i * 3) % 7
return s

def bench():
start = time.perf_counter()
for _ in range(50):
hot_func(5_000_000)
print(f" {time.perf_counter()-start:.3f} сек")

if __name__ == "__main__":
bench()


📌 Что нового:
В Python 3.14 появился экспериментальный JIT
он отслеживает *“горячие участки”* кода (часто исполняемые функции)
и компилирует их в нативный машинный код во время выполнения.

💡 Что это даёт:

* Ускорение CPU-интенсивных циклов на 20–50 %
* Прирост без внешних библиотек (PyPy, Numba и т.п.)
* Автоматически активируется для «горячих» функций (в будущем через флаг `PYTHONJIT=1`)

🧠 Пока режим JIT экспериментальный, но уже доступен в сборках 3.14+ как часть проекта cpython-jit prototype.

🛠 Для теста — установить Python 3.14 (free-threaded build) и запустить с переменной окружения:


PYTHONJIT=1 python your_script.py


Подпишись 👉🏻 @KodduuPython 🤖
2👍1
🚀 Надёжный HTTP POST с идемпотентностью и экспоненциальным бэкоффом


import requests, time, uuid, logging
logging.basicConfig(level=logging.INFO)

def post_json(url, data, headers=None, retries=5, backoff=0.5, timeout=10, idempotency_key=None):
h = dict(headers or {})
if idempotency_key: h.setdefault("Idempotency-Key", idempotency_key)
else: h.setdefault("Idempotency-Key", str(uuid.uuid4()))
for attempt in range(1, retries+1):
try:
r = requests.post(url, json=data, headers=h, timeout=timeout)
if r.status_code < 400:
return r
if r.status_code < 500 and r.status_code != 429:
r.raise_for_status() # client error — don't retry
# server error or 429 -> retry
logging.warning("POST %s -> %s (attempt %d)", url, r.status_code, attempt)
except (requests.Timeout, requests.ConnectionError) as e:
logging.warning("Request error: %s (attempt %d)", e, attempt)
sleep = backoff * (2 ** (attempt - 1)) * (0.5 + random.random()/1.0)
time.sleep(sleep)
raise RuntimeError(f"POST failed after {retries} attempts: {url}")


📌 Коротко: универсальная, готовая к использованию функция для надёжных HTTP POST-запросов. Поддерживает:

* идемпотентность через Idempotency-Key,
* экспоненциальный бэкофф с джиттером,
* различение клиентских (4xx) и серверных (5xx/429) ошибок.

🛠 pip install requests

Подпишись 👉🏻 @KodduuPython 🤖
2
⚡️ Кеширование HTTP-запросов с автоочисткой и TTL


import requests, time
from functools import lru_cache

@lru_cache(maxsize=128)
def _cached_get(url, ttl):
t = time.time()
r = requests.get(url, timeout=5)
return {"data": r.json(), "t": t}

def get_with_cache(url, ttl=60):
r = _cached_get(url, ttl)
if time.time() - r["t"] > ttl:
_cached_get.cache_clear()
return get_with_cache(url, ttl)
return r["data"]


📌 Простая обёртка для запросов, которая:

* кеширует ответы на ttl секунд,
* автоматически сбрасывает устаревшие данные,
* уменьшает нагрузку на API и ускоряет ответы.

🛠 pip install requests

Подпишись 👉🏻 @KodduuPython 🤖
Общая стоимость курсов в программе Junior Python Developer и Data Scientist +интервью тесты более 16 000 рублей 💰

До 31 октября всего 3450 рублей 🔥🔥🔥

Подпишись 👉🏻 @KodduuPython 🤖
🧩 Безопасное шифрование конфигураций (.env → .env.enc)


from cryptography.fernet import Fernet
import os

def encrypt_env(src=".env", dst=".env.enc", key_file="key.txt"):
key = Fernet.generate_key()
with open(key_file, "wb") as f: f.write(key)
fernet = Fernet(key)
with open(src, "rb") as f: data = f.read()
with open(dst, "wb") as f: f.write(fernet.encrypt(data))

def decrypt_env(dst=".env", src=".env.enc", key_file="key.txt"):
key = open(key_file,"rb").read()
fernet = Fernet(key)
with open(src,"rb") as f: data=f.read()
with open(dst,"wb") as f: f.write(fernet.decrypt(data))


📌 Храни конфиги и API-ключи безопасно:
encrypt_env() — зашифровывает .env,
decrypt_env() — расшифровывает перед запуском.
Ключ лежит отдельно и не коммитится в git.

🛠 pip install cryptography

Подпишись 👉🏻 @KodduuPython 🤖
👍1
📦 Автоматическое сжатие и архивирование логов


import gzip, shutil, os, glob, datetime

def rotate_logs(path="logs/*.log", keep_days=7):
now = datetime.datetime.now()
for file in glob.glob(path):
mtime = datetime.datetime.fromtimestamp(os.path.getmtime(file))
if (now - mtime).days > 0:
gz = f"{file}.{mtime:%Y%m%d}.gz"
with open(file, "rb") as f_in, gzip.open(gz, "wb") as f_out:
shutil.copyfileobj(f_in, f_out)
open(file, "w").close() # truncate log
for gz in glob.glob("logs/*.gz"):
mtime = datetime.datetime.fromtimestamp(os.path.getmtime(gz))
if (now - mtime).days > keep_days:
os.remove(gz)


📌 Автоматическая ротация логов:

* старые .log → архивируются в .gz;
* старше keep_days удаляются;
* экономит место и сохраняет историю.

🛠 всё на стандартной библиотеке — ничего ставить не нужно

Подпишись 👉🏻 @KodduuPython 🤖
👍31
Forwarded from AIGENTTO
Почему n8n вам не подойдет?

n8n или Нэйтон и прочие low-code/no-code фреймворки хороши в теории, но когда дело доходит до практики, нужно начинать писать свой код и вставлять его в блоки workflow no-code тулов. Например, чтобы сделать это в Yandex Workflow, у Yandex-разработчика ушло 2 дня 😀 Это не шутка — это правда.

Потом понимаешь, что UI/UX таких тулов очень убогий, а за то время, пока ты выясняешь, почему оно не работает, уже можно было написать много кода (тем более сейчас, когда есть LLM IDE).

И самое главное — все хотят кастомных штук: одному нужны стриминг, другому — чтобы внутри бота был task manager для support, третьему — особая красивая кодировка букв. Всё это нельзя сделать в любых no-code/low-code тулах без кода.

Мне кажется, эра no-code тулов, начавшаяся ещё в 00-х и так и не снискавшая успеха, скоро окончательно закончится, потому что писать код благодаря LLM стало просто и дешево. Но всякие консультанты упорно продают no-code: "зачем вам разработчики, сделай всё сам перетаскиванием кубиков" 😀

Подпишись 👉🏻 @aigentto 🤖
👉 4 курса 207 уроков 504 теста и 171 задача 🔥

Именно такой объем в программе Junior Python Developer и Data Scientist +интервью тесты 👈👈👈

Все это со скидкой 50% до конца октября 👏

Подпишись 👉🏻 @KodduuPython 🤖
🔐 Безопасное хранение токенов в системном keyring


import keyring, os

def save_token(service, token):
user = os.getlogin()
keyring.set_password(service, user, token)

def get_token(service):
user = os.getlogin()
return keyring.get_password(service, user)

def delete_token(service):
user = os.getlogin()
keyring.delete_password(service, user)


📌 Мини-хранилище API-токенов в системном keychain
(использует встроенную безопасную ОС-хранилку — macOS Keychain, Windows Credential Manager, Linux Secret Service).

🛠 pip install keyring

Подпишись 👉🏻 @KodduuPython 🤖
🔍 Улучшаем код с помощью списковых включений


def transform_data(data):
try:
# Пример спискового включения для преобразования
transformed =
return transformed
except Exception as e:
print(f"Ошибка при преобразовании данных: {e}")
return []

# Пример использования
raw_data = [" Apple ", " Banana", "Cherry ", 42, None]
cleaned_data = transform_data(raw_data)
print(cleaned_data) # Вывод: ['apple', 'banana', 'cherry']


📌 Этот код демонстрирует использование списковых включений для очистки и преобразования списка строк. Он удаляет пробелы и
переводит строки в нижний регистр, игнорируя нестроковые элементы. Это полезно для обработки данных, таких как очистка
пользовательского ввода или подготовки текстовых данных для анализа.

Подпишись 👉🏻 @KodduuPython 🤖
2
⚡️ Эффективная обработка данных с помощью генераторов Python


def read_large_file(file_path: str):
"""Генератор для построчного чтения большого файла."""
try:
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
yield line.strip()
except FileNotFoundError:
print(f"Файл {file_path} не найден.")
except IOError as e:
print(f"Ошибка при чтении файла: {e}")

# Пример использования
if __name__ == "__main__":
file_path = "large_data.txt"
for line in read_large_file(file_path):
print(line) # Обработка строки



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

Подпишись 👉🏻 @KodduuPython 🤖