tg-me.com/pyproglib/6553
Last Update:
🏗 Управление памятью в Python: как это работает
Python сам выделяет и очищает память, чтобы вы не думали о байтах и указателях. Но иногда автоматике стоит помочь.
1. Python управляет памятью автоматически
Когда вы пишете x = [1, 2, 3]
, Python не заставляет вас думать о байтах и указателях. Он сам выделяет память, отслеживает объекты и убирает мусор. Всё это делает менеджер памяти, который хранит:
▪️ Тип данных (int, list, dict)
▪️ Счетчик ссылок (кто использует объект)
▪️ Значение (сами данные)
Такой подход удобен: нет «висячих указателей», не нужно вручную вызывать malloc/free
, а ресурсы оптимизируются автоматически.
2. Счетчик ссылок
Каждый объект в Python — как воздушный шарик. Пока его кто-то держит (есть ссылки), он остается. Если все нити отпущены — объект исчезает.
Как это работает:
import sys
a = [1, 2, 3]
print(sys.getrefcount(a)) # 2 (одна ссылка в переменной + вызов функции)
b = a
print(sys.getrefcount(a)) # 3 (еще одна ссылка)
del a
print(sys.getrefcount(b)) # 2 (одна ссылка удалена)
b = None # Объект больше не используется → удален
💡Но есть нюансы: Python кэширует строки и мелкие числа (-5 до 256), поэтому их ссылки могут не изменяться.
3. Сборщик мусора
Если объекты ссылаются друг на друга, счетчик ссылок их не удалит. Например:
class Node:
def __init__(self):
self.parent = None
a = Node()
b = Node()
a.parent = b
b.parent = a # Циклическая ссылка!
Такие объекты удаляет сборщик мусора (Garbage Collector, GC), используя алгоритм поколений:
🍼 Поколение 0 — новые объекты, проверяются чаще.
🧑💼 Поколение 1 — пережили одну проверку.
🦖 Поколение 2 — «старожилы», проверяются реже.
Управление GC:
import gc
gc.collect() # Принудительный запуск
gc.set_threshold(700, 10, 10) # Настройка частоты очистки
💡 Совет: если у вас много циклических объектов, очищайте их вручную (gc.collect()).
4. Как оптимизировать память вручную
🔸 slots для уменьшения потребления памяти:
class User:
slots = ['name', 'age'] # Экономит до 40% памяти
def __init__(self, name, age):
self.name = name
self.age = age
🔸 Генераторы вместо списков:
# Неоптимально:
lines = open("data.txt").readlines() #Весь файл в памяти!
# Оптимально:
def read_lines(filename):
with open(filename) as f:
for line in f:
yield line # Читаем по одной строке
🔸 Массивы вместо списков:
import array
numbers = array.array('i', [1, 2, 3, 4, 5]) # Числовой массив (экономия памяти)
🔸 Кэширование с lru_cache:
from functools import lru_cache
@lru_cache(maxsize=1000)
def compute(x):
return x 2 # Кэширует результаты функции
5. Как искать утечки памяти
🔸 Используем tracemalloc — показывает, где «утекает» память:
import tracemalloc
tracemalloc.start()
data = [x for x in range(10_000)] # Проблемный код
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print(top_stats[0]) # Где выделена память?
🔸 Визуализация с objgraph — рисует граф зависимостей:
import objgraph
objgraph.show_most_common_types(limit=5) # Какие объекты «размножаются»?
📌 Подробнее про управление памятью в Python: https://clc.to/SNaUtg
Библиотека питониста #буст
BY Библиотека питониста | Python, Django, Flask

Share with your friend now:
tg-me.com/pyproglib/6553