Which is the more efficient/faster/better way to check if a key exists?
if 'subject' in request.POST:
subject = request.POST['subject']
else:
// handle error
OR
try:
subject = request.POST['subject']
except KeyError:
// handle error
Check If Key Exists Using has_key() The has_key() method is a built-in method in Python that returns true if the dict contains the given key, and returns false if it isn't.
To simply check if a key exists in a Python dictionary you can use the in operator to search through the dictionary keys like this: pets = {'cats': 1, 'dogs': 2, 'fish': 3} if 'dogs' in pets: print('Dogs found!') # Dogs found! A dictionary can be a convenient data structure for counting the occurrence of items.
To check if a key-value pair exists in a dictionary, i.e., if a dictionary has/contains a pair, use the in operator and the items() method. Specify a tuple (key, value) . Use not in to check if a pair does not exist in a dictionary.
The latter (try/except
) form is generally the better form.
try
blocks are very cheap but catching an exception can be more expensive. A containment check on a dict tends to be cheap, but not cheaper than nothing. I suspect there will be a balance of efficiency depending on how often 'subject'
is really there. However, this doesn't matter, since premature optimization is useless, distracting, wasteful, and ineffective. You would go with the better solution.
If the code would actually be of the form
if 'subject' in request.POST: subject = request.POST['subject'] else: subject = some_default
then what you actually want is request.POST.get('subject', some_default)
.
I use .get() method — it is preferable method.
Python 2.5.2 (r252:60911, Jul 22 2009, 15:33:10) [GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu3)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import dis >>> def f1(key, d): ... if key in d: ... return d[key] ... else: ... return "default" ... >>> dis.dis(f1) 2 0 LOAD_FAST 0 (key) 3 LOAD_FAST 1 (d) 6 COMPARE_OP 6 (in) 9 JUMP_IF_FALSE 12 (to 24) 12 POP_TOP 3 13 LOAD_FAST 1 (d) 16 LOAD_FAST 0 (key) 19 BINARY_SUBSCR 20 RETURN_VALUE 21 JUMP_FORWARD 5 (to 29) >> 24 POP_TOP 5 25 LOAD_CONST 1 ('default') 28 RETURN_VALUE >> 29 LOAD_CONST 0 (None) 32 RETURN_VALUE >>> def f2(key, d): ... return d.get(key, "default") ... >>> dis.dis(f2) 2 0 LOAD_FAST 1 (d) 3 LOAD_ATTR 0 (get) 6 LOAD_FAST 0 (key) 9 LOAD_CONST 1 ('default') 12 CALL_FUNCTION 2 15 RETURN_VALUE >>> def f3(key, d): ... try: ... return d[key] ... except KeyError: ... return "default" ... >>> dis.dis(f3) 2 0 SETUP_EXCEPT 12 (to 15) 3 3 LOAD_FAST 1 (d) 6 LOAD_FAST 0 (key) 9 BINARY_SUBSCR 10 RETURN_VALUE 11 POP_BLOCK 12 JUMP_FORWARD 23 (to 38) 4 >> 15 DUP_TOP 16 LOAD_GLOBAL 0 (KeyError) 19 COMPARE_OP 10 (exception match) 22 JUMP_IF_FALSE 11 (to 36) 25 POP_TOP 26 POP_TOP 27 POP_TOP 28 POP_TOP 5 29 LOAD_CONST 1 ('default') 32 RETURN_VALUE 33 JUMP_FORWARD 2 (to 38) >> 36 POP_TOP 37 END_FINALLY >> 38 LOAD_CONST 0 (None) 41 RETURN_VALUE
Last time I checked, the first one is a few nanoseconds faster. But most phythonistas seem to favor the second one.
I think I'm not the only one that want to reserve exceptions for exceptional behavior, so I try to use the first one, reserving the second one when it's invalid not to have the key
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