简体   繁体   中英

Why is my list different than what I appended?

I am working on a project that makes an 'ai' for a game called hexapawn that works via removing the possibility of a move occurring at that board position if the player ends up winning right after. For some that I am unaware of, whenever I append my board position and move that was made, when I print the whole list at the end, everything is right except the board inside each entry in the list.

Note: If I append the move entry as a string, everything works. But I need to have it be a list so that I can index from it later.

I know this has something to do with multiple references to the same list but I don't see where it's happening.

Here is my code.

import random

def main():
    print(printBoard(board))
    move(0, 0, board)
    print(printBoard(board))
    move(2, 1, board)
    print(printBoard(board))
    print(f'What I have in the end: {moves_ai}')

board = [
    [1, 1, 1],
    [0, 0, 0],
    [2, 2, 2]
    ]

moves_ai = []

forbiden_moves_ai = []

#Board Mechanics
def printBoard(board):
    return str(board[0]) + '\n' + str(board[1]) + '\n' + str(board[2]) + '\n'

def move(row, col, board):
    if board[row][col] == 1:
        if board[row + 1][col] == 0:
            moves_ai.append([row, col, row + 1, col, board])
            print(f'What I appended: {[row, col, row + 1, col, board]}')
            board[row + 1][col] = 1
            board[row][col] = 0
        else:
            return -1
    if board[row][col] == 2:
        if board[row - 1][col] == 0:
            moves_ai.append([row, col, row - 1, col, board])
            print(f'What I appended: {[row, col, row - 1, col, board]}')
            board[row - 1][col] = 2
            board[row][col] = 0
        else:
            return -1

def is_possible(end_row, end_col, board):
    if end_row < 0 or end_row > 2 or end_col < 0 or end_col > 2:
        return False
        
    return True

#AI Section
def random_move(board):
    ind = []
    move_decided = False
    for row in range(3):
        for col in range(3):
            if board[row][col] == 2:
                ind.append([row, col])
    while not move_decided:
        r_move = random.choice(ind)
        if bool(random.getrandbits(1)):
            if [r_move[0], r_move[1], r_move[0] - 1, r_move[1], board] not in forbiden_moves_ai and move(r_move[0], r_move[1], board) != -1:       
                move_decided = True
            else:
                continue
        else:
            left = bool(random.getrandbits(1))
            if left:
                if [r_move[0], r_move[1], r_move[0] - 1, r_move[1] - 1, board] not in forbiden_moves_ai:
                    if capture(left, r_move[0], r_move[1], board) != -1:
                        move_decided = True
                    else:
                        continue
            else:
                if [r_move[0], r_move[1], r_move[0] - 1, r_move[1] + 1, board] not in forbiden_moves_ai:
                    if capture(left, r_move[0], r_move[1], board) != -1:
                        move_decided = True
                    else:
                        continue
    

def remove_move(row1, col1, row2, col2, situation):
    forbiden_moves_ai.append([row1, col1, row2, col2, situation])

if __name__ == '__main__':
    main()

This is the expected output:

What I have in the end: [[0, 0, 1, 0, [[1, 1, 1], [0, 0, 0], [2, 2, 2]]], [2, 1, 1, 1, [[0, 1, 1], [1, 0, 0], [2, 2, 2]]]]

This is the output:

What I have in the end: [[0, 0, 1, 0, [[0, 1, 1], [1, 2, 0], [2, 0, 2]]], [2, 1, 1, 1, [[0, 1, 1], [1, 2, 0], [2, 0, 2]]]]

Also, here is an easy way to recreate the problem:

l = []
num = [1]

l.append(num)
num[0] = 9
l.append(num)

print(l)

Expected result:

[[1], [9]]

Result:

[[9], [9]]

I am still keeping the full code I wrote so that anyone who used that can still copy and paste it again.

l = []
num = [1]

l.append(num)
print(l) # [[1]]
num[0] = 9
print(l) # [[9]]
l.append(num)

print(l)

The issue is as @Itagyba Abondanza Kuhlmann stated. num is mutable. When you append it to l , you're not appending a snapshot of num , you're appending a "reference" to num . In the end, l contains as its elements two references, both to num which equals [9] which is why you l is [[9], [9]] .

pythontutor.com might help you see what is going on behind the scenes. Also, this presentation by Ned Batchelder explains some of this in a very good way: presentation .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM