Python - функция переписывает глобальную переменную

Рейтинг: 2Ответов: 2Опубликовано: 24.02.2023

Имею глобальную переменную (список):

game_matrix = ['7','8','9',],['4','5','6',],['1','2','3',]

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

  1. функции не должны так делать
  2. та часть кода, после выполнения которой данная переменная перезаписывается, не говорит явно, что нужно что-то в нее записать.


    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 дав пустое значение?

Ответы

▲ 3Принят

Если я правильно понял вопрос, то ваша проблема в том, что вот в этом коде

games = []
    for row in game_matrix:
        games.append(row)

вы ожидаете, что у вас создастся копия матрицы, не связанная с оригиналом.

Однако надо понимать, что games.append(row) добавляет в новую матрицу ту же саму строчку, а не её копию. То есть теперь у вас есть другая матрица, но состоящая из трёх тех же самых строчек.

(Если из других языков вы знакомы с понятием ссылки, то можно сказать, что строчка вставляется в новую матрицу по ссылке, а не по значению.)

Для того, чтобы получить отдельную матрицу, никак не связанную с изначальной, нужно явно брать копию строки:

games = []
    for row in game_matrix:
        games.append(row.copy())  # Вот так вот
▲ 1

Предложу ещё один вариант полного копирования массива: функция deepcopy модуля copy. Копирование массива в данном случае будет выглядеть так:

from copy import deepcopy
games = deepcopy(game_matrix)