2013-07-10 19 views
7

Po uruchomieniu poniższego kodu otrzymałem 3 i 36 jako odpowiedź.Jaka jest różnica między metodami len() i sys.getsizeof() w pythonie?

x ="abd" 
print len(x) 
print sys.getsizeof(x) 

Może ktoś mi wyjaśnić co jest jest różnica między nimi?

+6

Czy przejrzałeś dokumentację? – moooeeeep

+0

@moooeeeep: Przypuszczalnie OP uważał, że ciągi w Pythonie są podobne do ciągów C; jeden bajt na znak plus ewentualnie bajt zerowy. –

+1

Nie wiem, dlaczego został zamknięty. 2 lata później odpowiedź była dokładnie tym, czego szukałem, a IMO bardzo istotną dla każdego, kto potrzebuje zrozumieć rozmiary stringów. – Realistic

Odpowiedz

34

To nie to samo, co w ogóle.

len() zapytania o liczbę elementów znajdujących się w kontenerze. W przypadku łańcucha będącego liczbą znaków:

Zwraca długość (liczbę elementów) obiektu. Argumentem może być sekwencja (łańcuch, krotka lub lista) lub mapowanie (słownik).

sys.getsizeof() z drugiej strony zwraca rozmiar pamięci obiektu:

Return wielkość obiektu w bajtach. Obiekt może być dowolnym typem obiektu. Wszystkie wbudowane obiekty zwrócą poprawne wyniki, ale nie musi to dotyczyć rozszerzeń stron trzecich, ponieważ jest to specyficzne dla implementacji.

Obiekty w języku Python to nie proste sekwencje znaków, 1 bajt na znak.

Specyficznie, funkcja sys.getsizeof() obejmuje narzutu garbage collector jeżeli:

getsizeof() wzywa __sizeof__ metody obiektu i dodaje dodatkowy narzut garbage collector, gdy obiekt jest zarządzany przez garbage collector.

Obiekty ciągów nie muszą być śledzone (nie mogą tworzyć odwołań kołowych), ale obiekty ciągów muszą mieć więcej pamięci niż tylko bajty na znak. Pythona 2, metoda __sizeof__ powraca w kodzie (C):

Py_ssize_t res; 
res = PyStringObject_SIZE + PyString_GET_SIZE(v) * Py_TYPE(v)->tp_itemsize; 
return PyInt_FromSsize_t(res); 

gdzie PyStringObject_SIZE jest rozmiar nagłówka C struktura dla typu PyString_GET_SIZE w zasadzie jest taki sam jak len() i Py_TYPE(v)->tp_itemsize ma wielkość od znaku. W Pythonie 2.7, w przypadku ciągów bajtów, rozmiar na znak wynosi 1, ale to jest PyStringObject_SIZE, co wprowadza w błąd; na moim Macu, że rozmiar jest 37 bajtów:

>>> sys.getsizeof('') 
37 

Dla unicode strings wielkość per-charakteru podchodzi do 2 lub 4 (w zależności od opcji kompilacji). W wersjach Python 3.3 i nowszych łańcuchy znaków Unicode zajmują od 1 do 4 bajtów na znak, w zależności od zawartości ciągu znaków.

Powiązane problemy