Skip to main content
added 1526 characters in body
Source Link

The LBYL version is not necessarily as performant as the EAFP version, so saying that throwing exceptions is "expensive in terms of performance" is categorically false. It really depends on the type of strings you're processing:

In [33]: def lbyl(lines):
    ...:     for line in lines:
    ...:         if line.find(":") != -1:
    ...:             # Nuke the parens, do tuple unpacking like an idiomatic Python dev.
    ...:             role, lineSpoken = line.split(":",1)
    ...:             # no print, since output is obnoxiously long with %timeit
    ...:

In [34]: def eafp(lines):
    ...:     for line in lines:
    ...:         try:
    ...:             # Nuke the parens, do tuple unpacking like an idiomatic Python dev.
    ...:             role, lineSpoken = eachLine.split(":",1)
    ...:             # no print, since output is obnoxiously long with %timeit
    ...:         except:
    ...:             pass
    ...:

In [35]: lines = ["abc:def", "onetwothree", "xyz:hij"]

In [36]: %timeit lbyl(lines)
100000 loops, best of 3: 1.96 µs per loop

In [37]: %timeit eafp(lines)
100000 loops, best of 3: 4.02 µs per loop

In [38]: lines = ["a"*100000 + ":" + "b", "onetwothree", "abconetwothree"*100]

In [39]: %timeit lbyl(lines)
10000 loops, best of 3: 119 µs per loop

In [40]: %timeit eafp(lines)
100000 loops, best of 3: 4.2 µs per loop

The LBYL version is not necessarily as performant as the EAFP version, so saying that throwing exceptions is "expensive in terms of performance" is categorically false. It really depends on the type of strings you're processing:

In [33]: def lbyl(lines):
    ...:     for line in lines:
    ...:         if line.find(":") != -1:
    ...:             # Nuke the parens, do tuple unpacking like an idiomatic Python dev.
    ...:             role, lineSpoken = line.split(":",1)
    ...:             # no print, since output is obnoxiously long with %timeit
    ...:

In [34]: def eafp(lines):
    ...:     for line in lines:
    ...:         try:
    ...:             # Nuke the parens, do tuple unpacking like an idiomatic Python dev.
    ...:             role, lineSpoken = eachLine.split(":",1)
    ...:             # no print, since output is obnoxiously long with %timeit
    ...:         except:
    ...:             pass
    ...:

In [35]: lines = ["abc:def", "onetwothree", "xyz:hij"]

In [36]: %timeit lbyl(lines)
100000 loops, best of 3: 1.96 µs per loop

In [37]: %timeit eafp(lines)
100000 loops, best of 3: 4.02 µs per loop

In [38]: lines = ["a"*100000 + ":" + "b", "onetwothree", "abconetwothree"*100]

In [39]: %timeit lbyl(lines)
10000 loops, best of 3: 119 µs per loop

In [40]: %timeit eafp(lines)
100000 loops, best of 3: 4.2 µs per loop
added 107 characters in body
Source Link

TBH, it doesn't matter if you use the try/except mechanic or an if statement check. You commonly see both EAFP and LBYL in most Python baselines, with EAFP being slightly more common. Sometimes EAFP is much more readable/idiomatic, but in this particular case I think it's fine either way.

However...

I'd be careful using your current reference. A couple of glaring issues with their code:

  1. The file descriptor is leaked. Modern versions of CPython (a specific Python interpreter) will actually close it, since it's an anonymous object that's only in scope during the loop (gc will nuke it after the loop). However, other interpreters do not have this guarantee. They may leak the descriptor outright. You almost always want to use the with idiom when reading files in Python: there are very few exceptions. This isn't one of them.
  2. Pokemon exception handling is frowned upon as it masks errors (i.e. bare except statement that doesn't catch a specific exception)
  3. Nit: You don't need parens for tuple unpacking. Can just do role, lineSpoken = eachLine.split(":",1)

Ivc has a good answer about this and EAFP, but is also leaking the descriptor.

TBH, it doesn't matter if you use the try/except mechanic or an if statement check. You commonly see both EAFP and LBYL in most Python baselines, with EAFP being slightly more common. Sometimes EAFP is much more readable/idiomatic, but in this particular case I think it's fine either way.

However...

I'd be careful using your current reference. A couple of glaring issues with their code:

  1. The file descriptor is leaked. Modern versions of CPython (a specific Python interpreter) will actually close it, since it's an anonymous object that's only in scope during the loop (gc will nuke it after the loop). However, other interpreters do not have this guarantee. They may leak the descriptor outright. You almost always want to use the with idiom when reading files in Python: there are very few exceptions. This isn't one of them.
  2. Pokemon exception handling is frowned upon as it masks errors (i.e. bare except statement that doesn't catch a specific exception)

Ivc has a good answer about this and EAFP, but is also leaking the descriptor.

TBH, it doesn't matter if you use the try/except mechanic or an if statement check. You commonly see both EAFP and LBYL in most Python baselines, with EAFP being slightly more common. Sometimes EAFP is much more readable/idiomatic, but in this particular case I think it's fine either way.

However...

I'd be careful using your current reference. A couple of glaring issues with their code:

  1. The file descriptor is leaked. Modern versions of CPython (a specific Python interpreter) will actually close it, since it's an anonymous object that's only in scope during the loop (gc will nuke it after the loop). However, other interpreters do not have this guarantee. They may leak the descriptor outright. You almost always want to use the with idiom when reading files in Python: there are very few exceptions. This isn't one of them.
  2. Pokemon exception handling is frowned upon as it masks errors (i.e. bare except statement that doesn't catch a specific exception)
  3. Nit: You don't need parens for tuple unpacking. Can just do role, lineSpoken = eachLine.split(":",1)

Ivc has a good answer about this and EAFP, but is also leaking the descriptor.

Source Link

TBH, it doesn't matter if you use the try/except mechanic or an if statement check. You commonly see both EAFP and LBYL in most Python baselines, with EAFP being slightly more common. Sometimes EAFP is much more readable/idiomatic, but in this particular case I think it's fine either way.

However...

I'd be careful using your current reference. A couple of glaring issues with their code:

  1. The file descriptor is leaked. Modern versions of CPython (a specific Python interpreter) will actually close it, since it's an anonymous object that's only in scope during the loop (gc will nuke it after the loop). However, other interpreters do not have this guarantee. They may leak the descriptor outright. You almost always want to use the with idiom when reading files in Python: there are very few exceptions. This isn't one of them.
  2. Pokemon exception handling is frowned upon as it masks errors (i.e. bare except statement that doesn't catch a specific exception)

Ivc has a good answer about this and EAFP, but is also leaking the descriptor.