I was wondering, whether the following style is a common practice to avoid key not found in a dictionary?
# default is 0
value = my_dic[100] if 100 in my_dic else 0
value = my_dic.get(100, 0)
If you need the "default value" everywhere, consider defaultdict as a possible alternative. (A factory/callback approach offers a good bit of flexibility with the "default value".)
Happy coding.
If you try to access a key that is not in the dictionary, python will raise an exception that will crash your program. Instead of this, you should "catch" the exception and do something more graceful.
it's better practice to catch the exception:
try:
value = my_dic[100]
except KeyError:
print("key not found in dictionary") #or handle the error more elegantly
I haven't read the article, but you can learn more here:
http://en.wikipedia.org/wiki/Exception_handling
It is valid python syntax, however I would say that according to Python Coding Style Guidelines You should structure your if else statements like so,
if <condition>:
<statements>
else:
<statements>
first_name = params.get('first_name', None)
if first_name:
profile.first_name = first_name
Related
I am receiving from an API a dictionary, but the problem is that sometimes I get {value: test} and others {key: test}. I am using a try/except block to take the one set:
try:
var = received_dict['value']
except KeyError:
var = received_dict['key']
Is there a better way to do that in Python 3?
received_dict.get('value', received_dict.get('key', False))
This will still throw an error if neither key is present which is almost certainly the desired behavior.
received_dict.get('value', received_dict['key'])
However, python generally uses the: Easier to ask for forgiveness than permission mentality. If one of those occurs more frequently than the other how you're currently doing it may be best. If it really is 50/50 however using a get might be a cleaner way to go.
https://docs.python.org/3.4/glossary.html (See EAFP)
To be honest your approach seems good. If you want a bit more control over the different cases you can do this:
vars = [received_dict[key] for key in ["value","key"] if key in received_dict.keys()]
if not vars:
raise KeyError("No 'value' or 'key' keys exist in dictionary")
elif len(vars)==2:
raise KeyError("Both 'value' and 'key' keys exist in dictionary")
else:
var=vars[0]
The only advantage of this approach is that it throws an error also when both keys exist. If you don't care about the "both exist" error case and you don't mind a different type of error being raised when the "none exist" error case happens, then you can do the code below to have a one liner:
var = [received_dict[key] for key in ["value","key"] if key in received_dict.keys()][0]
If an associative array exists in Python3, is it a waste to check if an element of it exists rather than just using it?
Should you:
if 'name' in array and not array['name'].startswith('something'):
Or should you just:
if not array['name'].startswith('something'):
... And will Python3 handle it "for" you?
You can do -
if not array.get('name', 'something').startswith('something'):
get() function returns the second value by default if the key ( name ) is not found.
So in above case , this would return something , if key is not found in the dictionary, and because of the .startwith() and the not , the complete conditional expression would evaluate to False , as it would be doing in OP's first example .
The answer really depends on where does your array come from. Also on what can you do as a result of the check.
For example if it comes from the user, then yes, you definitely should check if name exists, so that you can respond with a better error message than some big stacktrace.... KeyError: "name".
If it's an internal structure you created and it's not exposed for user modifications, or if it's exposed via API but the expectation is that nobody should touch it, then don't bother checking. If it's missing, then it's an internal exception the developers should see and fix.
Of course there may be a situation where you don't really care if it was provided or not, because you have a reasonable fallback. Then a default value like in Anand's answer is a good solution too. array.get('name', some_default)
Python won't handle it for you. You'll have to do some work in both cases. Try to write code that makes sense to you later, because you'll write it once and read it (and maintain it) many times over.
You can do it two ways, pick the one that makes the most sense to you:
obj = array.get('name')
if obj and not obj.startswith('something'):
pass
In your second option, you'll have to catch the exception:
try:
if not array['name'].startswith('something'):
pass
except KeyError:
print('name does not exist in array')
Just do ...
if not array.get('name',"").startswith('something')
If name exists then it returns array['name'] else it will return empty string .
TLDR summary
I wrote a function navigateDict that does a safe navigation on a dict, similar to dict.get() but nested. It replaces code like
if 1 in data and 'i' in data[1] and 'a' in data[1]['i']:
print data[1]['i']['a']
else:
print "Not found"
with the roughly equivalent
found = navigateDict(data, 1, 'i', 'a')
if found is not None:
print found
else:
print "Not found"
Is anything similar to this already part of the standard library?
Is there a more idiomatic way to do the same thing?
Any response that requires typing any path component key more than once is probably a non-answer.
Additional details
The implementation is as follows:
# Allow fallback value other than None
def navigateDictEx(d, keys, fallback=None):
for key in keys:
if key in d:
d = d[key]
else:
return fallback
return d
def navigateDict(d, *keys):
return navigateDictEx(d, keys)
See the summary for example usage.
Pythonic or not, this function reduces repetition in a place where redundancy is a bad idea. For example, changing one path component in the example requires up to three distinct values to be modified as one in the original example, but only one in the modified example. Given my regular tendency to err, this is a big win.
Ultimately I'm asking this: Is there something in the standard library that does this, or am I going to need to find a place for it in my project's library?
If hits are expected to dominate misses
brionius correctly points out that catching KeyError will work:
try:
print data[1]['i']['a']
except KeyError:
print "Not found"
This might be the way I go; it's pretty terse and cuts the repetition. However, it does reflect an assumption that there will be more hits than misses. If there's a better way of assuming the opposite I'd like to know that, also.
One way to do this is as follows:
try:
print data[1]['i']['a']
except KeyError:
print "Not found!"
It's in line with the spirit of duck-typing. It may or may not be as fast, as I believe handling exceptions carries a certain amount of overhead, but it's certainly "safe".
a solution like this is cool
https://twitter.com/raymondh/status/343823801278140417
>>> from collections import defaultdict
>>> infinite_defaultdict = lambda: defaultdict(infinite_defaultdict)
>>> d = infinite_defaultdict()
>>> d['x']['y']['z'] = 10
>>> if d['x']['y']['z']: print d['x']['y']['z'] #better reflects that misses are common
Years late to the game, but for anyone stumbling upon this, there still does not seem to be a native, fluent way to safely navigate a Python dict.
Enter RestResponse:
"RestResponse aims to be a fluent python object for interfacing with RESTful JSON APIs"
This library includes a NoneProp object that allows for safely navigating (and building) JSON data structures.
>>> import RestResponse
>>> data = RestResponse.parse({})
>>> data.property.is_none
None
>>> bool(data.property.is_none)
False
>>> isinstance(data.property.is_none, RestResponse.NoneProp)
True
>>> data.property.is_none = None
>>> isinstance(data.property.is_none, RestResponse.NoneProp)
False
>>> print data.pretty_print()
{
"property": {
"is_none": null
}
}
I was just looking at the Python FAQ because it was mentioned in another question. Having never really looked at it in detail before, I came across this question: “How fast are exceptions?”:
A try/except block is extremely efficient. Actually catching an exception is expensive. In versions of Python prior to 2.0 it was common to use this idiom:
try:
value = mydict[key]
except KeyError:
mydict[key] = getvalue(key)
value = mydict[key]
I was a little bit surprised about the “catching an exception is expensive” part. Is this referring only to those except cases where you actually save the exception in a variable, or generally all excepts (including the one in the example above)?
I’ve always thought that using such idioms as shown would be very pythonic, especially as in Python “it is Easier to Ask Forgiveness than it is to get Permission”. Also many answers on SO generally follow this idea.
Is the performance for catching Exceptions really that bad? Should one rather follow LBYL (“Look before you leap”) in such cases?
(Note that I’m not directly talking about the example from the FAQ; there are many other examples where you just look out for an exception instead of checking the types before.)
Catching exceptions is expensive, but exceptions should be exceptional (read, not happen very often). If exceptions are rare, try/catch is faster than LBYL.
The following example times a dictionary key lookup using exceptions and LBYL when the key exists and when it doesn't exist:
import timeit
s = []
s.append('''\
try:
x = D['key']
except KeyError:
x = None
''')
s.append('''\
x = D['key'] if 'key' in D else None
''')
s.append('''\
try:
x = D['xxx']
except KeyError:
x = None
''')
s.append('''\
x = D['xxx'] if 'xxx' in D else None
''')
for i,c in enumerate(s,1):
t = timeit.Timer(c,"D={'key':'value'}")
print('Run',i,'=',min(t.repeat()))
Output
Run 1 = 0.05600167960596991 # try/catch, key exists
Run 2 = 0.08530091918578364 # LBYL, key exists (slower)
Run 3 = 0.3486251291120652 # try/catch, key doesn't exist (MUCH slower)
Run 4 = 0.050621117060586585 # LBYL, key doesn't exist
When the usual case is no exception, try/catch is "extremely efficient" when compared to LBYL.
The cost depends on implementation, obviously, but I wouldn't worry about it. It's unlikely going to matter, anyway. Standard protocols raise exceptions in strangest of places (think StopIteration), so you're surrounded with raising and catching whether you like it or not.
When choosing between LBYL and EAFP, worry about readability of the code, instead of focusing on micro-optimisations. I'd avoid type-checking if possible, as it might reduce the generality of the code.
If the case where the key is not found is more than exceptional, I would suggest using the 'get' method, which provide a constant speed in all cases :
s.append('''\
x = D.get('key', None)
''')
s.append('''\
x = D.get('xxx', None)
''')
If function returns a two value list or tuple on success or False on failure, how can I best unpack the return list into two variables while also checking for False?
def get_key_value():
if (cond != True):
return False
return [val1, val2]
# Call it
# How can I also check for False while unpacking?
key, value = get_key_value()
Coverting #Felix Kling's great comment into an answer.
If not being able to find a (key, value) pair indicates some kind of system failure, it would be better to throw an exception. If your failure doesn't really fall into any of the standard exceptions, you should build a new exception type of your own.
The cond != True is better written as not cond. Also it's better to not create a list if it's not necessary.
class DataNotFound(Exception): pass
def get_key_value():
if not cond:
raise DataNotFound("Couldn't find it!")
return val1, val2
try:
key,value = get_key_value()
except DataNotFound:
#handle the failure somehow
key, value = 'ERROR', 'ERROR'
This falls under the "Easier to Ask for Forgiveness than Permission" policy of Python. I avoid catching TypeError in your function, in case there's some other unforeseen problem.
data = get_key_value()
try:
key, value = data
except TypeError:
#handle the failure somehow
key, value = 'ERROR', 'ERROR'
I don't think there is an idiomatic way to do this -- not least because a function that behaves that way is itself unidiomatic. If you have to do it, I suggest you simply make use of the fact that your 2-element list or tuple is a "truthy" rather than a "falsy" value (this isn't Python terminology but it's useful):
pair_or_false = get_key_value()
if pair:
key,value = val
else:
# handle failure in whatever way
The obvious alternative is to treat the not-found case as an exception:
try:
key,value = get_key_value()
except TypeError:
# deal with not-found case
but if there's any possibility at all that something other than the unsuccessful unpacking could raise a TypeError then you run the risk of masking a genuine error that way.
You're running into problems because you're mixing return types. Just because you can doesn't mean you should.
Although I agree with the others here that an exception is one appropriate way to go, it may depend on whether you expect to find a valid key & value most of the time. If so, use an exception (something like KeyError) to indicate that the function failed. But if you expect it to fail at a high rate, you may not want the exception overhead. In that case, return something like [None, None] from get_key_value and then your calling code would look like:
key, value = get_key_value()
if key:
# take action
else:
# handle the error appropriately