def set_if_not_there(d, fields, default_value=None):
for field in fields:
if not field in d:
d[field] = default_value
d = { }
set_if_not_there(d, ['cnt1', 'cnt2'], 0)
set_if_not_there(d, ['tags1', 'tags2'], [])
d['cnt1'] += 1
d['tags1'].append('work')
print d
The output is:
{'tags2': ['work'], 'cnt2': 0, 'cnt1': 1, 'tags1': ['work']}
As you can see, tags1
and tags2
are actually refering to the same list, which is not intended. cnt1
and cnt2
are working fine.
How can I implement set_if_not_there
so that I create copies
of the mutable, but only when needed? That is, if default value is a "scalar" (int, string, None
, ...) no copy is needed, but for lists and dicts a copy is necessary.
Use a factory function instead of a default value:
def set_if_not_there(d, fields, default_factory=None):
if default_factory is None:
default_factory = lambda: None
for field in fields:
if not field in d:
d[field] = default_factory()
and pass in callables (like functions or lambdas, or default types):
set_if_not_there(d, ['cnt1', 'cnt2'], int)
set_if_not_there(d, ['tags1', 'tags2'], list)
int()
returns 0
, list()
returns a new empty list.
This is what the standard library collections.defaultdict()
type does as well, for example.
Demo:
>>> d = {}
>>> set_if_not_there(d, ['cnt1', 'cnt2'], int)
>>> set_if_not_there(d, ['tags1', 'tags2'], list)
>>> d['cnt1'] += 1
>>> d['tags1'].append('work')
>>> print d
{'tags2': [], 'cnt2': 0, 'cnt1': 1, 'tags1': ['work']}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With