Reputation: 5560
I have dictionaries for which I want to assign a value to a key if that key doesn't exist. I found myself writing this pretty often:
class Document(object):
def __init__(properties):
self.properties = properties
self.properties['created']=properties.get('created',datetime.datetime.now())
self.properties['foo']=properties.get('foo','bar')
Someone suggested this equivalent:
self.properties = {'created',datetime.datetime.now(),'foo':'bar'}
self.properties.update(properties)
Is there any benefit from using one or the other?
I was hoping to achieve this assignment in one line but unfortunately the update()
method does not return the modified dictionary. Is there a good performant one-liner alternative?
Upvotes: 1
Views: 1329
Reputation: 5115
You can use a defaultdict
from the collections module:
from collections import defaultdict
>>> d=defaultdict(datetime.datetime.now)
>>> d['created']
datetime.datetime(2016, 2, 4, 16, 44, 42, 767328)
You could also use setdefault
, a dict
method:
class Document(object):
def __init__(self,properties):
self.properties = properties
self.properties.setdefault('created',datetime.datetime.now())
Using setdefault
won't set the other dict values to datetime.datetime.now()
, so it is likely more appropriate for you.
Upvotes: 1
Reputation: 155333
If you're able to use Python 3.5, additional unpacking generalizations makes this easy:
class Document(object):
def __init__(self, properties):
self.properties = {'created': datetime.datetime.now(), **properties}
If the properties dict
is guaranteed to only have string keys, you could also do the following in any version of Python:
self.properties = dict({'created': datetime.datetime.now()}, **properties)
And while it's a little ugly, for any version of Python, you can get a similar effect to the additional unpacking generalizations with:
from itertools import chain
...
self.properties = dict(chain({'created': datetime.datetime.now()}.items(), properties.items()))
Lastly, if none of those are an option, you can at least avoid separate get
and store operations, by using setdefault
:
self.properties = properties
properties.setdefault('created', datetime.datetime.now())
setdefault
acts like get
, except it also stores the default value if there is no existing key. Note that like the get
based version, this keeps the exact dict
provided by the caller, mutating it, and remaining subject to being mutated by the caller in the future. All the other solutions avoid this. To fix that for either get
or setdefault
, change to:
self.properties = properties.copy()
self.properties.setdefault('created', datetime.datetime.now())
Upvotes: 1