es
Feedback
Программистика

Программистика

Canal cerrado

Лучший канал про python Ссылка для друга: https://t.me/+Ai6ughKtf5g2ZmFi Купить рекламу: https://telega.in/c/+Ai6ughKtf5g2ZmFi Админ: @JeyRahol По рекламе: @ReivuManager

Mostrar más
5 852
Suscriptores
Sin datos24 horas
-77 días
+27930 días

Carga de datos en curso...

Atraer Suscriptores
septiembre '26
septiembre '26
+121
en 4 canales
agosto '26
+380
en 75 canales
Get PRO
julio '26
+85
en 17 canales
Get PRO
junio '26
+59
en 10 canales
Get PRO
mayo '26
+80
en 25 canales
Get PRO
abril '26
+240
en 40 canales
Get PRO
marzo '26
+352
en 85 canales
Get PRO
febrero '26
+120
en 7 canales
Get PRO
enero '26
+273
en 15 canales
Get PRO
diciembre '25
+186
en 52 canales
Get PRO
noviembre '25
+488
en 84 canales
Get PRO
octubre '25
+43
en 16 canales
Get PRO
septiembre '25
+62
en 1 canales
Get PRO
agosto '25
+649
en 34 canales
Get PRO
julio '25
+172
en 43 canales
Get PRO
junio '25
+306
en 26 canales
Get PRO
mayo '25
+75
en 4 canales
Get PRO
abril '25
+80
en 1 canales
Get PRO
marzo '25
+176
en 17 canales
Get PRO
febrero '25
+375
en 30 canales
Get PRO
enero '25
+326
en 18 canales
Get PRO
diciembre '24
+656
en 26 canales
Get PRO
noviembre '24
+350
en 14 canales
Get PRO
octubre '24
+904
en 42 canales
Get PRO
septiembre '24
+167
en 18 canales
Get PRO
agosto '24
+153
en 3 canales
Get PRO
julio '24
+611
en 18 canales
Get PRO
junio '24
+451
en 10 canales
Get PRO
mayo '24
+1 207
en 32 canales
Get PRO
abril '24
+315
en 9 canales
Get PRO
marzo '24
+101
en 4 canales
Get PRO
febrero '24
+180
en 12 canales
Get PRO
enero '24
+413
en 20 canales
Get PRO
diciembre '23
+30
en 4 canales
Get PRO
noviembre '23
+250
en 9 canales
Fecha
Crecimiento de Suscriptores
Menciones
Canales
15 septiembre+3
14 septiembre0
13 septiembre+14
12 septiembre+2
11 septiembre0
10 septiembre+1
09 septiembre+6
08 septiembre0
07 septiembre+2
06 septiembre+73
05 septiembre0
04 septiembre0
03 septiembre0
02 septiembre+18
01 septiembre+2
Publicaciones del Canal
⚙️ Библиотека Python: Dynaconf Dynaconf — это гибкая библиотека для управления настройками приложения. Она поддерживает множе
⚙️ Библиотека Python: Dynaconf Dynaconf — это гибкая библиотека для управления настройками приложения. Она поддерживает множество форматов (.toml, .yaml, .json, .ini, .env), автоматически подхватывает переменные окружения и позволяет легко переключаться между средами (development, production). Вдохновлена принципами 12-factor приложений и избавляет от хаоса с конфигами. ✔️ Установка:
pip install dynaconf
🐱 Ссылка на репозиторий Программистика|| #Library

2
Программистика
Программистика
451
3
👩‍💻 9 ошибок, которые выдают Junior Backend разработчика Джуниор — это не тот, кто мало знает, а тот, кто ещё не научился д
👩‍💻 9 ошибок, которые выдают Junior Backend разработчика Джуниор — это не тот, кто мало знает, а тот, кто ещё не научился думать как инженер. Ошибки в коде — это полбеды. Ошибки в подходе к работе — вот что действительно выдаёт новичка. Разбираем 9 классических промахов, которые мешают джунам расти и проходить собеседования. 📱 Первоисточник Программистика|| #video
833
4
📁 `__init__.py` — что скрывается за этим файлом и зачем он нужен (не только чтобы сделать папку пакетом) Каждый Python-разработчик видел этот файл в папках проектов. Многие думают, что __init__.py — это просто маркер, который говорит Python: «эта папка — пакет». И оставляют его пустым. Но это лишь вершина айсберга. За ним скрывается мощный механизм управления импортами, инициализацией пакетов и даже экспортом API. Разбираемся, что умеет этот маленький файл. 🧱 Что делает `__init__.py` 1. Делает директорию пакетом До Python 3.3 __init__.py был обязателен для того, чтобы Python воспринимал папку как пакет. Сейчас это не строго обязательно (работают namespace-пакеты), но оставлять файл всё равно хорошая практика: он явно показывает, что папка — часть проекта. 2. Выполняется при первом импорте пакета Когда вы пишете import mypackage, Python сначала выполняет код из mypackage/__init__.py. Это даёт возможность выполнить инициализацию: настроить логирование, загрузить конфиги, установить соединение с БД — всё, что нужно сделать до работы с модулями пакета. 3. Формирует публичный интерфейс пакета Через __init__.py можно определить, какие объекты будут доступны при импорте пакета. Это позволяет скрыть внутреннюю структуру и предоставить пользователю удобный API. 📦 Что можно писать внутри `__init__.py` 1. Импорты подмодулей для удобного доступа Вместо того чтобы писать: ```python from mypackage.module import MyClass from mypackage.submodule import helper ``` Вы можете сделать в __init__.py: ```python from .module import MyClass from .submodule import helper ``` И тогда пользователь сможет писать: ```python from mypackage import MyClass, helper ``` Это делает код чище и скрывает внутреннюю структуру пакета. 2. `__all__` для явного экспорта Если вы используете from mypackage import *, Python ищет список __all__ в __init__.py. Определив его, вы контролируете, что попадёт в глобальное пространство имён при таком импорте. ```python all = ['MyClass', 'helper'] ``` Без __all__ import * импортирует всё, что не начинается с подчёркивания, что может быть нежелательно. 3. Инициализация пакета Код, который нужно выполнить один раз при первом импорте: ```python import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(name) ``` Это удобно для настройки логирования, загрузки конфигурации или проверки окружения. 4. Версионирование Вы можете определить __version__ в __init__.py, чтобы версия пакета была доступна как атрибут. ```python version = "1.0.0" ``` Тогда пользователь сможет проверить версию через mypackage.__version__. 5. Управление подпакетами Можно динамически импортировать подпакеты или модули в зависимости от условий (платформа, переменные окружения). 🧪 Пример: организация пакета для работы с API Допустим, у вас есть пакет api_client со структурой: api_client/ ├── __init__.py ├── client.py ├── auth.py ├── models.py └── utils.py В __init__.py вы можете сделать: from .client import APIClient from .auth import authenticate from .models import User, Product from .utils import validate_response __all__ = ['APIClient', 'authenticate', 'User', 'Product', 'validate_response'] Тогда внешний код будет использовать пакет так: from api_client import APIClient, authenticate client = APIClient() authenticate(client) Внутренняя структура скрыта, а пользователь получает чистый интерфейс. ⚠️ Ловушки и частые ошибки 1. Слишком много кода в `__init__.py` Всё, что выполняется при импорте, замедляет загрузку пакета. Оставляйте только инициализацию и импорты. Тяжёлые вычисления или загрузку данных выносите в отдельные функции. 2. Циклические импорты Если в __init__.py вы импортируете модули, которые в свою очередь импортируют что-то из __init__.py, может возникнуть циклическая зависимость. Решение — выносить логику в отдельные модули и избегать сложных взаимных импортов. 3. Путаница с относительными импортами Используйте явные относительные импорты (.module, ..subpackage), чтобы избежать конфликтов с глобальными модулями. 4. Игнорирование `__all__` при `import *` Без __all__ import * может принести лишние объекты, включая приватные (_internal). Всегда определяйте __all__, если планируете использовать import *. 5. Создание namespace-пакетов без `__init__.py` Если вы намеренно используете namespace-пакеты (когда один пакет разбит на несколько частей), пропускайте __init__.py. Но если вы не уверены, лучше оставить файл. 💡 Запомни: 🟢 __init__.py — не просто маркер, а точка входа в пакет. 🟢 Используйте его для упрощения импортов через from .module import .... 🟢 Определяйте __all__ для контроля публичного API. 🟢 Выполняйте инициализацию, но не перегружайте файл тяжёлым кодом. 🟢 Версионируйте пакет через __version__. 🟢 Помните про циклические импорты и относительные пути. Понимание устройства __init__.py делает вас не просто пользователем библиотек, а разработчиком, который умеет проектировать свои собственные пакеты чисто и удобно. Программистика|| #Статья
681
5
🧠 Отгадка: что выведет этот код? s1 = "hello" s2 = "hello" s3 = "".join(["h", "e", "l", "l", "o"]) print(s1 is s2, s1 is s3) ✅ Правильный ответ: 2. `True False` 📖 Почему так происходит? - s1 = "hello" и s2 = "hello" — это строковые литералы. Python интернирует короткие строки (состоящие из букв, цифр и подчёркиваний) для экономии памяти. Поэтому обе переменные указывают на один и тот же объект в памяти. s1 is s2 → True. - s3 = "".join(["h", "e", "l", "l", "o"]) — строка создаётся динамически во время выполнения. Даже если содержимое совпадает, интерпретатор не интернирует её автоматически (если только не используется sys.intern()). Поэтому s3 — это новый объект. s1 is s3 → False. Ключевой момент: - is проверяет идентичность объектов (адреса в памяти), а не значения. - Литералы могут быть интернированы, а динамически созданные строки — нет. Ставьте 🔥, если было полезно! Программистика || #quiz
652
6
Sin texto...
691
7
−16% на IT-профессию с ИИ-навыками до 17 сентября Освойте профессию и ИИ-навыки, которые уже требует рынок. Начните бесплатно
−16% на IT-профессию с ИИ-навыками до 17 сентября Освойте профессию и ИИ-навыки, которые уже требует рынок. Начните бесплатно до 17 сентября и учитесь со скидкой. Яндекс Практикум. Учим профессиям и навыкам с ИИ, чтобы вы не застряли в прошлом Узнать больше #реклама 16+ practicum.yandex.ru О рекламодателе
492
8
👨‍💻Гайд «Как стать программистом». А нейронки? А рынок вакансий? А можно еще? Путь в IT в 2026 году — это не просто выучить
👨‍💻Гайд «Как стать программистом». А нейронки? А рынок вакансий? А можно еще? Путь в IT в 2026 году — это не просто выучить Python и пойти на собеседование. Рынок изменился: нейросети пишут код, джунов стало больше, а требования — выше. Как не потеряться и построить карьеру сейчас — в новом большом гайде. Программистика|| #video
790
9
🚀 Память в Python: `__slots__`, `weakref` и `gc` — когда экономить, а когда не мешать В Python принято не думать о памяти. Вроде бы есть сборщик мусора, всё автоматически — живи и радуйся. Но когда ваш сервис начинает жрать 8 ГБ на ровном месте, а объекты, которые давно не нужны, почему-то не удаляются, становится не до шуток. Разбираемся с тремя инструментами, которые помогут держать память под контролем: __slots__, weakref и gc. 🧱 Проблема: почему память заканчивается, даже если объекты уже не нужны В Python память освобождается двумя способами: - Подсчёт ссылок — удаляет объект, когда счётчик падает до нуля. Работает мгновенно. - Циклический сборщик мусора (GC) — периодически ищет группы объектов, которые ссылаются друг на друга, но никому больше не нужны. Но есть ситуации, когда память всё равно утекает: - Вы храните объекты в глобальных списках или кэшах. - Циклические ссылки не дают объектам удалиться. - Вы создаёте миллионы объектов с __dict__, и память раздувается. - Слабые ссылки не используются, хотя могли бы спасти. 📦 `__slots__` — когда миллионы объектов, а памяти жалко По умолчанию каждый экземпляр класса содержит __dict__ — словарь для хранения атрибутов. Это удобно, но дорого: словарь занимает ~56 байт плюс сами атрибуты. Для 1 млн объектов разница — сотни мегабайт. __slots__ отключает __dict__ и заменяет его на дескрипторы. Объект становится компактнее. class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) p.z = 3 # ❌ AttributeError Замер памяти: import sys class WithoutSlots: def __init__(self, x, y): self.x = x self.y = y class WithSlots: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y print(sys.getsizeof(WithoutSlots(1, 2))) # ~112 байт print(sys.getsizeof(WithSlots(1, 2))) # ~48 байт 🟢 Когда использовать: - Миллионы объектов с фиксированными атрибутами. - Классы-структуры (точки, векторы, DTO). ❌ Не для 99% проектов — оптимизируйте только по факту. 🔗 `weakref` — ссылки, которые не мешают сборщику Вы когда-нибудь создавали кэш, который должен хранить объекты, но не мешать им удаляться? Или писали Observer, но объекты не удалялись, потому что их держал список наблюдателей? Сильные ссылки держат объекты живыми. weakref — это слабая ссылка, которая не учитывается сборщиком мусора. Если на объект есть только слабые ссылки, он может быть удалён. import weakref class HeavyObject: def __del__(self): print("Объект удалён") obj = HeavyObject() weak = weakref.ref(obj) del obj print(weak()) # None Где пригодится: - Кэши (объекты удаляются, если память нужна). - Наблюдатели (слушатели удаляются, когда на них никто не ссылается). - Обратные ссылки в деревьях. Типы слабых ссылок: - weakref.ref(obj) — базовая. - WeakKeyDictionary — ключи — слабые ссылки. - WeakValueDictionary — значения — слабые ссылки. - WeakSet — множество слабых ссылок. cache = weakref.WeakValueDictionary() obj = HeavyObject() cache['key'] = obj del obj print(cache.get('key')) # None ⚠️ Ограничения: - Не все объекты поддерживают слабые ссылки (числа, строки, кортежи без изменяемых элементов). - При __slots__ нужно добавить '__weakref__'. 🧹 `gc` — ручной контроль над циклическим сборщиком В Python есть автоматический сборщик мусора для циклических ссылок. Обычно он работает незаметно, но иногда нужно вмешаться. import gc # Запустить вручную gc.collect() # Проверить пороги print(gc.get_threshold()) # (700, 10, 10) # Посмотреть объекты в поколениях print(gc.get_count()) Когда может понадобиться: - Много циклических ссылок (графы, деревья с обратными ссылками). - В долгоживущих процессах — периодический gc.collect(). - В тестах — проверить, что объекты удаляются. class Node: def __init__(self): self.parent = None a = Node() b = Node() a.parent = b b.parent = a del a, b gc.collect() # Удалит циклическую ссылку ⚠️ Ловушки и частые ошибки 1. `__slots__` везде — не нужно, усложняет код. 2. Забыть `__weakref__` в `__slots__` — слабые ссылки не работают. 3. Не проверять слабую ссылку на `None` — объект мог быть удалён. 4. Отключать `gc` без необходимости — приводит к утечкам. 5. Игнорировать циклические ссылки — они могут накапливаться. 💡 Запомни: 🟢 __slots__ — экономия памяти для миллионов объектов. 🟢 weakref — ссылки, которые не мешают удалять объекты. 🟢 gc — ручное управление циклическим сборщиком мусора. 🟢 Не оптимизируйте без измерений. 🟢 Используйте tracemalloc и gc.get_objects() для отладки утечек. Программистика || #Статья
827
10
🧠 Загадка на ночь: что выведет этот код? s1 = "hello" s2 = "hello" s3 = "".join(["h", "e", "l", "l", "o"]) print(s1 is s2, s
🧠 Загадка на ночь: что выведет этот код? s1 = "hello" s2 = "hello" s3 = "".join(["h", "e", "l", "l", "o"]) print(s1 is s2, s1 is s3) Варианты: 1. True True 2. True False 3. False True 4. False False Пиши свой вариант в комментарии! Ответ и разбор — через пару часов 🔥 Программистика || #quiz
775
11
Весь Python. Самое актуальное и исчерпывающее руководство Всеобъемлющее современное руководство по программированию на Python
Весь Python. Самое актуальное и исчерпывающее руководство Всеобъемлющее современное руководство по программированию на Python, охватывающее фундаментальные идеи и практические приемы! Вы научитесь писать собственные программы и получите четкое представление о том, куда двигаться дальше и как использовать полученные знания. Изучение Python подкреплено практикой — огромным количеством примеров приложений. К концу книги вы будете готовы применить полученные знания и создать несколько реальных проектов. Вы научитесь эффективно использовать Python в анализе данных, веб-разработке и автоматизации задач. Книга включает описание новейших возможностей, появившихся в версиях Python 3.9–3.12, в том числе главы об аннотациях типов и консольных приложениях, а также примеры, демонстрирующие современные практики веб-разработки на Python. Программистика || #Книги
811
12
3 дня. 60 откликов. 1 оффер. Очень интересный кейс произошёл у команды Софи — ии-ассистента для поиска работы. К ним в поддер
3 дня. 60 откликов. 1 оффер. Очень интересный кейс произошёл у команды Софи — ии-ассистента для поиска работы. К ним в поддержку написала девушка, которая отписалась от продукта ещё месяц назад: «Мне прислали оффер!» Начали разбираться — оказывается, она пользовалась только 3 тестовыми днями. То есть за 3 дня ии-ассистент успел сделать 60 откликов. Потом она отписалась. А уже позже — из этих откликов её позвали на интервью, и одно из них привело к офферу. «Оффер с той вакансии, куда я сама никогда бы не откликнулась» Изначально Аня отменила подписку, так как было дорого. Ребята честно спросили у Ани, считает ли она теперь, что подписка стоит своих денег — и получили утвердительный ответ. В следующий раз доступ в Софи откроется 22 сентября. Если хочешь получить 3 дня бесплатного доступа - подписывайся на этот канал, все анонсы будут там.
449
13
Шпаргалка методы списков в Python Программистика|| #doc
Шпаргалка методы списков в Python Программистика|| #doc
928
14
Sin texto...
1
15
Weekend Offer ML*: быстрый найм в Яндекс Открыли регистрацию на онлайн-мероприятие для ML и DL-специалистов. Мы ищем инженеро
Weekend Offer ML*: быстрый найм в Яндекс Открыли регистрацию на онлайн-мероприятие для ML и DL-специалистов. Мы ищем инженеров с опытом от 2 лет в областях NLP, CV, RecSys и Classic ML. Как всё устроено: ✅ До 4 сентября — регистрация на сайте. ✅ 12 сентября — две технические секции онлайн. ✅ 13 сентября — финальные интервью со знакомством с командами. Ждём вас! Подробности и форма регистрации — на сайте. Зарегистрироваться #реклама 16+ yandex.ru О рекламодателе
473
16
🖥 FastSQLA — это асинхронное расширение для SQLAlchemy версии 2.0 и выше, разработанное для интеграции с FastAPI! Оно предос
🖥 FastSQLA — это асинхронное расширение для SQLAlchemy версии 2.0 и выше, разработанное для интеграции с FastAPI! Оно предоставляет готовые шаблоны, поддержку SQLModel и встроенную пагинацию, упрощая настройку и управление асинхронными соединениями с реляционными базами данных. 🐱 Ссылка на GitHub Программистика|| #Репозиторий
990
17
Программистика
Программистика
1 073
18
🧠 Отгадка: что выведет этот код? a = [1, 2, 3] b = a a = a + [4] print(b) ✅ Правильный ответ: 1. `[1, 2, 3]` 📖 Почему так происходит? В Python оператор + для списков создаёт новый список, а не изменяет существующий. Разберём по шагам: 1. a = [1, 2, 3] — создаётся список, a указывает на него. 2. b = a — b указывает на тот же список. 3. a = a + [4] — выражение a + [4] создаёт новый список [1, 2, 3, 4]. Затем a переназначается на этот новый объект. 4. b всё ещё указывает на старый список [1, 2, 3] и не изменился. Если бы мы написали a += [4] (или a.append(4)), то изменили бы исходный список, и ответ был бы [1, 2, 3, 4]. Но здесь — создание нового объекта, поэтому b остался неизменным. Ключевой момент: + возвращает новый объект, += или append() меняют существующий. Ставьте 🔥, если было полезно! Программистика || #quiz
1 186
19
🧠 Загадка на ночь: что выведет этот код? a = [1, 2, 3] b = a a = a + [4] print(b) Варианты: 1. [1, 2, 3] 2. [1, 2, 3, 4] 3.
🧠 Загадка на ночь: что выведет этот код? a = [1, 2, 3] b = a a = a + [4] print(b) Варианты: 1. [1, 2, 3] 2. [1, 2, 3, 4] 3. [4] 4. Ошибка Пиши свой вариант в комментарии! Ответ и разбор — через пару часов 🔥 Программистика || #quiz
1 125
20
👨‍💻 Работа с памятью в Python: как экономить, не утекать и не ломать голову В Python принято не думать о памяти. Вроде бы есть сборщик мусора, всё автоматически — живи и радуйся. Но когда ваш сервис начинает жрать 8 ГБ на ровном месте, а объекты, которые давно не нужны, почему-то не удаляются, становится не до шуток. Разбираемся с тремя инструментами, которые помогут держать память под контролем: __slots__, weakref и gc. 🧱 Проблема: почему память заканчивается, даже если объектов уже нет В Python память освобождается двумя способами: 1. Подсчёт ссылок (reference counting) — удаляет объект, когда счётчик ссылок падает до нуля. Работает мгновенно. 2. Циклический сборщик мусора (GC) — периодически ищет группы объектов, которые ссылаются друг на друга, но никому больше не нужны. Но есть ситуации, когда память всё равно утекает: 🔴 Вы храните объекты в глобальных списках или кэшах. 🔴 Циклические ссылки не дают объектам удалиться. 🔴 Вы создаёте миллионы объектов с __dict__, и память раздувается. 🔴 Слабые ссылки не используются, хотя могли бы спасти. Разберём три инструмента, которые решают эти проблемы. 📦 1. `__slots__` — экономия памяти для миллионов объектов По умолчанию каждый экземпляр класса в Python содержит __dict__ — словарь для хранения атрибутов. Это удобно, но дорого: словарь занимает ~56 байт плюс сами атрибуты. Для 1 млн объектов разница может составлять сотни мегабайт. __slots__ отключает __dict__ и заменяет его на дескрипторы. Объект становится компактнее (как C-структура). class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) p.z = 3 # ❌ AttributeError: 'Point' object has no attribute 'z' Замер памяти: import sys class WithoutSlots: def __init__(self, x, y): self.x = x self.y = y class WithSlots: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y obj1 = WithoutSlots(1, 2) obj2 = WithSlots(1, 2) print(sys.getsizeof(obj1)) # ~56 байт + __dict__ (~56) = 112 байт print(sys.getsizeof(obj2)) # 48 байт Когда использовать `__slots__`: 🟢 Миллионы объектов с фиксированным набором атрибутов. 🟢 Классы-структуры (Data Transfer Objects, точки, векторы). ❌ Для 99% проектов — не нужно. Оптимизируйте только по факту. Наследование: class Base: __slots__ = ('id',) class Child(Base): __slots__ = ('name', 'age') # id + name + age def __init__(self, id, name, age): self.id = id self.name = name self.age = age Нюанс: __slots__ не наследуется автоматически. Если дочерний класс не переопределяет __slots__, он получит __dict__ и потеряет экономию. 🔗 2. `weakref` — ссылки, которые не мешают сборщику мусора Вы когда-нибудь создавали кэш, который должен хранить объекты, но не мешать им удаляться? Или писали Observer, но объекты не удалялись, потому что их держал список наблюдателей? Это классическая проблема: сильные ссылки держат объекты живыми. weakref — это слабая ссылка, которая не учитывается сборщиком мусора. Если на объект есть только слабые ссылки, он может быть удалён. import weakref import gc class HeavyObject: def __del__(self): print("Объект удалён") obj = HeavyObject() weak = weakref.ref(obj) print(weak()) # <__main__.HeavyObject object at 0x...> del obj gc.collect() print(weak()) # None Где пригодится: 🟢 Кэши — объекты могут быть удалены, если память нужна. 🟢 Наблюдатели (Observer) — слушатели удаляются, когда на них больше никто не ссылается. 🟢 Обратные ссылки в деревьях — родитель держит сильную ссылку на детей, а дети — слабую на родителей. Типы слабых ссылок: 🔴 weakref.ref(obj) — базовая слабая ссылка. 🔴 weakref.WeakKeyDictionary — словарь, где ключи — слабые ссылки. 🔴 weakref.WeakValueDictionary — словарь, где значения — слабые ссылки. 🔴 weakref.WeakSet — множество слабых ссылок. Пример с WeakValueDictionary: import weakref class Cache: def __init__(self): self._data = weakref.WeakValueDictionary() def set(self, key, value): self._data[key] = value def get(self, key): return self._data.get(key) cache = Cache() obj = HeavyObject() cache.set('key', obj) print(cache.get('key')) # <HeavyObject object at ...> del obj print(cache.get('key')) # None Ограничения: 🔴 Не все объекты поддерживают слабые ссылки (числа, строки, кортежи без изменяемых элементов). 🔴 При использовании __slots__ нужно добавить '__weakref__' в слоты. 🔴 Проверяйте результат вызова слабой ссылки на None — объект мог быть удалён. 🧹 3. `gc` — ручное управление циклическим сборщиком мусора В Python есть автоматический сборщик мусора для циклических ссылок. Обычно он работает незаметно, но иногда нужно вмешаться. import gc # Включить/выключить сборку gc.enable() gc.disable() # Запустить вручную gc.collect() # Проверить пороги срабатывания print(gc.get_threshold()) # (700, 10, 10) # Посмотреть количество объектов в поколениях print(gc.get_count()) Когда может понадобиться: 🟢 Вы знаете, что создаётся много циклических ссылок (например, графы, деревья с обратными ссылками). 🟢 В долгоживущих процессах — периодический вызов gc.collect() может помочь. 🟢 В тестах — чтобы проверить, что объекты действительно удаляются. Пример с циклической ссылкой: class Node: def __init__(self): self.parent = None a = Node() b = Node() a.parent = b b.parent = a del a, b # Объекты зависли в циклической ссылке gc.collect() # Удалит их Модуль `gc` для отладки утечек: import gc import tracemalloc # Включить трассировку tracemalloc.start() # Получить список всех объектов objects = gc.get_objects() # Найти объекты определённого типа import pprint pprint.pprint([obj for obj in gc.get_objects() if isinstance(obj, dict)]) ⚠️ Ловушки и частые ошибки 1. Использовать `__slots__` везде — не нужно, усложняет код. 2. Забыть про `__weakref__` в `__slots__` — слабые ссылки не будут работать. 3. Проверять слабые ссылки без `if` — при доступе к удалённому объекту вернётся None. 4. Отключать `gc` без необходимости — приведёт к утечкам. 5. Игнорировать циклические ссылки — в сложных структурах они могут накапливаться. 💡 Запомни: 🟢 __slots__ — экономия памяти для миллионов объектов. 🟢 weakref — ссылки, которые не мешают удалять объекты. 🟢 gc — ручное управление циклическим сборщиком мусора. 🟢 Не оптимизируйте память без измерений. 🟢 Используйте tracemalloc и gc.get_objects() для отладки утечек. Программистика || #Статья
1 002