如果尚未设置值,则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
。但是更复杂的情况呢?
答案 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)