EAFP vs LBYL Interview Questions & Answers

5 questions Updated 2026-06-18

Python interview questions on EAFP vs LBYL, why try/except is preferred, the race conditions LBYL invites, and dict.get versus checking for a key.

EAFP = "Easier to Ask Forgiveness than Permission": just attempt the operation and handle the exception if it fails. LBYL = "Look Before You Leap": check the preconditions first, then act only if the checks pass. They are two styles for handling things that might go wrong.

# LBYL — check first
if "key" in config:
    value = config["key"]

# EAFP — try and handle failure
try:
    value = config["key"]
except KeyError:
    value = default

EAFP is the Pythonic default — it reads naturally and avoids redundant checks. Rule of thumb: in Python, try the operation and catch the specific exception rather than pre-validating every condition.

EAFP fits Python's design: exceptions are cheap and idiomatic, and the style avoids duplicating logic. With LBYL you often check a condition and then perform the same lookup/operation again, doing the work twice. EAFP also stays correct when an object merely behaves like the expected type (duck typing) rather than passing an explicit type check.

# LBYL duplicates the access and breaks on duck-typed objects
if hasattr(obj, "read") and callable(obj.read):
    data = obj.read()

# EAFP — just use it; let the exception surface real problems
try:
    data = obj.read()
except AttributeError:
    data = None

The happy path stays uncluttered and the error handling is explicit. Rule of thumb: write the common case as straight-line code and catch the specific exception for the rare failure.

LBYL introduces a TOCTOU bug — "Time Of Check to Time Of Use". Between the moment you check a condition and the moment you act on it, another thread or process can change the state, so the check is stale and the action fails or corrupts data. EAFP avoids the gap by acting atomically and handling failure.

import os
# LBYL — file can be deleted between the check and the open (race!)
if os.path.exists(path):
    with open(path) as f:    # may still raise FileNotFoundError
        data = f.read()

# EAFP — no window; the open either works or raises
try:
    with open(path) as f:
        data = f.read()
except FileNotFoundError:
    data = None

The check-then-act pattern is unsafe in concurrent or filesystem contexts. Rule of thumb: for files, sockets, and shared state, attempt the operation and handle the exception rather than checking first.

dict.get(key, default) returns the value if present and the default (None if unspecified) otherwise — a clean one-liner that avoids both the if key in d check and a try/except KeyError. Use a membership check or try/except only when you must distinguish a missing key from a stored None, or run different logic in each branch.

counts = {"a": 1}
counts.get("b")          # None — no KeyError
counts.get("b", 0)       # 0    — supply a default

# need to tell "missing" from "stored None"? then check explicitly
if "b" in counts:
    ...
# or accumulate with setdefault / defaultdict
counts.setdefault("c", 0)

For counting/grouping, collections.defaultdict or Counter is even cleaner. Rule of thumb: reach for .get() with a default for "value or fallback", and only branch explicitly when missing-ness itself is meaningful.

EAFP done carelessly causes two problems. First, a too-broad except (bare except: or except Exception) can swallow unrelated bugs — catching a KeyError you didn't intend, or hiding a NameError. Second, the try block should wrap only the line that can fail, so you don't accidentally catch exceptions from surrounding code.

# Bad — hides real errors and over-wide try block
try:
    value = config["key"]
    result = expensive_call(value)   # its errors get caught too!
except Exception:
    value = default

# Good — narrow exception, minimal try body
try:
    value = config["key"]
except KeyError:
    value = default
result = expensive_call(value)       # outside the try

Always catch the most specific exception and keep the try body small. Rule of thumb: EAFP means "catch the one expected failure", never "catch everything and hope".

Practice tests are coming soon

Get notified when interactive mock interviews and quizzes launch.