1
0
mirror of https://github.com/satwikkansal/wtfpython synced 2024-06-17 01:59:51 +02:00

Translate Bloating instance dict's example

This commit is contained in:
Vadim Nifadev 2024-04-24 16:28:57 +03:00
parent 4b4951d755
commit 9e2508ae6a

View File

@ -3566,3 +3566,67 @@ KeyError: 1
+ Этот процесс не обратим для конкретного экземпляра `dict`, и ключ даже не обязательно должен существовать в словаре. Поэтому попытка неудачного поиска имеет тот же эффект.
---
### ▶ Раздуваем экземпляры словарей *
<!-- Example ID: fe706ab4-1615-c0ba-a078-76c98cbe3f48 --->
```py
import sys
class SomeClass:
def __init__(self):
self.some_attr1 = 1
self.some_attr2 = 2
self.some_attr3 = 3
self.some_attr4 = 4
def dict_size(o):
return sys.getsizeof(o.__dict__)
```
**Результат:** (Python 3.8, другие версии Python 3 могут немного отличаться)
```py
>>> o1 = SomeClass()
>>> o2 = SomeClass()
>>> dict_size(o1)
104
>>> dict_size(o2)
104
>>> del o1.some_attr1
>>> o3 = SomeClass()
>>> dict_size(o3)
232
>>> dict_size(o1)
232
```
Попробуем снова... В новом сессии интерпретатора:
```py
>>> o1 = SomeClass()
>>> o2 = SomeClass()
>>> dict_size(o1)
104 # как ожидается
>>> o1.some_attr5 = 5
>>> o1.some_attr6 = 6
>>> dict_size(o1)
360
>>> dict_size(o2)
272
>>> o3 = SomeClass()
>>> dict_size(o3)
232
```
Что заставляет эти словари раздуваться? И почему только созданные объекты также раздуваются?
#### 💡 Объяснение:
+ CPython может повторно использовать один и тот же объект "keys" в нескольких словарях. Это было добавлено в [PEP 412](https://www.python.org/dev/peps/pep-0412/) с целью сокращения использования памяти, особенно в экземплярах словарей - где ключи (атрибуты экземпляра), как правило, общие для всех экземпляров.
+ Эта оптимизация совершенно беспроблемна для экземпляров словарей, но она не работает, если нарушены некоторые условия.
+ Словари с общим доступом к ключам не поддерживают удаление; если атрибут экземпляра удаляется, словарь становится "не общим", и общий доступ к ключам отключается для всех последующих экземпляров того же класса.
+ Кроме того, если размер ключей словаря был изменен (из-за вставки новых ключей), они остаются общими *только* если они используются только одним словарем (это позволяет добавить много атрибутов в `__init__` самого первого созданного экземпляра, не вызывая "unshare"). Если на момент изменения размера существует несколько экземпляров, совместное использование ключей отключается для всех последующих экземпляров одного класса: CPython не может определить, используют ли ваши экземпляры один и тот же набор атрибутов, и решает отказаться от попытки поделиться ключами.
+ Небольшой совет, если вы стремитесь уменьшить занимаемый программой объем памяти: не удаляйте атрибуты экземпляров и обязательно инициализируйте все атрибуты в `__init__`!
---