Set a value in a dict only if the value is not already set

半世苍凉 提交于 2019-12-21 07:55:38

问题


What is the most pythonic way to set a value in a dict if the value is not already set?

At the moment my code uses if statements:

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

dict.get(key,default) is appropriate for code consuming a dict, not for code that is preparing a dict to be passed to another function. You can use it to set something but its no prettier imo:

connection_settings["timeout"] = connection_settings.get("timeout", \
    compute_default_timeout(connection_settings))

would evaluate the compute function even if the dict contained the key; bug.

Defaultdict is when default values are the same.

Of course there are many times you set primative values that don't need computing as defaults, and they can of course use dict.setdefault. But how about the more complex cases?


回答1:


This is a bit of a non-answer, but I would say the most pythonic is the if statement as you have it. You resisted the urge to one-liner it with __setitem__ or other methods. You've avoided possible bugs in the logic due to existing-but-falsey values which might happen when trying to be clever with short-circuiting and/or hacks. It's immediately obvious that the compute function isn't used when it wasn't necessary.

It's clear, concise, and readable - pythonic.




回答2:


dict.setdefault will precisely "set a value in a dict only if the value is not already set".

You still need to compute the value to pass it in as the parameter:

connection_settings.setdefault("timeout", compute_default_timeout(connection_settings))



回答3:


One way to do this is:

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



回答4:


I'm using the following to modify kwargs to non-default values and pass to another function:

def f( **non_default_kwargs ):

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

    f2( **kwargs )

This has the merits that

  • you don't have to type the keys twice

  • all is done in a single function




回答5:


You probably need dict.setdefault:

Create a new dictionary and set a value:

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

If a value already set, dict.setdefault won't override it:

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



回答6:


I found it convenient and obvious to exploit the return of the dict .get() method being None (Falsy), along with or to put off evaluation of an expensive network request if the key was not present.

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)

In my case specifically, I was building a new dictionary from a cache then later updating the cache after expediting the fn() call.

Here's a simplified view of my use

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)


来源:https://stackoverflow.com/questions/15965146/set-a-value-in-a-dict-only-if-the-value-is-not-already-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!