파이썬을 공부하다가 처음 알게 된 LBYL과 EAFP를 정리한다. 내용은 마리아노 아나야의 <파이썬 클린 코드>를 기반으로 한다.
LBYL: Look Before You Leap
코드를 실행하기 전에 오류 또는 예외를 미리 확인한 후 처리하는 방식이다. 보통 실행 전 조건문을 걸어서 오류 발생을 사전에 막고, 안정성을 향상시킨다.
EAFP: Easier to Ask for Forgiveness than Permission
코드 실행 과정에 오류 발생 과정을 고려하고, 발생하면 처리하는 방식이다. 실행 시점에 처리하기에 코드 간결성을 유지할 수 있다.
코드로 보면 아래와 같다. LBYL은 if문으로 key를 미리 확인한 후 진행하고, EAFP는 일단 진행하고 향후에 처리한다.
# LBYL:
if key in dic:
process(dic[key])
else:
process(None)
# As an expression:
process(dic[key] if key in dic else None)
# EAFP:
try:
process(dic[key])
except KeyError:
process(None)
# As an expression:
process(dic[key] except KeyError: None)
책에 따르면 파이썬은 LBYL보다 EAFP 방식을 선호한다. dict.get(key, None)와 같은 함수를 지원하는 것이 일례이다.
관련 링크: https://peps.python.org/pep-0463/
여기까지 왔을 때 내 동년배 고연차 개발자들(모두 Java 출신)에게 물어봤을 때는 EAFP방식은 듣도 보도 못했다는 대답이 돌아왔다. 나를 포함하여 모두 LBYL을 디폴트로 깔고 있었던 것이다.

구글에 검색하면 모두들 파이썬을 주제로 두고 있다. 사실상 다른 언어에서는 크게 신경쓰지 않는 요소로 보인다.
이중 스택 오버플로에 흥미로운 주제가 있다: LBYL vs EAFP in Java
질문자도 Java 또는 C++에서는 EAFP 방식을 들어본 적이 없다고 한다. EAFP는 예외 오버헤드가 많을 것 같은데, 왜 EAFP를 선호하는지 잘 모르겠다는 것이 질문이다.
사람들의 논의가 이어지는데, 결론은 언어적 특성으로 보인다.
Python의 언어 특성상 조건절 검사보다 예외 처리가 비용면에서 효과적이라고 한다. Python, JavaScript와 같은 동적 타입 언어는 변수 타입을 실행 시점에 검사하기 때문에 실행 시점에 오류를 처리하여 간결성을 유지하는 것이 보편적이라는 것이다.
반대로 Java, C++은 정적 타입 언어로 런타임 시점에 이미 변수 타입을 알고 있고, 오류를 사전에 검출하여 코드 안정성을 높이는 LBYL 형식이 좋다고 한다.
마찬가지로 이는 개발 문화에도 깊숙히 들어있기에 안정성을 중요시하는 Java, C++ 개발자들은 LBYL을 선호하고, Python, JavaScript 개발자들은 속도를 중요시하기에 EAFP를 선호하는 경향이 있다고 한다.
경향일 뿐이며 상황에 따라 LBYL이 효과적일 수도 있고, EAFP가 효과적일 수도 있다.
가장 마음에 드는 결론을 가져왔다.
More to the point: The if vs. except debate doesn't matter.
Since exceptions are cheap, do not label them as a performance problem.
Use what makes your code clear and meaningful. Don't waste time on micro-optimizations like this.