Память
Как работает
-
Все работает на ссылках на память:
Счетчик Ссылок
- Нет ссылок - чистим память
- Не ищет циклические ссылки
Garbage Collector
- Ищет циклические ссылки
- Циклические ссылки:
list_ = [1,]; list_.append(list_)
- Помещает циклические ссылки + объекты, которые давно не чистились, в генерации / поколения
- 3 генерации
- Нужно для экономии ресурсов
- Различаются по длительности жизни (кол-во проверок на наличие ссылок)
Intering
[-5, 256]
- одна и та же область памяти:a1 = 1; a2 = 1; a1 is a2
- Аналогично: Строки (латиница + _ + цифры), пустые кортежи
sys.intern
- функ для ссылки на один и тот же объект
API
id
- айди объекта в памятиsys.getrefcount
- кол-во ссылок + 1gc.get_refferers(obj)
- список кто ссылается на объект- Глобальные объекты будут всегда в
globals
- Глобальные объекты будут всегда в
__del__
- вызывается когда объект будет удален из памяти
WeakRef
- Слабые ссылки = кол-во ссылок на объект не увеличивается:
- Объект Удаляется если все ссылки слабые
Юзкейсы
GC цикл. ссылок
c = Cls()
c.c = c
c = None
## No Cls.__del__ called
gc.collect()
## Cls.__del__ called
c.c = weakref.proxy(c)
c = None
## Cls.__del__ called
List of weak-refs / Observer Pattern
list_ = []
for i in range(3):
list_.append(weakref.ref(Cls(i)))
## Cls.__del__ called 3 times
c1 = Cls()
c2 = Cls()
list_ = []
list_.append(weakref.ref(c1))
list_.append(weakref.ref(c2))
del c1
## list_ == [None, c2]
Кеш: WeakKeyDictionary
, WeakValueDictionary
, WeakSet
dict_ = WeakKeyDictionary()
c = Cls()
dict_[c] = 2
c = None
## Cls.__del__ called
## dict_ is empty!