Хирьянов Т.Ф. - Основы программирования и анализа данных на Python - 12. Реляционные базы данных
Что происходит, когда мы создаём переменную в Python?
Как это происходит и как работает
Управление памятью в Python [Часть 1.2] Предыдущая часть Следующая часть Оптимизации Python для экономии памяти Python использует несколько интересных оптимизаций: 1. Integer caching: небольшие целые числа (обычно от -5 до 256) кэшируются: a = 42 b = 42 print(a is b) # True - это один и тот же объект! x = 257 y = 257 print(x is y) # False - разные объекты 1. String interning: Python автоматически интернирует (переиспользует) некоторые строки. Это происходит во время компиляции для идентификаторов: имен переменных, функций, классов. Интернируются строки, которые соответствуют правилам именования идентификаторов (начинаются с подчеркивания или буквы и содержат только подчеркивания, буквы и цифры): # Строки, соответствующие правилам идентификаторов s1 = 'hello' s2 = 'hello' print(s1 is s2) # True - строки интернированы # Строки, не соответствующие правилам идентификаторов s3 = 'hello world' # содержит пробел s4 = 'hello world' print(s3 is s4) # False - строки не интернированы # Можно принудительно интернировать любые строки import sys s5 = sys.intern('hello world') s6 = sys.intern('hello world') print(s5 is s6) # True - строки интернированы вручную Ручное интернирование через sys.intern() полезно, когда в вашем коде часто встречаются одинаковые строки, не соответствующие правилам идентификаторов. Это позволяет экономить память за счет переиспользования одного и того же объекта строки. Сборщик мусора в Python Python использует две основные стратегии для очистки памяти: 1. Reference counting (подсчёт ссылок) 2. Generational garbage collection (поколенческий сборщик мусора) Reference Counting Каждый объект в Python имеет счётчик ссылок. Когда создаётся новая ссылка на объект, счётчик увеличивается. Когда ссылка удаляется - уменьшается: import sys # Создаём список x = [1, 2, 3] print(sys.getrefcount(x) - 1) # 1 ссылка (минус 1, так как getrefcount создаёт временную ссылку) # Создаём ещё одну ссылку y = x print(sys.getrefcount(x) - 1) # 2 ссылки # Удаляем одну ссылку del y print(sys.getrefcount(x) - 1) # Снова 1 ссылка Когда счётчик достигает нуля, объект немедленно удаляется из памяти. Проблема циклических ссылок Reference counting отлично работает в большинстве случаев, но у него есть одна серьёзная проблема - он не может обработать циклические ссылки. Рассмотрим простой пример: class Node: def __init__(self, name): self.name = name self.ref = None def __repr__(self): return f"Node({self.name})" # Создаём два объекта node1 = Node("First") node2 = Node("Second") # Создаём цикл: node1 ссылается на node2, а node2 на node1 node1.ref = node2 node2.ref = node1 # Смотрим на ссылки print(f"node1 указывает на: {node1.ref}")# node2 print(f"node2 указывает на: {node2.ref}")# node1# Удаляем переменные del node1 del node2 # В этот момент оба объекта Node имеют счётчик ссылок = 1# (они ссылаются друг на друга), но до них больше нельзя# добраться из кода! Это утечка памяти. Именно для решения таких ситуаций в Python существует второй механизм сборки мусора - поколенческий сборщик мусора (generational garbage collector). Как работает поколенческий сборщик мусора Этот сборщик работает по следующим принципам: 1. Все объекты в Python распределяются по трём поколениям: - Поколение 0: новые объекты - Поколение 1: объекты, пережившие одну сборку мусора - Поколение 2: старые объекты, пережившие несколько сборок 2. Сборщик периодически просматривает объекты и ищет недостижимые циклы ссылок Давайте посмотрим на это в действии: import gc # Смотрим статистику по поколениям# Формат: (количество объектов в поколении 0, в поколении 1, в поколении 2) print("Статистика по поколениям:", gc.get_count()) # Создаём цикл как в примере выше node1 = Node("First") node2 = Node("Second") node1.ref = node2 node2.ref = node1 # Удаляем внешние ссылки del node1 del node2 # Запускаем сборщик мусора принудительно collected = gc.collect() print(f"Собрано {collected} объектов")# Увидим, что объекты были собраны В следующей части продолжим разбирать GC Поддержать на Boosty Посмотреть на Youtube