Я озадачен этим поведением выделения памяти set
с:Почему объединение потребляет больше памяти, если аргумент является набором?
>>> set(range(1000)).__sizeof__()
32968
>>> set(range(1000)).union(range(1000)).__sizeof__() # expected, set doesn't change
32968
>>> set(range(1000)).union(list(range(1000))).__sizeof__() #expected, set doesn't change
32968
>>> set(range(1000)).union(set(range(1000))).__sizeof__() # not expected
65736
Почему используя set
в качестве аргумента двойников объем памяти, используемый в результате set
? Результат в обоих случаях идентична оригинальной set
:
>>> set(range(1000)) == set(range(1000)).union(range(1000)) == set(range(1000)).union(set(range(1000)))
True
Обратите внимание, что то же самое происходит с помощью обычного итератора:
>>> set(range(1000)).union(iter(list(range(1000)))).__sizeof__()
32968
И с помощью метода update
:
>>> a.update(range(1000))
>>> a.__sizeof__()
32968
>>> a.update(set(range(1000)))
>>> a.__sizeof__()
65736
Сначала я подумал, что это происходит потому, что когда вызывается union
, он видит, что размер другого set
- 1000
и, таким образом, решает выделить достаточное количество памяти для всех элементов как set
s, а затем использует только часть этой памяти, в то время как в итерационном случае это просто итераторы над ней и добавляет элементы по одному (что doesn 't потребляет больше памяти, поскольку все элементы уже находятся в set
).
Но range
также является последовательностью, а также list
в первом примере.
>>> len(range(1000))
1000
>>> range(1000)[100]
100
Так почему это не происходит с range
и list
, но только с set
? Есть ли какое-либо дизайнерское решение за этим или это ошибка?
Протестировано на python 2.7.3 и python 3.2.3 на Linux 64 бит.
В встроенных наборах Python 2.7 [реализовано на C] (http://hg.python.org/cpython/file/0e41c4466d58/Objects/setobject.c), поэтому ваш анализ проверяет неправильные файлы. – user4815162342
@ user4815162342: Отличная точка, спасибо. Я переписал ответ, чтобы отразить это. – NPE
отличное редактирование, +1. – user4815162342