본문으로 건너뛰기
Advertisement

Ch 2.4 형변환(Type Casting)

형변환은 하나의 데이터 타입을 다른 타입으로 변환하는 과정입니다. 파이썬은 암시적 형변환과 명시적 형변환을 모두 지원합니다.

1. 암시적 형변환

파이썬이 자동으로 타입을 변환합니다. 주로 숫자 연산에서 발생합니다.

# int + float → float (자동 변환)
result = 5 + 2.0
print(result) # 7.0
print(type(result)) # <class 'float'>

# int + bool → int (bool이 int의 서브클래스)
result2 = 10 + True
print(result2) # 11
print(type(result2)) # <class 'int'>

result3 = 10 + False
print(result3) # 10

# int + complex → complex
result4 = 3 + (2 + 1j)
print(result4) # (5+1j)
print(type(result4)) # <class 'complex'>

# 암시적 변환 우선순위: complex > float > int

파이썬은 데이터 손실이 발생할 수 있는 변환은 암시적으로 하지 않습니다. 예를 들어 float + str은 TypeError가 발생합니다.

# 이것은 에러 — 암시적 변환 없음
# result = 5 + "10" # TypeError: unsupported operand type(s) for +: 'int' and 'str'

2. 명시적 형변환

개발자가 직접 타입을 변환합니다.

int() 변환

# float → int (소수점 버림, 반올림 아님!)
print(int(3.9)) # 3 (버림!)
print(int(-3.9)) # -3 (버림, 절댓값 기준)
print(int(3.1)) # 3

# str → int
print(int("42")) # 42
print(int(" 100 ")) # 100 (앞뒤 공백 자동 제거)

# bool → int
print(int(True)) # 1
print(int(False)) # 0

# 진수 변환 (문자열에서)
print(int("1010", 2)) # 10 (2진수 "1010" → 정수 10)
print(int("ff", 16)) # 255 (16진수 "ff" → 정수 255)
print(int("17", 8)) # 15 (8진수 "17" → 정수 15)

float() 변환

# int → float
print(float(42)) # 42.0

# str → float
print(float("3.14")) # 3.14
print(float("1e3")) # 1000.0
print(float("inf")) # inf
print(float("-inf")) # -inf
print(float("nan")) # nan

# bool → float
print(float(True)) # 1.0

str() 변환

# 모든 타입 → 문자열
print(str(42)) # '42'
print(str(3.14)) # '3.14'
print(str(True)) # 'True'
print(str(None)) # 'None'
print(str([1, 2, 3])) # '[1, 2, 3]'
print(str({"a": 1})) # "{'a': 1}"

bool() 변환

# 다양한 타입 → bool
print(bool(1)) # True
print(bool(0)) # False
print(bool(-1)) # True (0이 아니면 True)
print(bool("hello")) # True
print(bool("")) # False (빈 문자열)
print(bool([1, 2])) # True
print(bool([])) # False (빈 리스트)
print(bool(None)) # False
print(bool({})) # False (빈 딕셔너리)
print(bool({0})) # True (0이 있는 집합 — 비어있지 않음)

list(), tuple(), set() 변환

# 상호 변환
my_list = [1, 2, 3, 3, 2]
my_tuple = tuple(my_list) # (1, 2, 3, 3, 2)
my_set = set(my_list) # {1, 2, 3} (중복 제거)

print(list(my_tuple)) # [1, 2, 3, 3, 2]
print(list(my_set)) # [1, 2, 3] (순서 비결정)

# 문자열 → 리스트 (각 문자가 요소)
chars = list("Python")
print(chars) # ['P', 'y', 't', 'h', 'o', 'n']

# range → 리스트
numbers = list(range(1, 11))
print(numbers) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 딕셔너리 → 리스트 (키 목록)
d = {"a": 1, "b": 2, "c": 3}
print(list(d)) # ['a', 'b', 'c'] (키)
print(list(d.values())) # [1, 2, 3] (값)
print(list(d.items())) # [('a', 1), ('b', 2), ('c', 3)]

3. 문자열 → 숫자 변환 실패 처리

# 변환 실패 시 ValueError 발생
# int("hello") # ValueError: invalid literal for int() with base 10: 'hello'
# float("abc") # ValueError: could not convert string to float: 'abc'

# try/except으로 안전하게 처리
def safe_int(value: str, default: int = 0) -> int:
"""문자열을 정수로 안전하게 변환합니다."""
try:
return int(value)
except (ValueError, TypeError):
return default

print(safe_int("42")) # 42
print(safe_int("hello")) # 0 (기본값)
print(safe_int("3.14")) # 0 (소수점 있으면 실패)
print(safe_int(None)) # 0

def safe_float(value, default=0.0):
try:
return float(value)
except (ValueError, TypeError):
return default

print(safe_float("3.14")) # 3.14
print(safe_float("hello")) # 0.0

# 실전 예시: 사용자 입력 처리
def get_user_age() -> int:
while True:
user_input = input("나이를 입력하세요: ")
try:
age = int(user_input)
if age < 0 or age > 150:
print("올바른 나이를 입력해주세요 (0-150).")
continue
return age
except ValueError:
print(f"'{user_input}'는 유효한 숫자가 아닙니다. 다시 입력해주세요.")

4. Falsy 값 목록

파이썬에서 bool() 변환 시 False로 평가되는 값들입니다.

falsy_values = [
None, # NoneType
False, # bool
0, # int
0.0, # float
0j, # complex
"", # 빈 문자열
b"", # 빈 bytes
[], # 빈 리스트
(), # 빈 튜플
{}, # 빈 딕셔너리
set(), # 빈 집합
]

for val in falsy_values:
print(f"bool({val!r:15}) = {bool(val)}")

# 모두 False 출력됨

# Falsy 활용 패턴
def process_name(name: str | None) -> str:
if not name: # None, "", " ".strip() 결과 "" 모두 처리
return "Anonymous"
return name.strip().title()

print(process_name(None)) # Anonymous
print(process_name("")) # Anonymous
print(process_name("alice")) # Alice

5. 진수 변환

number = 255

# 정수 → 진수 문자열
print(bin(number)) # '0b11111111'
print(oct(number)) # '0o377'
print(hex(number)) # '0xff'

# 접두사 없이 출력
print(format(number, 'b')) # '11111111'
print(format(number, 'o')) # '377'
print(format(number, 'x')) # 'ff'
print(format(number, 'X')) # 'FF' (대문자)

# 자리수 지정
print(format(number, '08b')) # '11111111' (8자리)
print(format(number, '#010b')) # '0b11111111' (접두사 포함 10자리)

# 진수 문자열 → 정수
print(int("11111111", 2)) # 255 (2진수)
print(int("377", 8)) # 255 (8진수)
print(int("ff", 16)) # 255 (16진수)
print(int("FF", 16)) # 255 (대소문자 모두)
print(int("0xff", 16)) # 255 (접두사 포함도 가능)

# 실전: RGB 색상 변환
def hex_to_rgb(hex_color: str) -> tuple[int, int, int]:
"""#RRGGBB 형식을 RGB 튜플로 변환합니다."""
hex_color = hex_color.lstrip('#')
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
return r, g, b

def rgb_to_hex(r: int, g: int, b: int) -> str:
"""RGB 값을 #RRGGBB 형식으로 변환합니다."""
return f"#{r:02X}{g:02X}{b:02X}"

print(hex_to_rgb("#FF5733")) # (255, 87, 51)
print(rgb_to_hex(255, 87, 51)) # #FF5733

고수 팁: __int__, __float__, __bool__ 매직 메서드로 커스텀 형변환

파이썬의 int(), float(), bool() 함수는 내부적으로 객체의 매직 메서드를 호출합니다. 이를 구현하면 커스텀 클래스도 형변환을 지원할 수 있습니다.

class Temperature:
"""섭씨 온도를 나타내는 클래스"""

def __init__(self, celsius: float):
self.celsius = celsius

def __int__(self) -> int:
"""int() 호출 시 섭씨를 반올림한 정수 반환"""
return round(self.celsius)

def __float__(self) -> float:
"""float() 호출 시 섭씨 반환"""
return float(self.celsius)

def __bool__(self) -> bool:
"""절대영도(0K = -273.15°C) 초과 시 True"""
return self.celsius > -273.15

def __str__(self) -> str:
return f"{self.celsius}°C"

def to_fahrenheit(self) -> float:
return self.celsius * 9 / 5 + 32


temp = Temperature(36.6)

print(int(temp)) # 37
print(float(temp)) # 36.6
print(bool(temp)) # True

freezing = Temperature(-273.15)
print(bool(freezing)) # False (절대영도)

print(str(temp)) # 36.6°C
print(temp.to_fahrenheit()) # 97.88

# 실용적인 예: 금액 클래스
class Money:
def __init__(self, amount: float, currency: str = "KRW"):
self.amount = amount
self.currency = currency

def __int__(self) -> int:
return int(self.amount)

def __float__(self) -> float:
return float(self.amount)

def __bool__(self) -> bool:
return self.amount > 0

def __str__(self) -> str:
return f"{self.amount:,.0f} {self.currency}"

price = Money(29_900)
print(str(price)) # 29,900 KRW
print(bool(price)) # True
print(bool(Money(0))) # False

형변환의 다양한 방법을 이해했습니다. 다음 챕터에서는 파이썬 3.12+에서 더욱 중요해진 타입 힌트(Type Hints)를 알아보겠습니다.

Advertisement