Программистика
Canal cerrado
Лучший канал про python Ссылка для друга: https://t.me/+Ai6ughKtf5g2ZmFi Купить рекламу: https://telega.in/c/+Ai6ughKtf5g2ZmFi Админ: @JeyRahol По рекламе: @ReivuManager
Mostrar más5 852
Suscriptores
Sin datos24 horas
-77 días
+27930 días
Carga de datos en curso...
Canales Similares
Sin datos
¿Algún problema? Por favor, actualice la página o contacte a nuestro gerente de soporte.
Nube de Etiquetas
Menciones Entrantes y Salientes
---
---
---
---
---
---
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 septiembre | 0 | |||
| 13 septiembre | +14 | |||
| 12 septiembre | +2 | |||
| 11 septiembre | 0 | |||
| 10 septiembre | +1 | |||
| 09 septiembre | +6 | |||
| 08 septiembre | 0 | |||
| 07 septiembre | +2 | |||
| 06 septiembre | +73 | |||
| 05 septiembre | 0 | |||
| 04 septiembre | 0 | |||
| 03 septiembre | 0 | |||
| 02 septiembre | +18 | |||
| 01 septiembre | +2 |
Publicaciones del Canal
⚙️ Библиотека Python: Dynaconf
Dynaconf — это гибкая библиотека для управления настройками приложения. Она поддерживает множество форматов (
.toml, .yaml, .json, .ini, .env), автоматически подхватывает переменные окружения и позволяет легко переключаться между средами (development, production). Вдохновлена принципами 12-factor приложений и избавляет от хаоса с конфигами.
✔️ Установка:
pip install dynaconf
🐱 Ссылка на репозиторий
Программистика|| #Library| 2 | Программистика | 451 |
| 3 | 👩💻 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 сентября
Освойте профессию и ИИ-навыки, которые уже требует рынок. Начните бесплатно до 17 сентября и учитесь со скидкой.
Яндекс Практикум. Учим профессиям и навыкам с ИИ, чтобы вы не застряли в прошлом
Узнать больше
#реклама 16+
practicum.yandex.ru
О рекламодателе | 492 |
| 8 | 👨💻Гайд «Как стать программистом». А нейронки? А рынок вакансий? А можно еще?
Путь в 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, s1 is s3)
Варианты:
1. True True
2. True False
3. False True
4. False False
Пиши свой вариант в комментарии! Ответ и разбор — через пару часов 🔥
Программистика || #quiz | 775 |
| 11 | Весь Python. Самое актуальное и исчерпывающее руководство
Всеобъемлющее современное руководство по программированию на Python, охватывающее фундаментальные идеи и практические приемы!
Вы научитесь писать собственные программы и получите четкое представление о том, куда двигаться дальше и как использовать полученные знания. Изучение Python подкреплено практикой — огромным количеством примеров приложений. К концу книги вы будете готовы применить полученные знания и создать несколько реальных проектов. Вы научитесь эффективно использовать Python в анализе данных, веб-разработке и автоматизации задач.
Книга включает описание новейших возможностей, появившихся в версиях Python 3.9–3.12, в том числе главы об аннотациях типов и консольных приложениях, а также примеры, демонстрирующие современные практики веб-разработки на Python.
Программистика || #Книги | 811 |
| 12 | 3 дня. 60 откликов. 1 оффер.
Очень интересный кейс произошёл у команды Софи — ии-ассистента для поиска работы.
К ним в поддержку написала девушка, которая отписалась от продукта ещё месяц назад:
«Мне прислали оффер!»
Начали разбираться — оказывается, она пользовалась только 3 тестовыми днями.
То есть за 3 дня ии-ассистент успел сделать 60 откликов. Потом она отписалась.
А уже позже — из этих откликов её позвали на интервью, и одно из них привело к офферу.
«Оффер с той вакансии, куда я сама никогда бы не откликнулась»
Изначально Аня отменила подписку, так как было дорого. Ребята честно спросили у Ани, считает ли она теперь, что подписка стоит своих денег — и получили утвердительный ответ.
В следующий раз доступ в Софи откроется 22 сентября.
Если хочешь получить 3 дня бесплатного доступа - подписывайся на этот канал, все анонсы будут там. | 449 |
| 13 | Шпаргалка методы списков в Python
Программистика|| #doc | 928 |
| 14 | Sin texto... | 1 |
| 15 | Weekend Offer ML*: быстрый найм в Яндекс
Открыли регистрацию на онлайн-мероприятие для ML и DL-специалистов. Мы ищем инженеров с опытом от 2 лет в областях NLP, CV, RecSys и Classic ML.
Как всё устроено:
✅ До 4 сентября — регистрация на сайте.
✅ 12 сентября — две технические секции онлайн.
✅ 13 сентября — финальные интервью со знакомством с командами.
Ждём вас! Подробности и форма регистрации — на сайте.
Зарегистрироваться
#реклама 16+
yandex.ru
О рекламодателе | 473 |
| 16 | 🖥 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. [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 |
