모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.

9강 / 전체 32강

불리언(bool)과 None — 진리값 시스템의 철학

9분 읽기 조회 5

파이썬의 트루시니스 개념과 단락 평가를 완전히 이해하고 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
  • 누구나

📚 시리즈 전체 공유

파이썬 기초 40강 — 처음 배우는 프로그래밍

이 강의가 속한 시리즈는 총 32강, 모두 무료입니다. 처음부터 배우려는 동료에게 시리즈 전체를 알려 주세요.

댓글

0/1000

불러오는 중...