Python: список не мутируется после цикла

a =[1,2] for entry in a: entry = entry + 1 print a 

Не следует ли переименовать список в [2,3] ? Результат получился как [1,2] . Зачем?

4 Solutions collect form web for “Python: список не мутируется после цикла”

Нет, потому что когда вы делаете entry = entry + 1 вы создаете новый целочисленный объект и привязываете его к entry имени, исходный объект, привязанный к этому имени, не изменяется.

Помните, что в Python целые объекты неизменяемы. Однако, если a содержит измененные объекты, например списки, вы можете сделать это:

 a = [[1], [2]] for entry in a: entry += [1] print a 

И тогда элементы в a будут мутированы:

вывод

 [[1, 1], [2, 1]] 

Обратите внимание, что если вы только что сделали entry = entry + [1] то a останется неизменным из-за того, что простое присваивание связывает новый объект с именем.

Вы можете найти эту статью полезной: Факты и мифы о именах и ценностях Python , которые были написаны ветеранкой SO Нед Батчелдер.

Чтобы изменить исходный список, вы можете сделать следующее:

 a =[1,2] for x in range(len(a)): a[x] = a[x] + 1 print a 

Или вы можете изменить цикл for на «oneliner» следующим образом:

 a =[1,2] a = [x + 1 for x in a] print a 

Вывод любого из этих методов:

 [2, 3] 

Разница между методами – это первая модификация списка, а вторая создает новый список.

Нет, почему?

entry – это просто имя, которое цикл for присваивает каждому целому числу в списке. Если впоследствии вы переназначить это имя, чтобы указать на другое целое число, список не имеет значения.

Все переменные в Python содержат ссылки (т. Е. Указатели) на некоторый объект, хранящийся где-то. Даже целые числа являются объектами. Присвоение меняет указатель на другой объект, он не изменяет элемент, на который указывает.

Когда вы выполните:

 a = [1, 2] for entry in a: entry = entry + 1 

В первый раз по циклу entry делается для указания на целое число 1 , потому что это то, на что указывает первый элемент a (известный как a[0] ).

Теперь целое число 1 не сохраняется в самом списке, а entry не является указателем на слот в списке. Скорее, entry и a[0] указывают на один и тот же объект, целое число 1 .

Когда вы делаете entry = entry + 1 (или просто entry += 1 ), entry изменяется, чтобы указать на целое число 2 . Однако, a[0] не изменяется, потому что вы его не изменили. Он по-прежнему указывает на целое число 1 .

Пути Pythonic для изменения списка во время итерации по нему – это использовать enumerate() . Это дает вам как индекс (который вам нужно изменить элемент списка), так и значение из списка.

 for index, entry in enumerate(a): a[index] += 1 

Здесь вы фактически не используете существующее значение элемента, поэтому вы также можете использовать range :

 for index in range(len(a)): a[index] += 1 

Другой способ сделать это – назначить срез в сочетании с выражением генератора. Это заменяет все содержимое списка:

  a[:] = (entry + 1 for entry in a) 

Выполнение этого способа имеет то преимущество, что если в списке a также есть другие имена, измененный список отображается через эти другие имена. Если это не то, что вы хотите, вы также можете сделать:

  a = [entry + 1 for entry in a] 

Это создает новый список с обновленными значениями и указывает на него.

  • Динамическое создание модуля в sys.modules приводит к тому, что sys становится None
  • очистить терминал в python
  • Как получить SDK App Engine для отслеживания изменений файлов в каталогах, добавленных через sys.path?
  • Как найти все обычные буквы в наборе строк?
  • Как объявить 2D-список в Cython
  • Python: лучший способ разбить большой класс
  • API облачного видения Google: «В запросе недостаточно областей проверки подлинности».
  • Указание ограничения на повторение задач, поставленных в очередь с использованием отложенной библиотеки GAE
  • Python - лучший язык программирования в мире.