仅在尚未设置值的情况下在dict中设置值

时间:2013-04-12 07:06:16

标签: python dictionary lazy-evaluation

如果尚未设置值,则dict中设置值的 pythonic 方法最多的是什么?

目前我的代码使用if语句:

if "timeout" not in connection_settings:
    connection_settings["timeout"] = compute_default_timeout(connection_settings)

dict.get(key,default)适用于使用dict的代码,而不适用于准备将dict传递给另一个函数的代码。你可以用它来设置一些东西,但它没有更漂亮的imo:

connection_settings["timeout"] = connection_settings.get("timeout", \
    compute_default_timeout(connection_settings))
即使dict包含密钥,

也会评估计算函数;错误。

Defaultdict是默认值相同的时候。

当然,很多时候您将不需要计算的主要值设置为默认值,它们当然可以使用dict.setdefault。但是更复杂的情况呢?

8 个答案:

答案 0 :(得分:25)

dict.setdefault将精确地“仅在未设置值时在dict中设置值”,这是您的问题。但是,您仍然需要计算值以将其作为参数传递,这不是您想要的。

答案 1 :(得分:10)

这是一个非答案,但我会说最pythonic是你所拥有的if语句。你用__setitem__或其他方法抵制了对单行的冲动。您已经避免了逻辑中可能存在的错误,因为在尝试使用短路and / or黑客时变得聪明时可能会出现现有但错误的值。很明显,在没有必要时不使用计算功能。

它清晰,简洁,易读 - pythonic

答案 2 :(得分:2)

一种方法是:

if key not in dict:
  dict[key] = value

答案 3 :(得分:2)

Python 3.9 起,您可以使用 merge运算符 |合并两个字典。右侧的dict优先:

d = { key: value } | d

注意:这将使用更新后的值创建一个新字典。

答案 4 :(得分:0)

@Rotareti 的回答让我想知道对于旧版本的 Python 和 3.9,我们是否可以这样做:

>>> dict_a = {'a': 1 }
>>> dict_a = {'a': 3, 'b': 2, **dict_a}
>>> dict_a

{'a': 1, 'b': 2}

(嗯,它在 Python3.7 上肯定有效,但是这个 Pythonesque 足够了吗?)

答案 5 :(得分:-1)

我正在使用以下内容将kwargs修改为非默认值并传递给另一个函数:

def f( **non_default_kwargs ):

    kwargs = {
        'a':1,
        'b':2,
    }
    kwargs.update( non_default_kwargs )

    f2( **kwargs )

这有其优点

  • 您不必两次输入密钥

  • 所有这些都是在一个功能中完成的

答案 6 :(得分:-1)

您可能需要dict.setdefault

创建一个新词典并设置一个值:

>>> d = {}
>>> d.setdefault('timeout', 120)
120
>>> d
{'timeout': 120}

如果已设置值,dict.setdefault将不会覆盖它:

>>> d['port']=8080
>>> d.setdefault('port', 8888)
8080
>>> d
{'port': 8080, 'timeout': 120}

答案 7 :(得分:-1)

我发现利用d .get()方法返回None(Falsy)以及or来推迟评估昂贵的网络请求是方便而明显的。钥匙不存在。

d = dict()

def fetch_and_set(d, key):
    d[key] = ("expensive operation to fetch key")
    if not d[key]:
        raise Exception("could not get value")
    return d[key]

...

value = d.get(key) or fetch_and_set(d, key)

在我的具体情况中,我正在从缓存构建 new 字典,然后在加速fn()调用后更新缓存。

以下是我使用的简化视图

j = load(database)  # dict
d = dict()

# see if desired keys are in the cache, else fetch
for key in keys:
    d[key] = j.get(key) or fetch(key, network_token)

fn(d)  # use d for something useful

j.update(d)  # update database with new values (if any)