파이썬의 트루시니스 개념과 단락 평가를 완전히 이해하고 None의 올바른 활용법을 배운다.
🎯 이 강의에서 배우는 것
파이썬에서 if something:을 쓸 때, "something"은 True나 False가 아니어도 됩니다. 빈 리스트, 0, 빈 문자열도 거짓으로 평가됩니다. 이 개념을 트루시니스(truthiness)라고 합니다. 이 강의에서는 파이썬의 진리값 시스템 전체를 이해하고, 단락 평가(short-circuit evaluation)를 활용해 더 파이썬다운 코드를 작성합니다.
🧬 bool은 int의 서브클래스
# bool은 int를 상속한다
print(isinstance(True, int)) # True
print(isinstance(False, int)) # True
# True = 1, False = 0
print(True + True) # 2
print(True * 10) # 10
print(False + 5) # 5
# 이것이 가능한 이유: bool이 int의 서브클래스
# True는 정수 1과 값이 같지만 타입은 다름
print(True == 1) # True (값 비교)
print(True is 1) # False (다른 객체)
print(type(True)) # <class 'bool'>
print(type(1)) # <class 'int'>
# 리스트에서 True/False 카운팅 트릭
results = [True, False, True, True, False, True]
print(sum(results)) # 4 (True의 개수)
print(sum(not x for x in results)) # 2 (False의 개수)
왜 bool을 int의 서브클래스로 설계했을까요? 하위 호환성(backward compatibility)과 수학적 일관성 때문입니다. 불리언 값을 수치 연산에 그대로 사용할 수 있어 코드가 간결해집니다.
🌊 트루시니스 — 모든 객체의 진리값
파이썬에서 거짓(falsy)으로 평가되는 값들:
falsy_values = [
False, # 불리언 False
None, # None
0, # 정수 0
0.0, # 부동소수점 0
0j, # 복소수 0
"", # 빈 문자열
[], # 빈 리스트
(), # 빈 튜플
{}, # 빈 딕셔너리
set(), # 빈 셋
b"", # 빈 bytes
]
for v in falsy_values:
print(f"bool({repr(v):15}) = {bool(v)}")
그 외 모든 것은 참(truthy)입니다. 0이 아닌 숫자, 비어있지 않은 컨테이너, 함수 객체, 클래스 객체, 커스텀 객체(기본적으로 True) 등.
# 트루시니스를 활용한 파이썬다운 코드
items = []
# 비-파이썬적 (불필요하게 명시적)
if len(items) == 0:
print("비어있음")
# 파이썬적 (트루시니스 활용)
if not items:
print("비어있음")
# 값이 있을 때만 처리
if items:
process(items)
하지만 주의가 필요한 경우도 있습니다:
def get_count():
return 0 # 유효한 값이지만 falsy
count = get_count()
if count: # 0은 거짓 — 의도와 달리 실행 안 됨!
print(f"카운트: {count}")
# 올바른 방법: None을 명시적으로 비교
if count is not None: # 0도 유효한 값으로 처리
print(f"카운트: {count}")
🔗 단락 평가 — and, or의 숨겨진 동작
파이썬의 and와 or는 bool을 반환하지 않습니다. 원래 값을 반환합니다. 이것이 단락 평가(short-circuit evaluation)의 핵심입니다:
# and: 첫 번째 거짓값을 반환, 없으면 마지막 값 반환
print(1 and 2) # 2 (1은 참이므로 2까지 평가)
print(0 and 2) # 0 (0이 거짓이므로 즉시 반환)
print(1 and 2 and 3) # 3 (모두 참이면 마지막 값)
print("" and "hello") # "" (빈 문자열이 거짓이므로 즉시 반환)
# or: 첫 번째 참값을 반환, 없으면 마지막 값 반환
print(1 or 2) # 1 (1이 참이므로 즉시 반환)
print(0 or 2) # 2 (0이 거짓이므로 2 평가)
print(0 or "" or "hello") # "hello" (앞의 거짓값들 건너뜀)
print(0 or None) # None (모두 거짓이면 마지막 값)
단락 평가의 실용적인 활용:
# 1. 기본값 패턴 (or)
def greet(name=None):
display_name = name or "손님" # name이 None이나 ""면 "손님" 사용
print(f"안녕하세요, {display_name}님!")
greet("홍길동") # 안녕하세요, 홍길동님!
greet() # 안녕하세요, 손님님!
# 단, 0이나 False가 유효한 값이면 or 대신 명시적 None 체크를 써야 함
def safe_divide(a, b=None):
divisor = b if b is not None else 1 # 0도 유효한 divisor로 처리
# 2. 조건부 실행 (and)
user = {"name": "홍길동", "email": "hong@example.com"}
email = user.get("email")
email and send_notification(email) # email이 있을 때만 실행
# if email: send_notification(email) 와 동일
# 3. 예외 방지
lst = [1, 2, 3]
value = lst and lst[0] # lst가 비어있으면 [] 반환, 있으면 lst[0]
# 4. 단락 평가로 예외 방지
def expensive_check():
print("비싼 연산 실행")
return True
fast_condition = False
result = fast_condition and expensive_check() # expensive_check() 호출 안 됨!
print(result) # False
🚫 None — 싱글턴 객체
print(None) # None
print(type(None)) # <class 'NoneType'>
# None은 싱글턴 — 파이썬 프로세스에 하나만 존재
a = None
b = None
print(a is b) # True — 항상 같은 객체
# None 확인은 is로 (== 아님)
x = None
print(x is None) # True — 권장
print(x is not None) # False — 권장
print(x == None) # True — 작동하지만 관례에 어긋남
# None을 반환하는 두 가지 경우
def func_with_return():
return None # 명시적 None 반환
def func_without_return():
pass # return 없음 — 자동으로 None 반환
print(func_with_return()) # None
print(func_without_return()) # None
print(func_with_return() is func_without_return()) # True
# None vs False vs 0 vs "" — 각각의 의미
result_none = None # "아직 처리 안 됨" 또는 "해당 없음"
result_false = False # "아니오" (불리언 결과)
result_zero = 0 # "0개" (수량)
result_empty = "" # "빈 텍스트" (텍스트가 있지만 비어있음)
🔀 비교 연산자와 체인 비교
# 비교 연산자는 항상 bool 반환
print(3 > 2) # True
print(type(3 > 2)) # <class 'bool'>
# 체인 비교 (파이썬 고유 기능)
x = 5
print(1 < x < 10) # True — 수학적 부등식과 동일
print(1 < x and x < 10) # True — 위와 동일하지만 x를 두 번 평가
# 체인 비교는 x를 한 번만 평가 (중요: 부수 효과 방지)
def get_x():
print("x 계산 중...")
return 5
# 체인 비교: get_x() 한 번만 호출
print(1 < get_x() < 10) # "x 계산 중..." 한 번 출력, True
# 동등 비교 체인
print(1 == 1 == 1) # True
print(1 == 1 == 2) # False (1==1 and 1==2 = False)
⚠️ 자주 하는 실수
- None을 ==로 비교:
x == None대신x is None을 사용하세요.==는 커스텀__eq__를 호출할 수 있어 의도치 않은 결과가 나올 수 있습니다. - 0을 거짓으로 처리해 건너뜀:
if count:는 count가 0일 때 건너뜁니다. 0도 유효한 값이면if count is not None:을 사용하세요. - or 기본값에서 가변 객체 반환:
config = user_config or {}에서 여러 호출이 같은 딕셔너리를 수정할 수 있습니다. 매번 새 객체가 필요하면if/else를 사용하세요.
📝 정리 및 다음 강의 예고
- bool은 int의 서브클래스: True=1, False=0이며 수치 연산에 사용할 수 있습니다.
- 거짓(falsy)인 값: False, None, 0, 0.0, "", [], (), {}, set(). 그 외는 모두 참.
- and/or는 bool이 아닌 원래 값을 반환합니다. 이것이 단락 평가의 핵심입니다.
- None은 싱글턴 — 항상
is로 비교하세요.
다음 강의: 파이썬의 모든 연산자 우선순위를 체계적으로 정리하고, 연산자 오버로딩의 원리를 예고합니다.
++x가 왜 작동하는 것처럼 보이는지,**가 왜 오른쪽 결합인지 배웁니다.
관련 주제
- bool은 int의 서브클래스
- 트루시니스(Truthiness)
- 단락 평가(and/or)
- None 싱글턴
- 체인 비교
- is not None 패턴
- 개발·프로그래밍
- 개발·프로그래밍 강의
- 파이썬 기초 40강 — 처음 배우는 프로그래밍
- 무료강의
- 무료 온라인 강의
- NUGUNA
- 누구나
댓글
0/1000
불러오는 중...
