Python KeyError 即使字典包含值

问题描述 投票:0回答:1

我正在Python中实现波函数折叠算法,并且每个图块都有图块和规则集。为了存储规则集,我有一个 createAll 函数,它是一个图块及其规则的字典。

这是 createAll 函数(在 TileRuleSetFactory 内部):

    @staticmethod
    def createAll() -> dict[Tile, TileRuleSet]:
        if (TileRuleSetFactory._allRuleSets != None):
            return TileRuleSetFactory._allRuleSets
        
        ruleSets: dict[Tile, TileRuleSet] = {}

        ruleSets[TileFactory.createBlank()] = TileRuleSetFactory.createBlank()
        print(ruleSets)
        print(ruleSets[TileFactory.createBlank()])
        ruleSets[TileFactory.createUp()] = TileRuleSetFactory.createUp()
        ruleSets[TileFactory.createRight()] = TileRuleSetFactory.createRight()
        ruleSets[TileFactory.createDown()] = TileRuleSetFactory.createDown()
        ruleSets[TileFactory.createLeft()] = TileRuleSetFactory.createLeft()

        TileRuleSetFactory._allRuleSets = ruleSets

        return ruleSets

TileFactory 类:

class TileFactory:
    #region Tile IDs
    MAX_ID = 4

    BLANK_ID: int = 0
    UP_ID: int = 1
    RIGHT_ID: int = 2
    DOWN_ID: int = 3
    LEFT_ID: int = 4
    #endregion

    # for flyweight pattern
    _createdTiles: dict[int, Tile] = {}

    @staticmethod
    def createAllTiles() -> list[Tile]:
        tiles: list[Tile] = []

        tiles.append(TileFactory.createBlank())
        tiles.append(TileFactory.createUp())
        tiles.append(TileFactory.createRight())
        tiles.append(TileFactory.createDown())
        tiles.append(TileFactory.createLeft())

        return tiles

    @staticmethod
    def createRandTile() -> Tile:
        return TileFactory.createById(randint(0, TileFactory.MAX_ID))

    @staticmethod
    def createById(id: int) -> Tile:
        if (id == TileFactory.BLANK_ID):
            return TileFactory.createBlank()
        
        if (id == TileFactory.UP_ID):
            return TileFactory.createUp()
        
        if (id == TileFactory.RIGHT_ID):
            return TileFactory.createRight()
        
        if (id == TileFactory.DOWN_ID):
            return TileFactory.createDown()
        
        if (id == TileFactory.LEFT_ID):
            return TileFactory.createLeft()
        
        else:
            raise ValueError()

    @staticmethod
    def createBlank() -> Tile:
        return TileFactory._createdTiles.get(TileFactory.BLANK_ID, Tile('./tiles/blank.png'))
    
    @staticmethod
    def createUp() -> Tile:
        return TileFactory._createdTiles.get(TileFactory.UP_ID, Tile('./tiles/up.png'))
    
    @staticmethod
    def createRight() -> Tile:
        return TileFactory._createdTiles.get(TileFactory.RIGHT_ID, Tile('./tiles/right.png'))
    
    @staticmethod
    def createDown() -> Tile:
        return TileFactory._createdTiles.get(TileFactory.DOWN_ID, Tile('./tiles/down.png'))
    
    @staticmethod
    def createLeft() -> Tile:
        return TileFactory._createdTiles.get(TileFactory.LEFT_ID, Tile('./tiles/left.png'))

Tile 类:

class Tile:
    def __init__(self, imgPath: str) -> None:
        self.img: pygame.Surface = pygame.image.load(imgPath)
        self.imgPath = imgPath

    def __eq__(self, value: object) -> bool:
        if (type(value) != Tile):
            return False
        
        return self.img == value.img
    
    def __hash__(self) -> int:
        return self.imgPath.__hash__()
    
    def __str__(self) -> str:
        return str(self.__hash__())
    
    def __repr__(self) -> str:
        return self.__str__()

和 TileRuleSet 类:

class TileRuleSet:
    def __init__(self, up: set[Tile] = set(),
                 right: set[Tile] = set(), down: set[Tile] = set(), left: set[Tile] = set()) -> None:
        self.up: set[Tile] = up
        self.right: set[Tile] = right
        self.down: set[Tile] = down
        self.left: set[Tile] = left

    def __str__(self) -> str:
        return f"UP: {setToString(self.up)}, RIGHT: {setToString(self.right)}, "\
        f"DOWN: {setToString(self.down)}, LEFT: {setToString(self.left)}\n"
    
    def __repr__(self) -> str:
        return self.__str__()

但是,当我调用静态 createAll 方法时,控制台中会打印以下内容:

{238499618696605147: UP: {4114546419569344162, 238499618696605147}, RIGHT: {-6386996300615071302, 238499618696605147}, DOWN: {238499618696605147, 6516502529729026507}, LEFT: {-848466221319434871, 238499618696605147}
}
Traceback (most recent call last):
  File "[PATH]\tile.py", line 221, in <module>
    TileRuleSetFactory.createAll()
  File "[PATH]\tile.py", line 136, in createAll
    print(ruleSets[TileFactory.createBlank()])
          ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 238499618696605147

如您所见,字典中存在哈希值 238499618696605147,但我仍然收到 KeyError。为什么会发生这种情况,我该如何解决?

python pygame
1个回答
0
投票

尝试使用 dict 的 .get() 方法,在这种情况下,如果从 TileFactory.createBlank() 返回的键在 RuleSets 中不存在,它将返回 false,现在,如果您不这样做,则可以验证该行为没有钥匙。

例如:

if rule_set_value := ruleSets.get(TileFactory.createBlank()):
    print(rule_set_value)
else:
    #do something

如果是一个集合,请尝试验证其用途:

if TileFactory.createBlank() in ruleSets:
    print(ruleSets[TileFactory.createBlank()])
© www.soinside.com 2019 - 2024. All rights reserved.