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

时间:2015-01-10 22:04:17

标签: python python-3.x python-3.4

我常常发现,在使用Pythonic套装时,似乎没有Pythonic方式。

例如,做像dijkstra或*:

这样的事情
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的使用方式,例如,访问/使用dict的值,我本来希望能够做到:

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(如果可能更有效)的方式使用这种设置为防护用法?

1 个答案:

答案 0 :(得分:5)

添加操作不应该告诉您项目是否已经在集合中;它只是确保它添加后它在那里。换句话说,你想要的不是&#34;添加一个项目并检查它是否有效&#34 ;;你想首先检查项目是否在那里,如果没有,那么做一些特别的事情。如果您只想添加项目,则根本不会进行检查。关于这种模式没有什么不可思议的东西:

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

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