Python: Czy listy Pythona przechowują liczbę dla len (), czy też liczy się dla każdego wywołania?

79

Jeśli ciągle wywołuję len () z bardzo długiej listy, czy marnuję czas, czy też utrzymuje licznik int w tle?

PKKid
źródło
To zawsze mi przeszkadzało. zwłaszcza gdy mój profiler powiedział mi, że spędziłem 2,2 sekundy programu, który działał przez minutę, wywołując tę ​​funkcję.
Nathan,

Odpowiedzi:

87

Nie martw się: oczywiście oszczędza liczbę, a zatem len()na listach jest to dość tania operacja. Nawiasem mówiąc, to samo dotyczy ciągów znaków, słowników i zestawów!

Ferdinand Beyer
źródło
Wydaje mi się, że utrzymuje liczbę, taką jak indeks ostatniej pozycji + 1 lub coś w tym stylu, i wywołuje wartość len () z tego miejsca w pamięci. Czy mam rację?
geekidharsh
13

Napisz swój program tak, aby był zoptymalizowany pod kątem przejrzystości i łatwy w utrzymaniu . Czy Twój program jest bardziej przejrzysty dzięki wezwaniu do len(foo)? Więc zrób to.

Martwisz się o czas? Skorzystaj z timeitmodułu w bibliotece standardowej, aby zmierzyć wymagany czas i sprawdzić, czy jest on istotny w Twoim kodzie.

Podobnie jak większość ludzi, najprawdopodobniej błędnie zgadniesz, które części programu są najwolniejsze. Unikaj pokusy zgadywania i zamiast tego zmierz ją, aby się dowiedzieć.

Pamiętaj, że przedwczesna optymalizacja jest źródłem wszelkiego zła , jak mówi Donald Knuth. Skoncentruj się tylko na szybkości kodu, którą zmierzyłeś , aby wiedzieć, czy korzyść byłaby warta kosztu zmiany sposobu działania.

duży nos
źródło
1
Jestem programistą zaledwie kilka miesięcy po mojej pracy i popieram obie praktyki. Stoper oferuje dwuliniową obronę przed dużą liczbą konwencjonalnych mądrości („WYBIERZ .. LOSOWO jest zbyt kosztowna”), która zostanie rzucona w Twoją stronę.
Jesvin Jose
5

Na pytanie udzielono odpowiedzi ( lenjest O (1)), ale oto jak możesz to sprawdzić samodzielnie:

$ python -m timeit -s "l = range(10)" "len(l)"
10000000 loops, best of 3: 0.119 usec per loop
$ python -m timeit -s "l = range(1000000)" "len(l)"
10000000 loops, best of 3: 0.131 usec per loop

Tak, niezbyt wolniej.

dF.
źródło
3

„Lista” w Pythonie jest w rzeczywistości tablicą o zmiennym rozmiarze, a nie listą połączoną, więc gdzieś przechowuje rozmiar.

Rozpoznać
źródło
0

Musi gdzieś przechowywać długość, więc nie liczysz za każdym razem liczby elementów.

Georg Schölly
źródło
4
Ostrzegamy, że niekoniecznie jest to prawdą w każdym języku. Niektóre języki używają listy połączonej i mogą, ale nie muszą, przechowywać metadane dotyczące rozmiaru. Doskonałym przykładem jest Lisp, w którym listy używają stosunkowo prymitywnych struktur 2-komórkowych do budowania się, bez metadanych. W takich przypadkach połączenie o długości zajmuje O (n) czasu.
Ashton K