Функция изменяется вне переменной без запроса [дубликат]

avatar
lixitrixi
9 августа 2021 в 00:16
41
1
0

Я создаю простой минимаксный алгоритм для игры в крестики-нолики. Функция make_move() принимает доску и координаты x/y и возвращает доску с данным сделанным ходом. Я использую эту функцию как для выполнения ходов, так и для создания списка дочерних досок, чтобы выбрать лучший следующий ход.

Моя проблема: каждый раз, когда я вызываю функцию, она также изменяет глобальную переменную board, чтобы отразить перемещение. Я не использую board = make_move(), а также пытался использовать функцию с копией board, но безрезультатно. Вот более простая версия моего кода:

board = [ [0 for x in range(3)] for y in range(3) ] # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

def make_move(state, x, y): # return board with given move made
  state[y][x] = 1

  return state

print(make_move(board, 1, 1)) # prints [[0, 0, 0], [0, 1, 0], [0, 0, 0]]

print(board) # also prints [[0, 0, 0], [0, 1, 0], [0, 0, 0]]

Мой вопрос: поскольку я не указываю board = make_move(board, ...), что, очевидно, изменит исходную переменную board, что я здесь делаю неправильно, что приводит к изменению board?

Передача board[:] вместо board в make_move(), которая в противном случае должна создать отдельную копию, не работает.

Я надеюсь, что это было достаточно описательно; это мой первый вопрос :)

Источник
Tim Roberts
9 августа 2021 в 00:26
2

Учти это. В верхней строке вы создаете один объект списка, который содержит три других объекта списка. Во всей вашей программе это ТОЛЬКО четыре объекта списка, которые когда-либо существовали. Эти списки имеют разные имена: state и board оба относятся к исходному объекту списка.

juanpa.arrivillaga
9 августа 2021 в 00:54
1

Глобальная переменная board не изменяется, она по-прежнему ссылается на тот же самый объект, который вы передали в make_move, и мутирует внутри.

Ответы (1)

avatar
Hubert Bossy
9 августа 2021 в 00:30
1

[:] создает так называемую мелкую копию - новый объект со ссылками, скопированными из старого. Чтобы создать глубокую копию, используйте copy.deepcopy():

.
import copy
board = [ [0 for x in range(3)] for y in range(3) ] # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

def make_move(state, x, y): # return board with given move made
  state_copy = copy.deepcopy(state)
  state_copy[y][x] = 1

  return state_copy