Jestem zdziwiony tym zachowaniem alokacji pamięci set
S:Dlaczego związek zużywa więcej pamięci, jeśli argument jest zbiorem?
>>> 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
Dlaczego przy użyciu set
jako argument podwaja ilość pamięci używanej przez powstałą set
? Wynik w obu przypadkach jest identyczny z oryginalnym set
:
>>> set(range(1000)) == set(range(1000)).union(range(1000)) == set(range(1000)).union(set(range(1000)))
True
Należy zauważyć, że to samo dzieje się przy użyciu normalnego iterator:
>>> set(range(1000)).union(iter(list(range(1000)))).__sizeof__()
32968
iz metody update
:
>>> a.update(range(1000))
>>> a.__sizeof__()
32968
>>> a.update(set(range(1000)))
>>> a.__sizeof__()
65736
Początkowo myślałem, że to dlatego, że kiedy jest wywoływana union
, widzi, że rozmiar innego set
to 1000
iw ten sposób decyduje się na przydzielenie wystarczającej ilości pamięci, aby zmieścić wszystkie elementy obu set
s, ale potem wykorzystuje tylko część tej pamięci, podczas gdy w przypadku iteratora po prostu iteruje nad nią i dodaje elementy jeden po drugim (co robi Zużywa więcej pamięci, ponieważ wszystkie elementy są już w wersji set
).
Ale range
jest również sekwencją, podobnie jak list
w pierwszym przykładzie.
>>> len(range(1000))
1000
>>> range(1000)[100]
100
Więc dlaczego tak się nie dzieje z range
i list
ale tylko z set
? Czy istnieje jakaś decyzja dotycząca projektu lub czy jest to błąd?
Testowany na pythonie 2.7.3 i pythonie 3.2.3 na linuksie 64-bitowym.
W Pythonie 2.7 wbudowane zestawy są [zaimplementowane w C] (http://hg.python.org/cpython/file/0e41c4466d58/Objects/setobject.c), więc twoja analiza analizuje złe pliki. – user4815162342
@ user4815162342: Świetny punkt, dzięki. Przepisałem odpowiedź, aby to odzwierciedlić. – NPE
świetna edycja, +1. – user4815162342