EAFP

Peter Otten __peter__ at web.de
Mon May 16 06:05:14 EDT 2022


On 13/05/2022 18:37, bryangan41 wrote:
> Is the following LBYL:foo = 123if foo < 200:    do()If so, how to change to EAFP?Thanks!Sent from Samsung tablet.

The distinction between look-before-you-leap and
easier-to-ask-forgiveness-than-permission is weaker than yo might expect.

When you write

filename = ...
if exists(filename):
     with open(filename) as instream:
         # do stuff
else:
     # fallback

there are two checks for the file's existence, one explicit, and one
implicitly inside open() -- and worse, the first, explicit, check is
unreliable because between exists() and open() there is a small delay
that may be sufficient to create or delete the file. Therefore the
recommended (EAFP) version of the above is

filename = ...
try:
     with open(filename) as instrem:
         # do stuff
except FileNotFoundError
     # fallback

or just

with open(filename) as instream:
     # do stuff

if there is no meaningful fallback.

Regarding your example code, whether you can write an EAFP version for

if foo < 200:
     do()

depends on the contents of do(). If do() fails in a well-defined way,
let's say by raising a FooAbove199 exception you can write just

do()

or, if you need a fallback

try:
     do()
except FooAbove199:
     # fallback

Note that if you change do() from

do():
     # do stuff

to

def do():
     if foo < 200:
         # do stuff
     else:
         raise FooAbove199(f"Invalid {foo=!r}")

the

do()

invocation becomes EAFP even though you are actually performing the same
test as before.


More information about the Python-list mailing list