파코기(파이썬 코딩의 기술) 책을 읽다가 Better way 16에서 내가 알고 있던 것과 다른 내용이 나와서 글을 쓴다.
😵💫 발단
counter 딕셔너리의 값을 증가시키는 코드를 짜려고 한다. 아래 두 후보 중 어느 것이 맞을까?
# 1번 후보, counter[key]에 +1을 하기 전에 key가 있는지 확인하고 간다.
if key in counter:
counter[key] = 0
else:
counter[key] += 1
# 2번 후보, counter[key]에 +1을 하고 없다고 에러가 뜨면 예외를 처리한다.
try:
counter[key] += 1
except KeyError:
counter[key] = 1
이 책을 보기 전의 나는 "당연히 1번이지! 예외는 말이야~ 원래 오래 걸린다~~ 이 말이야!" 라며 으스댔을 것이다.
하지만 파코기 책에선 2번 후보가 if문 하나가 없다는 이유로 더 좋다고 하는 것이다.
🤔 이유 찾기
분명히 성능상의 차이가 있을 듯한데? 싶어 찾아보았다.
분명 예외는 일반 상황보다 10배 정도 더 비싸다.
참고: https://stackoverflow.com/questions/2522005/cost-of-exception-handlers-in-python
a = 0
try:
b = 10/a
except ZeroDivisionError:
pass
0.27 usec/pass
a = 0
if a:
b = 10/a
0.02 usec/pass
그래도 예외가 터지지만 않는다면 좀 더 빠른 것 같다.
try except 비용이 제로 코스트 라고 한다.
참고: https://docs.python.org/3.11/whatsnew/3.11.html#optimizations
“Zero-cost” exceptions are implemented. The cost of try statements is almost eliminated when no exception is raised. (Contributed by Mark Shannon in bpo-40222.)
다들 "파이썬의 예외는 싸요~ 어디가서 이 가격 주고 못사~"라고 해서 "다른 언어 보고 올게요" 하고 Java의 경우를 찾아보았다.
1000만 번 호출했을 때, 예외 있음: 20891ms, 예외 없음: 62ms로 300배 정도 차이를 보인다.
참고: https://stackoverflow.com/questions/567579/how-expensive-are-exceptions
물론, 이 두 경우를 보고 단언하긴 어렵지만 파이썬에서는 이런 방식이 선호되는 것 같다.
다음은 파이썬 용어집에서 볼 수 있는 글이다.
다른 언어에선 "돌다리도 두들겨 봐라"라는 원칙을 적용하지만 파이썬은 "허락보다 용서를 구하는 게 쉽다" 원칙을 고수한다고 한다.
그래서 try except문을 많이 쓰는거라고..
EAFP
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 and except statements. The technique contrasts with the LBYL style common to many other languages such as C.
참고: https://docs.python.org/3.11/glossary.html?highlight=forgiveness%20than%20permission#term-EAFP
👏 결론
파이썬 코드 리뷰하면서 젭알 try except를 쓰지 말라고 깨스라이팅한 나를 반성하자
'프로그래밍 > 파이썬' 카테고리의 다른 글
[Async-SQLModel] SQLModel서 비동기 프로그래밍시 발생하는 문제의 대안 (1) | 2024.04.03 |
---|---|
MongoDB의 Date와 python의 datetime (1) | 2023.08.10 |