Pythonic 方式添加到集合并关心它是否有效



很多时候,我发现,在使用 Python 集合时,Python 的方式似乎不存在。

例如,执行类似 dijkstra 或 a* 的操作:

openSet, closedSet = set(nodes), set(nodes)
while openSet:
    walkSet, openSet = openSet, set()
    for node in walkSet:
        for dest in node.destinations():
            if dest.weight() < constraint:
                if dest not in closedSet:
                    closedSet.add(dest)
                    openSet.add(dest)

这是一个做作不力的例子,重点是最后三行:

if not value in someSet:
    someSet.add(value)
    doAdditionalThings()

鉴于 Python 的工作方式,例如,访问/使用字典的值,我希望能够做到:

try:
    someSet.add(value)
except KeyError:
    continue # well, that's ok then.
doAdditionalThings()

作为一名C++程序员,我的皮肤爬行了一点,我甚至做不到:

if someSet.add(value):
    # add wasn't blocked by the value already being present
    doAdditionalThings()

有没有一种更 Pythonic (如果可能的话更有效)的方式来处理这种设置即保护的使用?

add 操作不应该告诉您该项目是否已在集合中;它只是确保在添加后它在那里。 或者换句话说,你想要的不是"添加一个项目并检查它是否有效";你想检查该项目是否存在,如果没有,那就做一些特殊的事情。 如果您只想添加项目,则根本不会进行检查。 这种模式没有什么不pythonient的:

if item not in someSet:
    someSet.add(item)
    doStuff()
else:
    doOtherStuff()

确实,API 的设计可以.add返回该项目是否已经存在,但根据我的经验,这不是一个特别常见的用例。 集合的部分要点是您可以自由添加项目,而不必担心它们是否已经在那里(因为添加已经包含的项目不起作用)。 此外,.add返回 None 符合 Python 内置类型的一般约定,即改变其参数的方法返回 None。 实际上,像dict.setdefault这样的事情(它获得一个项目,但如果不存在,则首先添加它)是不寻常的情况。

最新更新