О том, как изменить список на месте в функции в Python
Если я попытаюсь изменить список "доски" на месте, как показано ниже, он не будет работать, похоже, что он генерирует какую-то новую "доску" вместо того, чтобы модифицировать на месте.
def func(self, board):
"""
:type board: List[List[str]]
"""
board = [['A' for j in range(len(board[0]))] for i in range(len(board))]
return
Я должен сделать что-то вроде этого, чтобы изменить это на месте, в чем причина? Благодарю.
for i in range(len(board)):
for j in range(len(board[0])):
board[i][j] = 'A'
2 ответа
Кажется, вы понимаете разницу между этими двумя случаями и хотите знать, почему Python заставляет вас обращаться с ними по-разному?
Я должен сделать что-то вроде этого, чтобы изменить это на месте, в чем причина?
Создание новой копии - это то, что имеет значение. Так что имеет смысл для этого быть выражением. На самом деле, списочные понимания были бы бесполезны, если бы они не были выражениями.
Мутирование списка на месте не имеет значения. Так что нет причин делать это выражением, и на самом деле это было бы странно. Конечно, вы можете придумать какое-то значение (например, список, видоизменяемый). Но это противоречило бы всему остальному в дизайне Python: spam.append(eggs)
не возвращается spam
, это ничего не возвращает. spam = eggs
не имеет значения. И так далее.
Во-вторых, стиль понимания очень хорошо вписывается в итеративную парадигму, которая является фундаментальной для Python. Например, обратите внимание, что вы можете превратить понимание списка в понимание генератора (которое дает вам ленивый итератор для значений, которые вычисляются по требованию), просто изменив […]
в (…)
, Какой полезный эквивалент может быть для мутации?
Создание более удобной копии-преобразования также побуждает людей использовать стиль без мутаций, что часто приводит к лучшим ответам на многие проблемы. Если вы хотите узнать, как избежать написания трех строк вложенного оператора для изменения какого-либо глобального, ответ заключается в том, чтобы прекратить изменять этот глобальный объект, вместо этого передать параметр и вернуть новое значение.
Кроме того, синтаксис был скопирован с Haskell, где нет мутации.
Но, конечно, все эти "часто" и "обычно" не означают "никогда". Иногда (если вы не разрабатываете язык без мутаций), вам нужно делать вещи на месте. Вот почему мы имеем list.sort
так же как sorted
, (И много работы ушло на оптимизацию ада list.sort
; это не просто запоздалая мысль.)
Python не мешает вам сделать это. Он просто не наклоняется так далеко, чтобы облегчить копирование.
Это не меняет его на месте. Синтаксис понимания списка [x for y in z]
создает новый список. Исходный список не изменяется с помощью этого синтаксиса. Если имя внутри функции указывает на новый список, это не изменит того списка, на который указывает имя вне функции.
Другими словами, при вызове функции python передает ссылку на объект, а не имя, поэтому нет простого способа изменить, к какому объекту относится имя переменной вне функции.