Python - функция переписывает глобальную переменную
Имею глобальную переменную (список):
game_matrix = ['7','8','9',],['4','5','6',],['1','2','3',]
а также функцию, которая должна брать из нее все сведения и загружать в похожий список, заменяя некоторые элементы. Сейчас столкнулся с проблемой, что функция вносит изменения в глобальную переменную и очень смущает два факта:
- функции не должны так делать
- та часть кода, после выполнения которой данная переменная перезаписывается, не говорит явно, что нужно что-то в нее записать.
index=0
games = []
for row in game_matrix:
games.append(row)
print (games)
print (game_matrix)
for row in games:
if row[0] != 'o' and row[0] != 'x':
games[index][0]=None
if row[1] != 'o' and row[0] != 'x':
games[index][1]=None
if row[2] != 'o' and row[0] != 'x':
games[index][2]=None
index+=1
print (games)
print (game_matrix)
первая пара print в терминале дает:
[['7', '8', '9'], ['4', '5', '6'], ['o', '2', '3']]
(['7', '8', '9'], ['4', '5', '6'], ['o', '2', '3'])
список и кортеж с нужными данными ([2][0]) изменяется еще до вызова функции, с этим проблем нет, но вот вторая партия print выводит уже странный результат:
[[None, None, None], [None, None, None], [None, None, 'o']]
([None, None, None], [None, None, None], [None, None, 'o'])
собственно возникает вопрос почему цикл for .. in .. при переборе элементов взял и переписал game_matrix дав пустое значение?
Ответы (2 шт):
Если я правильно понял вопрос, то ваша проблема в том, что вот в этом коде
games = []
for row in game_matrix:
games.append(row)
вы ожидаете, что у вас создастся копия матрицы, не связанная с оригиналом.
Однако надо понимать, что games.append(row) добавляет в новую матрицу ту же саму строчку, а не её копию. То есть теперь у вас есть другая матрица, но состоящая из трёх тех же самых строчек.
(Если из других языков вы знакомы с понятием ссылки, то можно сказать, что строчка вставляется в новую матрицу по ссылке, а не по значению.)
Для того, чтобы получить отдельную матрицу, никак не связанную с изначальной, нужно явно брать копию строки:
games = []
for row in game_matrix:
games.append(row.copy()) # Вот так вот
Предложу ещё один вариант полного копирования массива: функция deepcopy модуля copy. Копирование массива в данном случае будет выглядеть так:
from copy import deepcopy
games = deepcopy(game_matrix)