Python 2.5中增加的collections.defaultdict极大地减少了对dict的setdefault方法的需求。这个问题是为了我们的集体教育:

在今天的Python 2.6/2.7中,setdefault在哪些方面仍然有用? setdefault的哪些流行用例被collections.defaultdict所取代?


当前回答

我经常使用setdefault,在字典中设置默认值(!!)通常是os。环境字典:

# Set the venv dir if it isn't already overridden:
os.environ.setdefault('VENV_DIR', '/my/default/path')

简单点说,是这样的:

# Set the venv dir if it isn't already overridden:
if 'VENV_DIR' not in os.environ:
    os.environ['VENV_DIR'] = '/my/default/path')

值得注意的是,你也可以使用结果变量:

venv_dir = os.environ.setdefault('VENV_DIR', '/my/default/path')

但与违约之前相比,这已经不那么必要了。

其他回答

正如大多数答案,state setdefault或defaultdict将允许您在键不存在时设置默认值。然而,我想指出一个关于setdefault用例的小警告。当Python解释器执行时,setdefaultit将始终计算函数的第二个参数,即使该键存在于字典中。例如:

In: d = {1:5, 2:6}

In: d
Out: {1: 5, 2: 6}

In: d.setdefault(2, 0)
Out: 6

In: d.setdefault(2, print('test'))
test
Out: 6

正如你所看到的,即使字典中已经存在2,print也会被执行。如果您计划使用setdefault来进行诸如内存之类的优化,这就变得尤为重要。如果将递归函数调用作为setdefault的第二个参数,则不会从中获得任何性能,因为Python总是递归地调用该函数。

既然提到了内存,一个更好的选择是使用functools。Lru_cache装饰器,如果考虑使用内存增强函数。Lru_cache可以更好地处理递归函数的缓存需求。

我经常使用setdefault,在字典中设置默认值(!!)通常是os。环境字典:

# Set the venv dir if it isn't already overridden:
os.environ.setdefault('VENV_DIR', '/my/default/path')

简单点说,是这样的:

# Set the venv dir if it isn't already overridden:
if 'VENV_DIR' not in os.environ:
    os.environ['VENV_DIR'] = '/my/default/path')

值得注意的是,你也可以使用结果变量:

venv_dir = os.environ.setdefault('VENV_DIR', '/my/default/path')

但与违约之前相比,这已经不那么必要了。

当我想要OrderedDict中的默认值时,我使用setdefault()。没有一个标准的Python集合可以同时做到这两点,但是有一些方法可以实现这样的集合。

我通常使用setdefault作为关键字参数字典,例如在这个函数中:

def notify(self, level, *pargs, **kwargs):
    kwargs.setdefault("persist", level >= DANGER)
    self.__defcon.set(level, **kwargs)
    try:
        kwargs.setdefault("name", self.client.player_entity().name)
    except pytibia.PlayerEntityNotFound:
        pass
    return _notify(level, *pargs, **kwargs)

它非常适合在包装器中围绕接受关键字参数的函数调整参数。

[编辑]大错特错!setdefault总是会触发long_computation,因为Python很急切。

扩展塔特尔的答案。对我来说,最好的用例是缓存机制。而不是:

if x not in memo:
   memo[x]=long_computation(x)
return memo[x]

这需要3行和2到3次查找,我很乐意这样写:

return memo.setdefault(x, long_computation(x))