#python #python-3.x #list
#python #python-3.x #Список
Вопрос:
Я хочу напечатать каждое число и индекс:
nums = [3,2,1,5,6,4]
#1st code:
for i in range(len(nums)):
print(i,nums[i])
#2nd code:
length = len(nums)
for i in range(length):
print(i,nums[i])
Какой из этих двух кодов эффективен или они одинаковы?
Ответ №1:
Лучший способ сделать это с помощью enumerate
функции:
nums = [3, 2, 1, 5, 6, 4]
for index, number in enumerate(nums):
print(index, number)
Ответ №2:
Оба примера приведут к одному и тому же байт-коду, за исключением того факта, что второй вариант также сохраняет длину в отдельной переменной. Таким образом, оба они фактически идентичны, и использование одного над другим не окажет заметного влияния.
Причина этого, кстати. что цель итерации, т.Е. range(len(nums))
or range(length)
, выполняется только один раз в начале вашего цикла. Таким образом, этот код никогда не выполняется более одного раза, поэтому не имеет значения, выполняете ли вы этот код вне синтаксиса цикла for или внутри.
Ответ №3:
Согласно ссылке на язык CPython, он вычисляется только один раз (курсив мой):
Оператор for используется для перебора элементов последовательности (например, строки, кортежа или списка) или другого итеративного объекта:
for_stmt ::= «для» target_list «в» expression_list «:» suite [«else» «:» suite]
Список выражений вычисляется один раз; он должен выдавать итеративный объект. Для результата expression_list создается итератор.
Ответ №4:
Вы можете собрать и сравнить себя:
nums = [3,2,1,5,6,4]
# 1st code:
def f1():
for i in range(len(nums)):
pass # print(i,nums[i])
#2nd code:
def f2():
length = len(nums)
for i in range(length):
pass # print(i,nums[i])
import dis
dis.dis(f1)
dis.dis(f1)
И смотрите:
# f1 -----
5 0 LOAD_GLOBAL 0 (range)
2 LOAD_GLOBAL 1 (len)
4 LOAD_GLOBAL 2 (nums)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 GET_ITER
>> 12 FOR_ITER 2 (to 18)
14 STORE_FAST 0 (i)
6 16 JUMP_ABSOLUTE 6 (to 12)
против
# f2 -----
5 >> 18 LOAD_CONST 0 (None) # storing len
20 RETURN_VALUE # in variable
5 0 LOAD_GLOBAL 0 (range)
2 LOAD_GLOBAL 1 (len)
4 LOAD_GLOBAL 2 (nums)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 GET_ITER
>> 12 FOR_ITER 2 (to 18)
14 STORE_FAST 0 (i)
6 16 JUMP_ABSOLUTE 6 (to 12)
5 >> 18 LOAD_CONST 0 (None)
20 RETURN_VALUE
Идентично (отличается только сохранение len в переменной). Я прокомментировал печать для простоты демонстрации — она одинакова в обоих. Так f2
что сохраняет len в const в дополнение к тому, что f1
делает — так что никакого заметного влияния во времени — и не пересматривает len(nums)
несколько раз.