Программистика
Закритий канал
Лучший канал про python Ссылка для друга: https://t.me/+Ai6ughKtf5g2ZmFi Купить рекламу: https://telega.in/c/+Ai6ughKtf5g2ZmFi Админ: @JeyRahol По рекламе: @ReivuManager
Показати більше5 768
Підписники
-324 години
-137 днів
-6530 днів
Архів дописів
5 801
⚡️ `cached_property`: кэшируй свойство без лишнего кода
Вы когда-нибудь писали свойство, которое вычисляется один раз, а потом просто возвращает сохранённое значение? Например, тяжёлый расчёт из атрибутов объекта. В Python 3.8+ для этого есть встроенный декоратор
functools.cached_property.
❌ Было (ручной кэш):
class Data:
def __init__(self):
self._result = None
@property
def result(self):
if self._result is None:
self._result = self._calculate()
return self._result
✔️ Стало (одна строка):
from functools import cached_property
class Data:
@cached_property
def result(self):
return self._calculate()
🟢 Как работает: при первом обращении к obj.result метод выполняется, а результат сохраняется в __dict__ объекта. При повторных обращениях возвращается уже готовое значение.
⚠️ Важно: работает только для классов с __dict__ (не для __slots__). Если объект изменяемый и зависит от других атрибутов, кэш может устареть — используйте осознанно.
Идеально для дорогих вычислений, чтения из БД, парсинга конфигов.
Программистика|| #Статья5 801
🐈 Декораторы в Python
Парадокс этого курса в том, что он МАЛЕНЬКИЙ, но при этом позволяет сделать БОЛЬШОЙ шаг в понимании функциональных возможностей Python и внутренней механики функций.
🌐 СсылкаПрограммистика || #Course
5 801
0️⃣ Секрет `int.bit_count()`: считай единицы в двоичном представлении без циклов
В Python 3.10+ появился встроенный метод для подсчёта единичных битов в числе. Больше не нужно писать циклы или использовать
bin(x).count('1').
❌ Было (медленно и некрасиво):
x = 42
count = bin(x).count('1') # 3
✔️ Стало (быстро и чисто):
x = 42
count = x.bit_count() # 3
🟢 Почему круто:
- Работает на уровне C — быстрее, чем преобразование в строку.
- Поддерживает отрицательные числа (возвращает количество единиц в дополнительном коде).
- Идеально для битовых масок, криптографии, алгоритмов.
Пример с битовой маской:
permissions = 0b101101
print(permissions.bit_count()) # 4 — количество включённых флагов
Запомни: bit_count() — твой друг, когда работаешь с битами.
Программистика|| #tips5 801
Вся правда о комиссиях — от ИИ на данных FinamTrade
ИИ-агенты забираются в банковские процессы — а ваши счета пока разбираются вручную. Считать вручную долго.
💻 Finam MCP передаёт ваши счета, позиции и историю сделок в привычный AI-клиент (ChatGPT, Claude и др.). Дальше вы просто спрашиваете ИИ: динамика портфеля, прибыль и убытки, комиссии, графики — ответ по реальным данным FinamTrade.
• Счета, история сделок и заявок — прямо в чате с ИИ
• Интерактивные графики, списки наблюдения, заметки
• Несколько счетов в одном запросе, работает и с демо
• Токен за пару минут в FinamTrade, сервис бесплатный
✅ Дополнительный софт не нужен. Сгенерируйте MCP-токен и задайте ИИ первый вопрос о своих сделках.
Информация не является индивидуальной инвестиционной рекомендацией и не гарантирует доходности. Инвестиции связаны с риском.
Попробовать
Финансовые услуги оказывает: АО «Инвестиционная компания «ФИНАМ».
#реклама 16+
broker.finam.ru
О рекламодателе
5 801
Что ему написали, что он выдал ТАКОЕ?
Иногда смотришь на чужой результат нейросети и не понимаешь: почему у тебя получается поздравление от завуча, а у него — будто работала целая команда?
Самое интересное здесь — запрос, который остался за кадром.
В «Докторе GPT» разбирают нейросети, делятся готовыми промптами и находками для текстов, картинок и видео.
Чтобы было что скопировать, попробовать и оставить себе 👇
https://t.me/+sH14t7NdryRhOGRi
5 801
🕷 Библиотека Python: Scrapling
Scrapling — это адаптивный фреймворк для веб-скрапинга, который решает главную боль парсеров: «сайт изменился — код сломался». Вместо жёстких CSS-селекторов он использует умное отслеживание элементов, запоминая их визуальные признаки и контекст. Если вёрстка обновилась, Scrapling автоматически находит нужные данные заново. Плюс в комплекте — обход Cloudflare, поддержка JavaScript-рендеринга, асинхронность и встроенный MCP-сервер для AI-агентов.
✔️ Установка:
pip install scrapling
Программистика|| #Library5 801
😎 Глубокое обучение на Python. 2-е международное издание
Глубокое обучение динамично развивается, открывая все новые и новые возможности создания ПО. Это не только автоматический перевод текстов с одного языка на другой, распознавание изображений, но и многое другое. Глубокое обучение превратилось в важный навык, необходимый каждому разработчику. Keras и TensorFlow облегчают жизнь разработчикам и позволяют легко работать даже тем, кто не имеет фундаментальных знаний в области математики или науки о данных. Настала пора познакомиться с глубоким обучением и мощной библиотекой Keras! В этом расширенном и дополненном издании создатель библиотеки Keras — Франсуа Шолле — делится знаниями и с новичками, и с опытными специалистами. Иллюстрации и наглядные примеры помогут вам разобраться с самыми сложными вопросами и концепциями. Вы быстро приобретете навыки, необходимые для разработки приложений глубокого обучения.Программистика || #Книги
5 801
+1
Как связаны случайные графы, дата-центры и человек, который просто хотел разобраться, как всё это работает?
На самом деле — очень просто. Иногда, чтобы понять, почему современные системы устроены именно так, приходится залезть в математику, теорию графов и архитектуру дата-центров. А потом ещё и объяснить всё это человеческим языком.
Именно этим занимается Аня — разработчик в Microsoft — в своём Telegram-канале Baba Нюра’s Wisdom.
Здесь разбирают IT без попытки сделать вид, что вы уже знаете все эти страшные слова. Недавно, например, говорили о квазислучайных графах, строили графы своими руками, а потом добрались до того, как устроены сети в дата-центрах.
А ещё здесь есть собеседования, карьера в IT, жизнь в США, путешествия, книги и просто истории из жизни разработчика.
Если хочется не просто читать про IT, а наконец понять, что там происходит под капотом, — загляните в Baba Нюра’s Wisdom.
Реклама. Аникина А.С. ИНН 772796434915. erid: 2W5zFK8npCq
5 801
🧵 `contextvars` — как пробросить данные через весь асинхронный код
Вы пишете асинхронный сервис на
asyncio. В каждом запросе нужно логировать request_id, передавать текущего пользователя и собирать метрики. Вы начинаете прокидывать эти данные через аргументы всех функций. Через неделю сигнатуры становятся трёхэтажными, а код — нечитаемым. Знакомо? Тогда эта статья для вас. contextvars решает эту проблему элегантно.
🧱 Проблема: `threading.local` не работает в async
В синхронном мире для «глобальных в рамках потока» данных используют threading.local. Каждый поток видит свои значения, и они не мешают друг другу.
import threading
local_data = threading.local()
def worker():
local_data.request_id = "abc"
print(local_data.request_id) # abc
t = threading.Thread(target=worker)
t.start()
Но в asyncio всё иначе. Корутины выполняются в одном потоке, переключаясь на await. Если использовать threading.local, все корутины будут видеть одни и те же данные, потому что поток один. Начинается хаос: request_id одного запроса «протекает» в другой.
# ❌ Так делать нельзя
import threading
local_data = threading.local()
async def handle_request(request_id):
local_data.request_id = request_id
await some_async_operation()
print(local_data.request_id) # может быть уже чужой request_id!
🧠 `contextvars`: контекст, привязанный к задаче
contextvars — это модуль из стандартной библиотеки, который создаёт переменные, чьи значения привязаны к текущему контексту выполнения. В asyncio каждая задача (Task) получает свой контекст. Переключение между корутинами не смешивает данные.
from contextvars import ContextVar
request_id: ContextVar[str] = ContextVar("request_id", default="unknown")
async def handle_request(rid):
request_id.set(rid) # устанавливаем значение для текущего контекста
await some_async_operation()
print(request_id.get()) # всегда наш rid
async def some_async_operation():
await asyncio.sleep(0.1)
print(request_id.get()) # тоже наш rid, хотя функция вложенная
Что произошло:
- ContextVar создаёт переменную.
- .set(value) устанавливает значение в текущем контексте.
- .get() читает значение из текущего контекста.
- При переключении на другую корутину контекст сохраняется и восстанавливается.
🧪 Пример: логирование с `request_id`
Самое частое применение — прокидывание request_id в логи через middleware.
import asyncio
import logging
from contextvars import ContextVar
request_id: ContextVar[str] = ContextVar("request_id", default="-")
# Настраиваем логгер с request_id
class RequestIdFilter(logging.Filter):
def filter(self, record):
record.request_id = request_id.get()
return True
logging.basicConfig(
format="%(asctime)s [%(request_id)s] %(message)s",
level=logging.INFO,
)
logger = logging.getLogger(__name__)
logger.addFilter(RequestIdFilter())
async def handle_request(rid):
request_id.set(rid)
logger.info("Начало обработки")
await asyncio.sleep(0.1)
logger.info("Конец обработки")
async def main():
await asyncio.gather(
handle_request("req-1"),
handle_request("req-2"),
)
asyncio.run(main())
Вывод:
2026-10-19 12:00:00,001 [req-1] Начало обработки 2026-10-19 12:00:00,002 [req-2] Начало обработки 2026-10-19 12:00:00,102 [req-1] Конец обработки 2026-10-19 12:00:00,102 [req-2] Конец обработкиКаждый запрос видит свой
request_id, хотя все корутины работают в одном потоке.
🧱 `copy_context` и `run_in_executor`
Если вы запускаете синхронный код в пуле потоков через loop.run_in_executor, контекст не пробрасывается автоматически. Нужно скопировать его вручную.
import asyncio
from contextvars import copy_context
async def main():
request_id.set("req-42")
loop = asyncio.get_running_loop()
ctx = copy_context()
# Запускаем синхронную функцию в потоке с нашим контекстом
await loop.run_in_executor(None, ctx.run, sync_function)
ctx.run(func) выполняет функцию в скопированном контексте, и request_id.get() внутри sync_function вернёт "req-42".
⚠️ Ловушки и частые ошибки
1. Использовать `threading.local` в асинхронном коде — данные перемешиваются между корутинами.
2. Забыть, что `set()` возвращает `Token` — можно использовать для сброса значения.
```python
token = request_id.set("abc")
# ...
request_id.reset(token) # вернуть прежнее значение
```
3. Ожидать, что контекст пробросится в `run_in_executor` сам — нужно копировать через copy_context.
4. Создавать `ContextVar` внутри функции — создавайте на уровне модуля, иначе каждый вызов создаёт новую переменную.
5. Использовать `ContextVar` для передачи больших данных — это лёгкий механизм для небольших значений (ID, флаги, пользователь).
💡 Запомни:
🟢 contextvars — это threading.local для асинхронного мира.
🟢 ContextVar привязан к контексту задачи, а не к потоку.
🟢 Используйте .set() и .get() для установки и чтения значения.
🟢 Для run_in_executor копируйте контекст через copy_context().
🟢 Идеально для request_id, текущего пользователя, флагов и метрик.
🟢 Не используйте threading.local в asyncio — данные перемешаются.
contextvars — это не «ещё одна фича». Это способ писать асинхронный код, который не превращается в спагетти из аргументов. Освоив его, вы перестанете бояться пробрасывать данные через вложенные вызовы.
Программистика|| #Статья5 801
🧠 Отгадка: что выведет этот код?
class A:
def __new__(cls):
return B()
def __init__(self):
print("A init")
class B:
def __init__(self):
print("B init")
a = A()
print(type(a).__name__)
✔️ Правильный ответ: 2. `B init`, затем `B`
📖 Почему так происходит?
Когда вы вызываете A(), Python сначала вызывает __new__ класса A. В нашем коде __new__ возвращает экземпляр класса `B` (вызов B()), а не A. Поэтому:
1. __new__ создаёт объект класса B → срабатывает B.__init__ → печатается B init.
2. Поскольку __new__ вернул объект не того класса, для которого вызван (вернул B, а не A), Python не вызывает A.__init__. Поэтому A init не печатается.
3. a — это экземпляр B. type(a).__name__ возвращает 'B'.
Итог: B init, затем B.
Ключевой момент: __init__ вызывается только если __new__ вернул экземпляр того же класса (или его подкласса). Если возвращён объект другого класса, __init__ игнорируется.
Это отличный пример того, как __new__ может полностью изменить поведение конструктора.
Ставьте 🔥, если было полезно!
Программистика|| #quiz5 801
⚪️ Все лучшие инструкции, гайды, книги и инструменты — без воды.
☁️ Хакинг & ИБ — 756GB
⌨️ Python — 955GB
🙃 Linux & Bash — 459GB
🤒 OSINT — 315GB
🖥 Курсы & GitHub — 1579GB
➡️ Присоединяйтесь и качай.
Пост будет удален через 48 часов.
5 801
⚡️ Библиотека Python: Thermite
Thermite — это сверхбыстрая библиотека машинного обучения, написанная на Rust и полностью совместимая с scikit-learn. Она переписывает вычислительно тяжёлые части sklearn нативно на Rust, используя SIMD, многопоточность Rayon и оптимизации matrixmultiply, при этом сохраняя тот же Python API. Достаточно заменить
import sklearn на import thermite — никакого нового синтаксиса и руководств по миграции не требуется. Библиотека поддерживает zero-copy интеграцию с Polars, GPU-ускорение через wgpu и настоящий параллелизм без GIL, что делает её идеальной для высоконагруженных ML-пайплайнов и подготовки данных.
✔️ Установка:
pip install thermite-ml
Программистика|| #Library5 801
🔍 Секрет `math.isclose`: никогда не сравнивай float через `==`
Вы уже знаете, что
0.1 + 0.2 не равно 0.3? В Python это даёт False из-за особенностей хранения чисел с плавающей точкой.
❌ Плохо:
print(0.1 + 0.2 == 0.3) # False
✅ Хорошо:
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
math.isclose(a, b) сравнивает числа с учётом погрешности. Можно настроить точность через rel_tol и abs_tol.
🟢 Запомни: для float используй math.isclose, а не ==.
Программистика|| #tips5 801
🧠 Загадка на ночь: что выведет этот код?
class A:
def __new__(cls):
return B()
def __init__(self):
print("A init")
class B:
def __init__(self):
print("B init")
a = A()
print(type(a).__name__)
Варианты:
1. A init и B init, затем A
2. B init, затем B
3. A init, затем A
4. B init, затем A
Пиши свой вариант в комментарии! Ответ и разбор — через пару часов 🔥
Программистика|| #quiz5 801
👩💻 От 1 до 10 000 RPS: Как масштабируется Backend приложение при росте нагрузки
📱 ПервоисточникПрограммистика|| #video
5 801
💀 Почему вы не пишете тесты (и почему это ошибка)
Вы пишете код. Он работает. Вы проверяете вручную — «вроде норм». Через месяц нужно что-то изменить. Вы меняете одну строчку. Ломается три других. Вы не понимаете, где именно. Начинаете проверять всё руками снова. Знакомо? Тогда эта статья для вас. Только честно, без утешений.
🧱 Почему вы не пишете тесты
Давайте честно. Вы не пишете тесты, потому что:
- «Это долго» - «Я и так знаю, что код работает» - «Тесты пишут только в больших компаниях» - «У меня нет времени»Но правда в другом: вы не пишете тесты, потому что не умеете. Вас этому не научили. Курсы про тесты — скучные. А ручная проверка даёт мгновенный результат. 📌 Правило: если вы не можете написать тест на свою функцию — вы не понимаете, что она делает. 🧱 Что происходит без тестов Каждое изменение — это русская рулетка. Вы не знаете:
- что сломалось после правки - работает ли код на краевых случаях - можно ли безопасно рефакторить - не вернулся ли старый багВы тратите часы на ручную проверку. И всё равно пропускаете баги. Потому что человек не может проверить 50 сценариев в голове одновременно. 📌 Правило: код без тестов — это код, который работает «сегодня». Завтра он может сломаться. 🧱 Тесты — это не про «доказать, что код работает» Новички думают, что тесты нужны, чтобы доказать правильность. На самом деле тесты нужны для другого:
- Уверенность при рефакторинге. Вы меняете код и знаете: если что-то сломалось — тест покажет. - Документация поведения. Тест — это живой пример использования функции. - Быстрая обратная связь. Ошибку видно за секунды, а не через неделю в проде. - Смелость менять. Без тестов вы боитесь трогать код. С тестами — рефакторите спокойно.📌 Правило: тесты — это не про «доказать», а про «не бояться». 🧱 Почему это ошибка Работодатели знают: код без тестов — это технический долг. Проект, который нельзя безопасно менять, умирает. Именно поэтому на собеседованиях спрашивают про тестирование.
Вы можете быть гениальным программистом. Но если вы не пишете тесты — вы не инженер. Вы ремесленник, который делает одноразовые вещи.📌 Правило: в современной разработке тесты — это не опция. Это часть профессии. 🧱 Что делать прямо сейчас
1. Начните с одного теста. Возьмите самую простую функцию и напишите для неё test_*.py. Пять минут — и вы уже в игре. 2. Не гонитесь за 100% покрытием. Начните с критичных мест. 3. Используйте `pytest`. Он проще, чем unittest, и читается как обычный код. 4. Пишите тесты до рефакторинга. Сначала зафиксируйте поведение, потом меняйте. 5. Не оправдывайтесь. «Нет времени на тесты» — значит, будет время на отладку багов в проде.💡 Запомни: 🟢 Тесты — не про доказательство, а про уверенность. 🟢 Без тестов рефакторинг — это хождение по минному полю. 🟢 Не можете написать тест — не понимаете функцию. 🟢 Начните с одного теста. Прямо сейчас. 🟢 Тесты — это часть профессии, а не «для больших компаний». Вы не пишете тесты не потому, что у вас нет времени. Вы не пишете их потому, что не умеете. Научитесь — и код станет надёжнее, а работа спокойнее. Если зашла такая рубрика ставь реакцию 🔥? Программистика|| #Статья
5 801
🧠 TypeVar и ограничения типов: как писать гибкий, но безопасный код
Вы пишете функцию, которая должна работать с разными типами, но при этом сохранять типовую безопасность. Например, функция
first() возвращает первый элемент списка — но если вы передали list[int], она должна вернуть int, а не Any. Для этого в Python есть TypeVar — мощный инструмент дженериков. Разбираемся, как его готовить.
🧱 Что такое `TypeVar`
TypeVar — это переменная типа, которая позволяет создавать обобщённые (generic) функции и классы. Она говорит: «тип будет уточнён при вызове».
from typing import TypeVar
T = TypeVar('T')
def first(items: list[T]) -> T:
return items[0]
# type checkers знают, что результат — int
result = first([1, 2, 3]) # int
Без TypeVar пришлось бы возвращать Any или object, теряя всю информацию о типе.
🧱 Ограничения: `bound` vs `constraints`
У TypeVar есть два способа ограничить типы.
1. `bound` — верхняя граница
Говорит: «тип должен быть наследником указанного класса».
from typing import TypeVar
class Animal:
def speak(self) -> str:
return "..."
class Dog(Animal):
def speak(self) -> str:
return "Гав"
T = TypeVar('T', bound=Animal)
def make_speak(animal: T) -> T:
print(animal.speak())
return animal
make_speak(Dog()) # OK
make_speak(42) # ❌ type checker ошибётся
🟢 Важно: bound разрешает наследников, но не требует точного типа.
2. `constraints` — жёсткий список типов
Говорит: «тип должен быть ровно одним из перечисленных».
from typing import TypeVar
T = TypeVar('T', int, str)
def double(value: T) -> T:
return value * 2 # работает и для int, и для str
double(5) # int
double("ab") # str
double(3.14) # ❌ type checker ошибётся — float не разрешён
🟢 Разница: bound — «или наследник», constraints — «ровно один из списка».
🧱 Generic-классы
TypeVar можно использовать и в классах.
from typing import TypeVar, Generic
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
stack: Stack[int] = Stack()
stack.push(1)
stack.push("abc") # ❌ type checker ошибётся
🟢 Type checkers (mypy, pyright) проверят, что вы не смешиваете типы в одном стеке.
🧱 Практический пример: кэш с типами
from typing import TypeVar, Generic, Optional
K = TypeVar('K')
V = TypeVar('V')
class Cache(Generic[K, V]):
def __init__(self) -> None:
self._data: dict[K, V] = {}
def get(self, key: K) -> Optional[V]:
return self._data.get(key)
def set(self, key: K, value: V) -> None:
self._data[key] = value
cache = Cache[str, int]()
cache.set("age", 30)
value = cache.get("age") # int | None
🧱 Ограничения и `bound` в реальном коде
from typing import TypeVar
from collections.abc import Sequence
T = TypeVar('T', bound=Sequence)
def total_length(items: list[T]) -> int:
return sum(len(item) for item in items)
total_length([[1, 2], "abc", (4, 5)]) # OK
total_length([1, 2, 3]) # ❌ int не Sequence
⚠️ Ловушки и частые ошибки
1. Путать `bound` и `constraints`.
bound — наследники разрешены, constraints — только точные типы.
2. Использовать `TypeVar` без необходимости.
Если функция работает с любым типом и не зависит от него — используйте object или Any.
3. Забыть про `Generic` в классе.
Без Generic[T] type checker не поймёт, что класс обобщённый.
4. Ожидать, что `TypeVar` работает в runtime.
TypeVar — только для статических анализаторов. В рантайме это просто объект.
5. Игнорировать `covariance` и `contravariance`.
Для сложных случаев есть covariant=True и contravariant=True, но это уже высший пилотаж.
💡 Запомни:
🟢 TypeVar — переменная типа для обобщённых функций и классов.
🟢 bound — верхняя граница (наследники разрешены).
🟢 constraints — жёсткий список допустимых типов.
🟢 Используйте Generic[T] для обобщённых классов.
🟢 TypeVar работает только со статическими анализаторами (mypy, pyright).
Программистика|| #Статья