Вартість функції len ()


Відповіді:


341

Це O (1) (постійний час, не залежно від фактичної довжини елемента - дуже швидко) для кожного згаданих вами типів, а також setінших тощо array.array.


17
Дякуємо за корисну відповідь! Чи є рідні типи, для яких це не так?
mvanveen


84

Усі ці об’єкти відстежують власну довжину. Час вилучення довжини невеликий (O (1) в нотації big-O) і здебільшого складається з [грубого опису, написаного термінами Python, а не з термінами C]: шукайте "len" у словнику та відправляйте його до вбудована функція len, яка шукатиме __len__метод об'єкта і викликає, що ... все, що він повинен зробити, - цеreturn self.length


3
Я думаю, що це найбільш відповідна відповідь, оскільки це дає зрозуміти деталі реалізації.
АК

чому не lengthз’являється у словнику від dir(list)?
ViFI

це те, що я шукав
Вісак Віджаян

@ViFI Тому що це лише приклад. Ілюстрована list.lenghtзмінна реалізована в C, а не в Python.
Ковальські

73

Наведені нижче вимірювання забезпечують доказ того, що len()O (1) для часто використовуваних структур даних.

Примітка щодо timeit: Коли використовується -sпрапор і два рядки передаються timeitв перший рядок, виконується лише один раз і не приурочено до часу.

Список:

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

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

Кортеж:

$ python -m timeit -s "t = (1,)*10;" "len(t)"
10000000 loops, best of 3: 0.0712 usec per loop

$ python -m timeit -s "t = (1,)*1000000;" "len(t)"
10000000 loops, best of 3: 0.0699 usec per loop

Рядок:

$ python -m timeit -s "s = '1'*10;" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop

$ python -m timeit -s "s = '1'*1000000;" "len(s)"
10000000 loops, best of 3: 0.0686 usec per loop

Словник (розуміння словника доступно в 2.7+):

$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(10))};" "len(d)"
10000000 loops, best of 3: 0.0711 usec per loop

$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(1000000))};" "len(d)"
10000000 loops, best of 3: 0.0727 usec per loop

Масив:

$ python -mtimeit -s"import array;a=array.array('i',range(10));" "len(a)"
10000000 loops, best of 3: 0.0682 usec per loop

$ python -mtimeit -s"import array;a=array.array('i',range(1000000));" "len(a)"
10000000 loops, best of 3: 0.0753 usec per loop

Набір (розуміння набору доступно в 2.7+):

$ python -mtimeit -s"s = {i for i in range(10)};" "len(s)"
10000000 loops, best of 3: 0.0754 usec per loop

$ python -mtimeit -s"s = {i for i in range(1000000)};" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop

Deque:

$ python -mtimeit -s"from collections import deque;d=deque(range(10));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop

$ python -mtimeit -s"from collections import deque;d=deque(range(1000000));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop

1
Це не так добре, як тест, навіть якщо він показує те, що ми вже знаємо. Це тому, що діапазон (10) і діапазон (1000000) не повинні бути O (1).
Невідомо

3
Це, безумовно, найкраща відповідь. Вам слід просто додати висновок на випадок, якщо хтось не усвідомлює постійний час.
santiagobasulto

4
Дякуємо за коментар Я додав примітку про складність O (1) len(), а також зафіксував вимірювання, щоб правильно використовувати -sпрапор.
механічний_міс

Важливо зауважити, що збереження довжини у змінну може заощадити значну кількість обчислювального часу: python -m timeit -s "l = range(10000);" "len(l); len(l); len(l)"223 нсек за цикл python -m timeit -s "l = range(100);" "len(l)"66,2 нсек за цикл
Радостін Стоянов

16

len - це O (1), оскільки у вашій ОЗУ списки зберігаються у вигляді таблиць (серія суміжних адрес). Щоб знати, коли таблиця зупиняється, комп'ютер потребує двох речей: довжина та початкова точка. Ось чому len () - це O (1), комп'ютер зберігає значення, тому його просто потрібно шукати.


3

Я думав, що len () в Python залежить від розміру списку, тому я завжди зберігаю довжину в змінній, якщо використовую кілька разів. Але сьогодні під час налагодження я помітив атрибут __len__ у об’єкті списку, тому len () повинен бути лише його видобуванням, що робить складність O (1). Тож я просто гуглив, якщо хтось це вже запитав і натрапив на цю посаду.


Але __len__це функція, а не змінна, яка представляє довжину списку.
Ковальський

@Kowalski так len - це функція, але все, що вона робить, повертає self.length
AYUSH SENAPATI

Але ваш пост про це нічого не говорить. Також як ти це знаєшlist.__len__ функція працює в постійний час? Це робить, але не лише тому, що це функція. Тому що він реалізований так.
Ковальські
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.