通过递归函数调用传递的空字典被视为“NoneType”

时间:2017-11-18 20:50:37

标签: python dictionary recursion null

我有一个递归功能,机器人正在使用它来玩连接四游戏为了让你对函数中发生的事情有一个基本的了解 - 它使用蒙特卡罗搜索来选择统计上具有的下一个动作最好的胜利:在所有可能的举动中失去比例

但是,对于我的问题,这些信息都不是必需的。我的递归函数在第一次调用时将其作为其参数之一的空字典{}。该字典被传递到每个递归调用,直到到达游戏结束的点。此时,字典被修改并返回,因此该字典将通过所有递归调用并最终返回到函数的初始调用。字典的每个键都是我的类Cell的一个实例,每个值都是一个长度为2的整数列表。

当我用空dict逐字调用递归函数时,在到达游戏结束的第一点,我需要添加第一个Cell - [int, int]键值对dict,在这样做的时候,我有一个if语句来检查密钥是否已经存在于字典中。

此时我正在接受错误:

in __MonteCarloSearch
    if startingCell in winRatios:
TypeError: argument of type 'NoneType' is not iterable

这是我的代码,我已经评论了导致错误的行:

def getMove(self, prompt, grid):
    winRatios = self.__MonteCarloSearch(grid, True, {}, None)
    bestCell = [None, None]
    for cell, ratio in winRatios.items():
        if ratio[0] / ratio[1] > bestCell[1]:
            bestCell = Cell

    return cell.colLabel

def __MonteCarloSearch(self, grid, myMove, winRatios, startingCell):   # COUNT NUM SEQUENCE SIMULATED
    for cell in grid:
        if startingCell is None:
            startingCell = cell
        cellBelow = None
        if cell.row > 0:
            cellBelow = grid.getCellFromLabel(cell.colLabel + rowLabels[cell.row - 1])
        if (cell.value == empty or cell.value == blocked) and (cell.row == 0 or cellBelow.value != empty):
            testGrid = deepcopy(grid)
            if myMove:
                testGrid.placeChip(cell.colLabel, self.chip)
            else:
                testGrid.placeChip(cell.colLabel, chips[(chips.index(self.chip) + 1) % len(chips)])
            gameWon, gridFull = testGrid.gameOver()
            if gameWon and myMove:
                if startingCell in winRatios:   # ERROR PRODUCED HERE
                    winRatios[startingCell] = [winRatios[startingCell][0] + 1, winRatios[startingCell][1] + 1]
                else:
                    winRatios[startingCell] = [1, 1]
                return winRatios
            if (gameWon and not myMove) or gridFull:
                if startingCell in winRatios:   # ERROR PRODUCED HERE
                    winRatios[startingCell] = [winRatios[startingCell][0], winRatios[startingCell][1] + 1]
                else:
                    winRatios[startingCell] = [0, 1]
                return winRatios
            winRatios = self.__MonteCarloSearch(testGrid, not myMove, winRatios, startingCell)

另外,我已将行更改为if winRatios and startingCell in winRatios,但接收到类似错误:

in __MonteCarloSearch
    winRatios[startingCell] = [0, 1]
TypeError: 'NoneType' object does not support item assignment

1 个答案:

答案 0 :(得分:3)

您需要在功能结束时返回winRatios。有些代码路径不会从递归调用返回winRatios值,最终会返回一个隐式的无。

例如,这将在

时发生

if (cell.value == empty or cell.value == blocked) and (cell.row == 0 or cellBelow.value != empty):

对于for循环中的任何单元格,

都不会计算为True。