Reputation: 15367
In Python I use regularly the following construct:
x = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
y = x[v] if v in x.keys() else None
where v is normally one of the dictionary values, and y gets the value of the dictionary if the key exists, otherwise None.
I was wondering if this is a desired construct or if it can be enhanced?
x[v] can be values as above, but I also use a similar construct to call a function depending on the value of v, like:
{'a': self.f1, 'b': self.f2, 'c': self.f3, 'd': self.f4}[v]()
Upvotes: 0
Views: 265
Reputation: 41950
After spending many hours profiling some similar code, I found the most efficient way to do this is to use defaultdict
...
from collections import defaultdict
x = defaultdict(lambda: None, {'a': 1, 'b': 2, 'c': 3, 'd': 4})
y = x[v]
...and the next most efficient is two key lookups...
x = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
y = x[v] if x in v else None
Both of these are much faster than this...
x = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
y = x.get(v, None)
...and this...
x = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
try:
y = x[v]
except KeyError:
y = None
Upvotes: 1
Reputation: 1122352
Normally you'd use dict.get()
:
y = x.get(v)
.get()
takes a default parameter to return if v
is not present in the dictionary, but if you omit it None
is returned.
Even if you were to use an explicit key test, you don't need to use .keys()
:
y = x[v] if v in x else None
Interestingly enough, the conditional expression option is slightly faster:
>>> [x.get(v) for v in 'acxz'] # demonstration of the test; two hits, two misses
[1, 3, None, None]
>>> timeit.timeit("for v in 'acxz': x.get(v)", 'from __main__ import x')
0.8269917964935303
>>> timeit.timeit("for v in 'acxz': x[v] if v in x else None", 'from __main__ import x')
0.67330002784729
until you avoid the attribute lookup for .get()
:
>>> timeit.timeit("for v in 'acxz': get(v)", 'from __main__ import x; get = x.get')
0.6585619449615479
so if speed matters, store a reference to the .get()
method (note the get = x.get
assignment).
Upvotes: 6
Reputation: 43457
What you have described can be said like this:
"y should be the value of key "v" if "v" exists in the dictionary, else it should be "none"
In Python, that is:
y = x.get(v, None)
Note: None
is already the default return value when the key is not present.
In your question, you also mention that sometimes your dictionaries contain references to methods. In this case, y
would then be the method if it is not None
and you can call it normally:
y(*args, **kwargs)
Or like in your example:
{'a': self.f1, 'b': self.f2, 'c': self.f3, 'd': self.f4}.get(v)()
Note: that if the key is not in the dictionary, then it will raise a TypeError
Upvotes: 2