Python: Чи ведуть списки Python підрахунок для len () або він враховує кожен виклик?


79

Якщо я продовжую дзвонити len () у дуже довгий список, я марно витрачаю час, чи це робить підрахунок int у фоновому режимі?


Мене це завжди хвилювало. особливо коли мій профіліст сказав мені, що я витратив 2,2 секунди програми, яка працювала протягом однієї хвилини, викликаючи цю функцію.
Натан,

Відповіді:


87

Не хвилюйтеся: звичайно, це економить підрахунок, і, отже, len()для списків це досить дешева операція. До речі, те саме стосується рядків, словників та наборів!


Я вважаю, що він зберігає рахунок, як індекс останнього елемента + 1 або щось інше, і викликає значення len () з цього місця пам'яті. Я правий?
geekidharsh



13

Напишіть свою програму так, щоб вона була оптимізована для ясності та легко підтримувалась . Ваша програма зрозуміліша із закликом до len(foo)? Тоді зробіть це.

Вас турбує витрачений час? Використовуйте timeitмодуль у стандартній бібліотеці, щоб виміряти час, який потрібно, і перевірити, чи він важливий у вашому коді.

Ви, як і більшість людей, з великою ймовірністю помилятиметеся, які частини вашої програми є найповільнішими. Уникайте спокуси вгадати, а замість цього виміряйте це, щоб з’ясувати.

Пам’ятайте, що передчасна оптимізація - це корінь усього зла , за висловом Дональда Кнута. Зосередьтеся лише на швидкості коду, для якого ви виміряли швидкість, щоб знати, чи варта б вигода витрат на зміну того, як це працює.


1
Я програміст за кілька місяців роботи і схвалюю обидві практики. Матеріали таймера пропонують дворядковий захист від великої маси загальноприйнятої думки ("ВИБІР .. СТАНДАРТНЕ занадто дорого"), яку вам кинуть.
Jesvin Jose

5

На запитання відповіли ( lenце O (1)), але ось як ви можете перевірити самі:

$ 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

Так, не дуже повільніше.


3

"Список" Python - це справді масив, який можна змінити, а не пов'язаний список, тому він десь зберігає розмір.


0

Він повинен десь зберігати довжину, тому ви не будете рахувати кількість предметів кожного разу.


4
Зауважте, це не обов’язково відповідає дійсності кожної мови. Деякі мови насправді використовують зв’язаний список і можуть зберігати метадані приблизно, приблизно, приблизно. Ідеальним прикладом є Lisp, де списки використовують відносно примітивні 2-клітинні структури для побудови себе, без метаданих. У цих випадках тривалість дзвінка займає час O (n).
Ashton K,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.