Ответ 1
Нет, PEP 412 не делает __slots__
избыточным.
Во-первых, Армин Риго прав, что вы не правильно его измеряете. Для измерения нужно указать размер объекта плюс значения, а также __dict__
(только для NoSlots
) и ключи (только для NoSlots
).
Или вы можете делать то, что он предлагает:
cls = Slots if len(sys.argv) > 1 else NoSlots
def f():
tracemalloc.start()
objs = [cls() for _ in range(100000)]
print(tracemalloc.get_traced_memory())
f()
Когда я запускаю это на 64-разрядном CPython 3.4 в OS X, я получаю 8824968
для NoSlots
и 25624872
для Slots
. Итак, похоже, что экземпляр NoSlots
занимает 88 байт, а экземпляр Slots
занимает 256 байт.
Как это возможно?
Поскольку между __slots__
и разделом клавиш __dict__
существуют еще две отличия.
Сначала хеш-таблицы, используемые словарями, поддерживаются ниже 2/3rds, и они растут экспоненциально и имеют минимальный размер, поэтому у вас будет дополнительное пространство. И не сложно определить, сколько места, глядя на красиво прокомментированный источник : у вас будет 8 хэш-кодов вместо 5 слотов.
Во-вторых, сам словарь не является бесплатным; он имеет стандартный заголовок объекта, счетчик и два указателя. Это может показаться не очень большим, но когда вы говорите об объекте, который получил только несколько атрибутов (обратите внимание, что большинство объектов имеют только несколько атрибутов...), заголовок dict может иметь такое же значение, как и хеш-таблица.
И, конечно же, в вашем примере значения, поэтому единственная стоимость здесь - это сам объект, плюс 5 слотов или 8 хэш-кодов и заголовок dict, поэтому разница довольно драматична. В реальной жизни __slots__
редко будет такой значительной выгодой.
Наконец, обратите внимание, что PEP 412 только утверждает:
Бенчмаркинг показывает, что использование памяти сокращается на 10% до 20% для объектно-ориентированных программ
Подумайте, где вы используете __slots__
. Либо сбережения настолько огромны, что не использовать __slots__
было бы смешно, или вам действительно нужно выжать последние 15%. Или вы строите ABC или другой класс, который, как вы ожидаете, будет подклассифицирован кем-то, что и подклассы, возможно, потребуют экономии. Во всяком случае, в тех случаях тот факт, что вы получаете половину пособия без __slots__
, или даже две трети выгоды, по-прежнему редко будет достаточным; вам все равно придется использовать __slots__
.
Настоящая победа в тех случаях, когда не стоит использовать __slots__
; вы получите небольшое пособие бесплатно.
(Кроме того, есть определенные программисты, которые чрезмерно используют ад из __slots__
, и, может быть, это изменение может убедить некоторых из них включить свою энергию в микро-оптимизацию чего-то еще не столь неулокального, если вам повезет. )