#python #list
#python #Список
Вопрос:
Я практиковал python ‘list variable’ с ‘for loop’, но был удивлен, увидев, что порядок элементов в списке изменился.
xlist=[1,2,3,4,5]
print(xlist)
#loop all items in the lxist
for item in xlist:
print(item)
#multiply each item by 5
xlist[xlist.index(item)] = item * 5
#print the list
print(xlist)
Я ожидал, что порядок списка будет [5,10,15,20,25]
но вместо этого я получил [25, 10, 15, 20, 5]
Я использую python 3.8 (версия 32) с использованием pycharm IDE.
Кто-нибудь может пояснить, почему изменился порядок списка
Комментарии:
1. Примечание: Переменные Python не имеют типов, у объектов есть типы. Это важно понимать.
2. @juanpa.arrivillaga Мне любопытно, как это работает. Есть ли хорошие ресурсы, которые можно прочитать? Я читал, что все является объектом в python (даже классы). Так не должны ли переменные тоже быть объектами и, следовательно, иметь тип?
3. Нет, переменные на самом деле не являются объектами, хотя где-то в некотором пространстве имен есть объект string, который соответствует имени переменной. Однако в качестве оптимизации локальные пространства имен работают по-другому.
4. Итак, что я конкретно имею в виду, что переменные не имеют типов, так это то, что python — динамический язык . Переменные могут ссылаться на объекты любого типа и будут с радостью ссылаться на list, а затем, если вы повторно назначите int или строку, без проблем:
x = [1,2,3]; x = 42; print(x)
.
Ответ №1:
Вы неправильно используете .index
метод. Две проблемы, семантически, это не означает то, что вы думаете, это означает, это дает вам первый индекс некоторого объекта в списке. Итак, обратите внимание, на вашей последней итерации:
xlist.index(5) == 0
Поскольку на вашей первой итерации вы устанавливаете:
xlist[0] = 1 * 5
Правильный способ сделать это — поддерживать и индексировать по мере выполнения итерации, либо вручную, используя что-то вроде index = 0
вне цикла и увеличивая его, либо выполняя итерацию по диапазону и извлекая элемент, используя этот индекс. Но pythonic способ сделать это — использовать enumerate
, который автоматически предоставляет счетчик при выполнении цикла:
for index, item in enumerate(xlist):
xlist[index] = item*5
Другая проблема заключается в том, что даже если все ваши элементы были уникальными и возвращенный индекс был правильным, использование .index
в цикле излишне увеличивает квадратичное время вашего алгоритма, поскольку .index
требуется линейное время.
Комментарии:
1. Я могу понять, что OP, вероятно, пытается изучить различные методы как новичок, но я не уверен, какую роль
index
должен играть «pythonic way» для достижения результата; Я думал, что это будет понимание списка. 🙂2. @navneethc нет, for-циклы идеально подходят для python. В цикле for нет ничего плохого, если это выполняется идиоматически . Обратите внимание, что понимание списка создает новый список, и вам может потребоваться, чтобы список был изменен на месте, что и делается выше. Чтобы использовать понимание списка, вы могли бы сделать
xlist[:] = [5*item for item in xlist]
, но это все равно создает новый список, требующий линейного пространства, когда это можно сделать тривиально в постоянном пространстве. Конечно, многие сочли бы изменение менее идеальным … но это другая тема3. Я никогда ничего не говорил о for-циклах, я специально спрашивал о явном использовании индекса.
4. @navneethc прочитал мою правку, я подробно объяснил, почему в данном конкретном случае я бы не стал использовать понимание списка. Конечно, если вы в порядке, создавая другой список, тогда ОК, но я просто принимаю вопрос за чистую монету
5. @juanpa.arrivillaga, я думаю, ты не вводил
enumerate(xlist)
, когда иллюстрировал это..
Ответ №2:
index
Метод возвращает индекс первого вхождения элемента, который вы передали в качестве аргумента (при условии, что он существует). Итак, к тому времени, когда вы достигнете последнего элемента, т. е. 5 с индексом 4, элемент с индексом 0 также равен 5, так что в конечном результате вы получите 5 * 5 с индексом 0.
Ответ №3:
Когда index
метод выполняет поиск 5-го числа ( 5
), он находит первый индекс, который имеет это значение. На данный момент индекс 0 (1-е число) также равен 5
, поэтому он умножает индекс 0 на 5. Лучший способ выполнить цикл — использовать enumerate
метод для перебора каждого индекса и изменения номера по этому индексу, вместо того, чтобы впоследствии находить индекс. Это устраняет проблемы с index
методом.
xlist=[1,2,3,4,5]
print(xlist)
#loop all items in the lxist
for i, item in enumerate(xlist):
print(item)
#multiply each item by 5
xlist[i] *= 5
#print the list
print(xlist)
Результаты:
[1, 2, 3, 4, 5]
1
[5, 2, 3, 4, 5]
2
[5, 10, 3, 4, 5]
3
[5, 10, 15, 4, 5]
4
[5, 10, 15, 20, 5]
5
[5, 10, 15, 20, 25]
Комментарии:
1. Ваш ответ прекрасен, но в Python это не обычный шаблон для написания только потому, что просмотр элементов с помощью простого
for
или использованиеenumerate
более краткого.2. Я не знал о
enumerate
. Это действительно хороший способ сделать это, спасибо. Я обновил свой ответ, чтобы использовать это вместоrange
.3. @TheOtterlord Спасибо за ваше подробное объяснение.