What is meant by "using the EAFP principle" in Python? Could you provide any examples?
From the glossary:
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.
An example would be an attempt to access a dictionary key.
EAFP:
try:
x = my_dict["key"]
except KeyError:
# handle missing key
LBYL:
if "key" in my_dict:
x = my_dict["key"]
else:
# handle missing key
The LBYL version has to search the key inside the dictionary twice, and might also be considered slightly less readable.
x
when the key doesn't exist: x = mydict.get('key')
will return None
if 'key'
is not in my_dict
; you could also do .get('key', <something>)
, and then x will be assigned that something if the key isn't in the dictionary. dict.setdefault()
and collections.defaultdict
are nice things for avoiding excess code as well. –
Nadabb except KeyError
as well as AttributeError
are simple but some of the worst examples. So many times I was stuck debugging something because except AttributeError
was put in wrong place, which end up catching wrong attribute error raised deeper down in the chain. Better examples I think are: try: open() ... except: IOError
. Or try: parseLine() ... except ParseError
–
Subgroup except Exception
to catch any problem that might occur, but it's much better to catch errors explicitly. (Note that this example includes an explicit exception statement.) –
Parliamentarian I'll try to explain it with another example.
Here we're trying to access the file and print the contents in console.
LBYL - Look Before You Leap :
We might want to check if we can access the file and if we can, we'll open it and print the contents. If we can't access the file we'll hit the else
part. The reason that this is a race condition is because we first make an access-check. By the time we reach with open(my_file) as f:
maybe we can't access it anymore due to some permission issues (for example another process gains an exclusive file lock). This code will likely throw an error and we won't be able to catch that error because we thought that we could access the file.
import os
my_file = "/path/to/my/file.txt"
# Race condition
if os.access(my_file, os.R_OK):
with open(my_file) as f:
print(f.read())
else:
print("File can't be accessed")
EAFP - Easier to Ask for Forgiveness than Permission :
In this example, we're just trying to open the file and if we can't open it, it'll throw an IOError
. If we can, we'll open the file and print the contents. So instead of asking something we're trying to do it. If it works, great! If it doesn't we catch the error and handle it.
# # No race condition
try:
f = open(my_file)
except IOError as e:
print("File can't be accessed")
else:
with f:
print(f.read())
try, except
blocks, correct? –
Waldron else
block is completely unnecessary - that code should have been part of the try
block instead. –
Colorblind I call it "optimistic programming". The idea is that most times people will do the right thing, and errors should be few. So code first for the "right thing" to happen, and then catch the errors if they don't.
My feeling is that if a user is going to be making mistakes, they should be the one to suffer the time consequences. People who use the tool the right way are sped through.
To add @sven-marnach
to answer,
You could use:
dict[“key”] = dict.get(“key”, None)
This is better than the search twice issue he mentions for doing LBYL.
© 2022 - 2024 — McMap. All rights reserved.