Using 'try' vs. 'if' in Python
You often hear that Python encourages EAFP style ("it's easier to ask for forgiveness than permission") over LBYL style ("look before you leap"). To me, it's a matter of efficiency and readability.
In your example (say that instead of returning a list or an empty string, the function were to return a list or None
), if you expect that 99 % of the time result
will actually contain something iterable, I'd use the try/except
approach. It will be faster if exceptions really are exceptional. If result
is None
more than 50 % of the time, then using if
is probably better.
To support this with a few measurements:
>>> import timeit
>>> timeit.timeit(setup="a=1;b=1", stmt="a/b") # no error checking
0.06379691968322732
>>> timeit.timeit(setup="a=1;b=1", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.0829463709378615
>>> timeit.timeit(setup="a=1;b=0", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.5070195056614466
>>> timeit.timeit(setup="a=1;b=1", stmt="if b!=0:\n a/b")
0.11940114974277094
>>> timeit.timeit(setup="a=1;b=0", stmt="if b!=0:\n a/b")
0.051202772912802175
So, whereas an if
statement always costs you, it's nearly free to set up a try/except
block. But when an Exception
actually occurs, the cost is much higher.
Moral:
- It's perfectly OK (and "pythonic") to use
try/except
for flow control, - but it makes sense most when
Exception
s are actually exceptional.
From the Python docs:
EAFP
Easier to ask for forgiveness than
permission. This common Python coding
style assumes the existence of valid
keys or attributes and catches
exceptions if the assumption proves
false. This clean and fast style is
characterized by the presence of many
try
andexcept
statements. The
technique contrasts with the LBYL
style common to many other languages
such as C.
Difference between try and if
I believe you're asking about the paradigm "Easier to ask for forgiveness than for permission" which is sometimes quoted as a Python guideline.
In this context try / except
corresponds to trying and asking for forgiveness, while if
corresponds to asking for permission then trying.
Have a look: http://docs.python.org/glossary.html#term-eafp
When do we need to use try, except in python? Is it similar to if, else ?
The try
and except
blocks are used to catch and handle exceptions. The program will first run the try
statement "normally". If there are any exceptions that trigger in the try statement, the except statement will trigger. For example,
try:
print(str) #Here, str isn't defined and you will get an exception which triggers the except statement
except NameError: #Here, you specify which exception you think might happen
#Do something
You can have as many exception blocks as you want! Also note that if you catch an exception the other ones will not trigger. Also note that an exception block with no arguments will catch all exceptions.
The finally block can be added on and triggers even if there was an exception or not. This can be helpful for closing and cleaning objects. Another example,
try:
#stuff
except:
#stuff if exception
finally:
#do stuff even if there is or is not an exception
I should also mention the pass
function. You should use it if you want to ignore exceptions. Example,
try:
#stuff
except:
pass #i don't want to do anything
Hope I helped!
Better to 'try' something and catch the exception or test if it's possible first to avoid an exception?
You should prefer try/except
over if/else
if that results in
- speed-ups (for example by preventing extra lookups)
- cleaner code (fewer lines/easier to read)
Often, these go hand-in-hand.
speed-ups
In the case of trying to find an element in a long list by:
try:
x = my_list[index]
except IndexError:
x = 'NO_ABC'
the try, except is the best option when the index
is probably in the list and the IndexError is usually not raised. This way you avoid the need for an extra lookup by if index < len(my_list)
.
Python encourages the use of exceptions, which you handle is a phrase from Dive Into Python. Your example not only handles the exception (gracefully), rather than letting it silently pass, also the exception occurs only in the exceptional case of index not being found (hence the word exception!).
cleaner code
The official Python Documentation mentions EAFP: Easier to ask for forgiveness than permission and Rob Knight notes that catching errors rather than avoiding them, can result in cleaner, easier to read code. His example says it like this:
Worse (LBYL 'look before you leap'):
#check whether int conversion will raise an error
if not isinstance(s, str) or not s.isdigit():
return None
elif len(s) > 10: #too many digits for int conversion
return None
else:
return int(s)
Better (EAFP: Easier to ask for forgiveness than permission):
try:
return int(s)
except (TypeError, ValueError, OverflowError): #int conversion failed
return None
Why `try ... except` is faster than `if`?
The additional runtime comes from the .keys()
call. If you want to prevent that extra call and still stay with if
and else
, try something like this:
obj = d.get(key)
if obj:
obj.append(element)
else:
d[key] = [element]
Alternatively you can use a defaultdict
which does this in the background. Example:
from collections import defaultdict
d = defaultdict(list)
d['123'].append('abc')
can i combine if else and with try catch python?
You can raise an exception if the function returns False, by doing:
s = '127.0.0.0'
def validate(a):
a = a.split('.')
if len(a) !=4:
return False
for x in a :
if not x.isdigit():
return False
i = int(x)
if i < 0 or i > 255 :
return False
return True
try:
if not validate(s): #ip validation
raise TypeError
except TypeError:
print("insert you're ip correctly")
Note: you probably want to return True
for the end, since I believe that's when the function validates successfully, and a = a.split('.')
not s.split
, or else you're splitting the global variable s
.
Tip: when using try...except, try to catch a specific error than to use the catch-all except:
.
Python: try-except vs if-else to check dict keys
Exception handling is generally much slower than an if statement. With the presence of nested dictionaries, it is easy to see why the author used an exception statement. However, the following would work also.
var = mydict.get(a,{}).get(b,None)
if var is None:
print("Not found")
else:
print("Found: " + str(var))
The use of get
on the dict
object returns a default value when the key is not present.
Python if vs try-except
You're setting alist only once. The first call to "tryway" clears it, then every successive call does nothing.
def tryway():
alist = range(1000)
try:
while True:
alist.pop()
except IndexError:
pass
def ifway():
alist = range(1000)
while True:
if alist == []:
break
else:
alist.pop()
if __name__=='__main__':
from timeit import Timer
print "Testing Try"
tr = Timer("tryway()","from __main__ import tryway")
print tr.timeit(10000)
print "Testing If"
ir = Timer("ifway()","from __main__ import ifway")
print ir.timeit(10000)
>>> Testing Try
>>> 2.09539294243
>>> Testing If
>>> 2.84440898895
Related Topics
How to Return Dictionary Keys as a List in Python
How to Redirect 'Print' Output to a File
How to Make Firefox Headless Programmatically in Selenium with Python
Typeerror: Unsupported Operand Type(S) for -: 'Str' and 'Int'
Why Does Adding a Trailing Comma After a Variable Name Make It a Tuple
Python: Removing List Element While Iterating Over List
Converting a Pandas Groupby Output from Series to Dataframe
Generate Random Integers Between 0 and 9
How to Run Multiple Python Versions on Windows
How to Urlencode a Querystring in Python
How to Get List of Values from Dict
How to Limit Execution Time of a Function Call
Matplotlib: How to Create Axessubplot Objects, Then Add Them to a Figure Instance