I want to create a new dictionary, by updating an existing one. This behaves as supposed:
x = {'a': 1}
x.update({'a': 2})
But why does the following results in a NoneType?
({'a': 1}).update({'a': 2})
All in-place operations in the Python standard library return None, dict.update() is no exception.
You cannot create a dict literal and call .update() on that and expect it to return the updated dict object, no.
You essentially are doing this:
tmp = {'a': 1}
result = tmp.update({'a': 2})
del tmp
and expect result to be the dictionary.
You could use:
dict({'a': 1}, **{'a': 2})
and get a merged dictionary, however. Or, for a more practical looking version:
copy = dict(original, foo='bar')
creating a copy of a dictionary plus setting some extra keys (replacing any previous value for that key).
In Python 3.5 and newer you’d use:
copy = {**original, 'foo': 'bar'}
Because update, like all mutating methods in Python, returns None.
Related
This is two questions, and I'd be happy with either being answered (unless one method is preferred to another).
I have a function, say
def my_func(a, b, c, d = None):
print(a)
print(f"I like {b}")
print(f"I am {c}")
if d:
print(d)
I have a dictionary of keywords my_dict = {'a': 'Hello', 'b': 'Dogs', 'c': 'Happy', 'd': 10} which are always passed as inputs to the function my_func(**kwargs).
My questions are:
If I want to input a different value, say a='Goodbye', is there a way I can input the same argument twice overriding the first entry with the second instance of it?
Alternatively, is there something comparable to my_dict.update({'a': 'Hello'}) that won't change the values in the dictionary permanently, but will let me pass in a different value for a specific keyword?
I know I can create a new dictionary and pass that in, but I think it would be cleaner if I could do it without needing to do this (though feel free to correct me if I'm wrong!).
Edit: I'm using Python 3.8.
On Python 3.5 and up, you can unpack my_dict into a new dict and override the 'a' entry:
my_func(**{**my_dict, 'a': 'Goodbye'})
On Python 3.9 and up, you can use the | operator to create a new dict by merging entries from two dicts. Values for duplicated keys will be taken from the second dict:
my_func(**my_dict | {'a': 'Goodbye'})
Since Python 3.3, you can use collections.ChainMap:
A ChainMap groups multiple dicts or other mappings together to create
a single, updateable view.[...]
Lookups search the underlying mappings successively until a key is
found. [...]
A ChainMap incorporates the underlying mappings by reference. So, if
one of the underlying mappings gets updated, those changes will be
reflected in ChainMap.
So, your code could be:
from collections import ChainMap
def my_func(a, b, c):
print(a)
print(f"I like {b}")
print(f"I am {c}")
my_dict = {'a': 'Hello', 'b': 'Dogs', 'c': 'Happy'}
new = {'a':'Goodbye' }
my_func(**ChainMap(new, my_dict))
#Goodbye
#I like Dogs
#I am Happy
Note that new must come before my_dict, as the value will be taken from the first dict that contains the key.
Since Python 3.10, you can use the | operator:
d | other
Create a new dictionary with the merged keys and values of d
and other, which must both be dictionaries. The values of other take
priority when d and other share keys.
So, you could call your function with
my_func(**(my_dict | new))
Note that in this case, new must come after `mydict.
For hashable objects inside a dict I could easily pair down duplicate values store in a dict using a set. For example:
a = {'test': 1, 'key': 1, 'other': 2}
b = set(a.values())
print(b)
Would display [1,2]
Problem I have is I am using a dict to store mapping between variable keys in __dict__ and the corresponding processing functions that will be passed to an engine to order and process those functions, some of these functions may be fast some may be slower due to accessing an API. The problem is each function may use multiple variable, therefor need multiple mappings in the dict. I'm wondering if there is a way to do this or if I am stuck writing my own solution?
Ended up building a callable class, since caching could speed things up for me:
from collections.abc import Callable
class RemoveDuplicates(Callable):
input_cache = []
output_cache = []
def __call__(self, in_list):
if list in self.input_cache:
idx = self.input_cache.index(in_list)
return self.output_cache[idx]
else:
self.input_cache.append(in_list)
out_list = self._remove_duplicates(in_list)
self.output_cache.append(out_list)
return out_list
def _remove_duplicates(self, src_list):
result = []
for item in src_list:
if item not in result:
result.append(item)
return result
If the objects can be ordered, you can use itertools.groupby to eliminate the duplicates:
>>> a = {'test': 1, 'key': 1, 'other': 2}
>>> b = [k for k, it in itertools.groupby(sorted(a.values()))]
>>> print(b)
[1, 2]
Is there something simple like a set for un-hashable objects
Not in the standard library but you need to look beyond and search for BTree implementation of dictionary. I googled and found few hits where the first one (BTree)seems promising and interesting
Quoting from the wiki
The BTree-based data structures differ from Python dicts in several
fundamental ways. One of the most important is that while dicts
require that keys support hash codes and equality comparison, the
BTree-based structures don’t use hash codes and require a total
ordering on keys.
Off-course its trivial fact that a set can be implemented as a dictionary where the value is unused.
You could (indirectly) use the bisect module to create sorted collection of your values which would greatly speed-up the insertion of new values and value membership testing in general — which together can be utilized to unsure that only unique values get put into it.
In the code below, I've used un-hashable set values for the sake of illustration.
# see http://code.activestate.com/recipes/577197-sortedcollection
from sortedcollection import SortedCollection
a = {'test': {1}, 'key': {1}, 'other': {2}}
sc = SortedCollection()
for value in a.values():
if value not in sc:
sc.insert(value)
print(list(sc)) # --> [{1}, {2}]
This question already has answers here:
Is there a standard class for an infinitely nested defaultdict?
(6 answers)
Closed 9 years ago.
I'm creating a dictionary structure that is several levels deep. I'm trying to do something like the following:
dict = {}
dict['a']['b'] = True
At the moment the above fails because key 'a' does not exist. At the moment I have to check at every level of nesting and manually insert an empty dictionary. Is there some type of syntactic sugar to be able to do something like the above can produce:
{'a': {'b': True}}
Without having to create an empty dictionary at each level of nesting?
As others have said, use defaultdict. This is the idiom I prefer for arbitrarily-deep nesting of dictionaries:
def nested_dict():
return collections.defaultdict(nested_dict)
d = nested_dict()
d[1][2][3] = 'Hello, dictionary!'
print(d[1][2][3]) # Prints Hello, dictionary!
This also makes checking whether an element exists a little nicer, too, since you may no longer need to use get:
if not d[2][3][4][5]:
print('That element is empty!')
This has been edited to use a def rather than a lambda for pep8 compliance. The original lambda form looked like this below, which has the drawback of being called <lambda> everywhere instead of getting a proper function name.
>>> nested_dict = lambda: collections.defaultdict(nested_dict)
>>> d = nested_dict()
>>> d[1][2][3]
defaultdict(<function <lambda> at 0x037E7540>, {})
Use defaultdict.
Python: defaultdict of defaultdict?
Or you can do this, since dict() function can handle **kwargs:
http://docs.python.org/2/library/functions.html#func-dict
print dict(a=dict(b=True))
# {'a': {'b' : True}}
If the depth of your data structure is fixed (that is, you know in advance that you need mydict[a][b][c] but not mydict[a][b][c][d]), you can build a nested defaultdict structure using lambda expressions to create the inner structures:
two_level = defaultdict(dict)
three_level = defaultdict(lambda: defaultdict(dict))
four_level = defaultdict(lamda: defaultdict(lambda: defaultdict(dict)))
I am iterating a dict created using the following.
tree = defaultdict(partial(defaultdict, partial(defaultdict, list)))
for dt, hour, value in flat_list:
tree[dt][hour]=[]
tree[dt][hour].append(value)
My output looks like this:
for k,v in tree.iteritems():
2012-08-07 defaultdict(<functools.partial object at 0x1e0a050>, {'17': ['30']})
2012-08-24 defaultdict(<functools.partial object at 0x1e0a050>, {'3': ['70']})
How do I get rid of this stuff? How do I iter like a regular dict?:
defaultdict(<functools.partial object at 0x1e0a050>
You are already iterating over the default dicts like a regular dict, but you are printing the defaultdict representation too.
To print these like you would print a regular dict, just turn them back into one:
for k,v in tree.iteritems():
print k, dict(v)
Note that a defaultdict is a direct subclass of dict, apart from the updated __getitem__ behaviour and the updated __repr__ hook1, a defaultdict behaves exactly like a normal dict would, certainly when it comes to iterating.
1__copy__ and __deepcopy__ are overridden too, to create a new defaultdict when using the copy module. A custom __reduce__ is provided for the pickle module for the same reasons.
This question already has answers here:
How to concatenate two dictionaries to create a new one? [duplicate]
(5 answers)
Closed 7 years ago.
I have two dictionaries and I'd like to be able to make them one:
Something like this pseudo-Python would be nice:
dic0 = {'dic0': 0}
dic1 = {'dic1': 1}
ndic = dic0 + dic1
# ndic would equal {'dic0': 0, 'dic1': 1}
If you're interested in creating a new dict without using intermediary storage: (this is faster, and in my opinion, cleaner than using dict.items())
dic2 = dict(dic0, **dic1)
Or if you're happy to use one of the existing dicts:
dic0.update(dic1)
Here are quite a few ways to add dictionaries.
You can use Python3's dictionary unpacking feature:
ndic = {**dic0, **dic1}
Note that in the case of duplicates, values from later arguments are used. This is also the case for the other examples listed here.
Or create a new dict by adding both items.
ndic = dict(tuple(dic0.items()) + tuple(dic1.items()))
If modifying dic0 is OK:
dic0.update(dic1)
If modifying dic0 is NOT OK:
ndic = dic0.copy()
ndic.update(dic1)
If all the keys in one dict are ensured to be strings (dic1 in this case, of course args can be swapped)
ndic = dict(dic0, **dic1)
In some cases it may be handy to use dict comprehensions (Python 2.7 or newer),Especially if you want to filter out or transform some keys/values at the same time.
ndic = {k: v for d in (dic0, dic1) for k, v in d.items()}
>>> dic0 = {'dic0':0}
>>> dic1 = {'dic1':1}
>>> ndic = dict(list(dic0.items()) + list(dic1.items()))
>>> ndic
{'dic0': 0, 'dic1': 1}
>>>
You are looking for the update method
dic0.update( dic1 )
print( dic0 )
gives
{'dic0': 0, 'dic1': 1}
dic0.update(dic1)
Note this doesn't actually return the combined dictionary, it just mutates dic0.
The easiest way to do it is to simply use your example code, but using the items() member of each dictionary. So, the code would be:
dic0 = {'dic0': 0}
dic1 = {'dic1': 1}
dic2 = dict(dic0.items() + dic1.items())
I tested this in IDLE and it works fine.
However, the previous question on this topic states that this method is slow and chews up memory. There are several other ways recommended there, so please see that if memory usage is important.