2014-02-08 2 views
1

Я пишу небольшой скрипт python, который выводит список строк, где сами строки являются списком строк. Это то, что делает функция. Предполагается взять этот список в качестве входных данных и распечатать прекрасную версию, не изменяя при этом этот список. Я могу заставить его распечатать правильный вывод. Но при более внимательных проверках также изменяет первоначальный список, хотя первым, что я делаю в функции, чтобы сделать копию исходного списка с помощью этого grid_copy = grid[:]Python - функция, меняющая список ввода, хотя я сделал копию

Проблемы: Сценарий превращает любой '' в ' ' хотя я не изменить список

[['X', 'X', ''], ['', 'O', 'O'], ['O', 'X', '']]

в:

[X] [X] [ ] 

[ ] [O] [O] 

[O] [X] [ ] 

Я не знаю, что вызывает изменение списка, нет, где я ссылаюсь на исходный список, за исключением случаев, когда я делаю копию в начале.

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

def show_grid(grid): 
    """ 
    grid: list. A list of lines, where the lines are a list of strings 
    return: None 
     Prints the grid out in the classic 3x3 
    """ 
    grid_copy = grid[:] # make a copy so we do not want to actually change grid 
    len_grid = len(grid_copy) # I use this so much, might as well store it 

    # add whitespaces to make each single spot the same width 
    len_digits = len(str((len(grid_copy)**2))) # the number of chars wide the highest number is 
    # modification happens somewhere vvv 
    for line in range(len_grid): 
     for char in range(len_grid): 
      grid_copy[line][char] = str(grid_copy[line][char]).rjust(len_digits) # proper white spaces 

    # modification happens somewhere ^^^ 

    # add brackets, THIS IS NOT WHERE THE PROBLEM IS 
    for line in grid_copy: 
     print('[' + '] ['.join(line)+']\n') # print each symbol in a box 


# TESTING TESTING 
test_grid = [['X', 'X', ''], ['', 'O', 'O'], ['O', 'X', '']] 
print('test_grid before: {}'.format(test_grid)) 
show_grid(test_grid) # this should not modify test_grid, but it does 
print('test_grid after: {}'.format(test_grid)) 

ВЫВОД:

test_grid before: [['X', 'X', ''], ['', 'O', 'O'], ['O', 'X', '']] 
[X] [X] [ ] 

[ ] [O] [O] 

[O] [X] [ ] 

test_grid after: [['X', 'X', ' '], [' ', 'O', 'O'], ['O', 'X', ' ']] 
+0

Кстати, [ссылка] (http://docs.python.org/2/library/copy.html) все еще полезна, и она всегда должна быть вашим первым визитом. – keyser

ответ

6

Когда вы пишете grid_copy = grid[:] в списке списка, вы только скопировать верхний список, но не является элементом самого списка. Это называется мелкой копии, противоположной глубокой копии. Вы должны написать

grid_copy = [x[:] for x in grid] 

или

grid_copy = copy.deepcopy(grid) 
+0

, так что я был списком строк, а не списком списка, который мой метод будет работать? – Vader

+0

Список строк должен делать то, что вы намеревались, потому что str являются неизменяемыми. – dstromberg

+0

@Vader: копирование списка строк с l [:] в порядке, потому что строки неизменяемы (это означает, что вы не можете изменить строку в Python). Поэтому не нужно копировать строку. – hivert

3

Используйте источник, Люк! (Извините, я должен был)

В этом разница между мелкой копией и глубокой копией. Это подробно объясняется в документации по copy module. Мелкая копия берет только контейнер первого уровня, заполняя копию ссылками на содержащиеся объекты. В то время как глубокая копия также копирует содержащиеся объекты.

+0

хорошо у вас есть upvote для исходного комментария – Vader

Смежные вопросы