【问题标题】:Empty dict passed through recursive function calls is being seen as `NoneType`通过递归函数调用传递的空字典被视为`NoneType`
【发布时间】:2018-05-02 10:13:13
【问题描述】:

我有一个递归函数,机器人正在使用它来玩连接四的游戏 为了让您对函数中发生的事情有一个基本的了解 - 它使用蒙特卡洛搜索来选择下一步将在统计上具有所有可能动作中最好的输赢比例

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

当我最初使用空字典调用递归函数时,在到达游戏结束的第一点,我需要将第一个 Cell - [int, int] 键值对添加到字典中,并且在这样做时,我有一个 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

【问题讨论】:

    标签: python dictionary recursion null


    【解决方案1】:

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

    例如,当

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

    对于 for 循环中的任何单元格都不评估为 True。

    【讨论】:

    • 啊,是的,我明白了,只需将return winRatios 添加到函数的最后一行即可解决问题。谢谢。
    • 很高兴能帮上忙!如果这对您有用,您能否将答案标记为“已接受”? :)
    • 是的,它说我必须再等 5 分钟,然后就可以了!
    猜你喜欢
    • 2014-03-14
    • 2018-03-07
    • 2020-10-02
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    相关资源
    最近更新 更多