0
def paintPointsBlack(originalBoard, point0, point1, point2):
    board = originalBoard[:]
    # do something
    return board

def fillTheBoard(board, point):
    movePointToWhitePoint(board, point)   

    if point['row'] == height - 1:
        print('last line. terminate')
        return

    elif point['row'] != height - 1:
        LCanFit = canPutLShape(board, point)
        if LCanFit['total'] != 0:
            point0 = dict(point)
            if LCanFit['RdD'] == 1:
                ...
                newBoard = paintPointsBlack(board[:], point, point1, point2)
                fillTheBoard(newBoard, point0)
            if LCanFit['DL'] == 1:
                ...
                newBoard = paintPointsBlack(board[:], point, point1, point2)
                fillTheBoard(newBoard, point0)
            if LCanFit['RD'] == 1:
                ...
                newBoard = paintPointsBlack(board[:], point, point1, point2)
                fillTheBoard(newBoard, point0)
            if LCanFit['DR'] == 1:
                ...
                newBoard = paintPointsBlack(board[:], point, point1, point2)
                fillTheBoard(newBoard, point0)          
            print("inspected everything around : ", point['row'], point['col'])
        else:
            return

fillTheBoard is a function that calls itself if certain condition(LCanFit) matches. There are many ifs, and for this to work properly, the initially passed argument board should not change at the same depth of if. The only function that could have changed board was paintPointsBlack but to avoid this, I passed the copy (board[:]) and in an extra cautious but meaningless attempt, I made it to copy the argument inside the paintPointsBlack.

The problem I have is that the board is still changed after one branch of recursion finishes and moves to the next branch(next if). So the board inside if LCanFit['RdD'] == 1 and board inside if LCanFit['DL'] == 1(the same depth) is not the same because board is changed to newBoard of the last called function(deepest as it can go with the previous if).

I know there is no way that pass by value can change the original but I still see it changes board and it's so confusing. If I better rewrite the code, how should I structure it?

  • 6
    `board[:]` only copies the top-level list - I'm guessing that this variable is actually a list of lists, so the inner lists are being passed via references that can be mutated. Use `copy.deepcopy()` to make a complete copy of the object. – jasonharper May 09 '19 at 14:33
  • I imagine you've seen ... https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list – wwii May 09 '19 at 14:39
  • Recursion itself won't cause the behavior you're seeing, just makes it harder to think about. Are you printing stuff at the top of the function and in the if suites? Any way you can construct an [mcve] that can be copied and tested by your readers? – wwii May 09 '19 at 14:43
  • Sometimes just creating a *self contained* [mcve] will highlight the problem for you. – wwii May 09 '19 at 14:49
  • Python does not use call by value. – juanpa.arrivillaga May 09 '19 at 15:24
  • @jasonharper Yes, so unlike what I thought, list(board) or board[:] was all shallow copy. I used deepcopy() as you suggested and it works as intended. Thanks! – PuffedRiceCrackers May 11 '19 at 02:22
  • @wwii I thought erasing parts of the code will help people to see it, but I guess it did the opposite. Thank you for suggesting a helpful guideline! – PuffedRiceCrackers May 11 '19 at 02:22

0 Answers0