파이썬의 모든 문자열 포맷팅 방법을 비교하고 f-string의 모든 기능을 마스터한다.
🎯 이 강의에서 배우는 것
파이썬에서 문자열에 변수 값을 넣는 방법은 시대에 따라 세 번 진화했습니다. % 연산자, str.format(), 그리고 f-string. 각각의 탄생 이유와 한계를 이해하고, f-string의 모든 형식 지정자를 마스터합니다. 올바른 포맷팅 방법 선택이 코드 가독성과 유지보수성을 크게 좌우합니다.
📜 포맷팅의 역사 — 왜 세 가지 방법이 있는가
name = "홍길동"
age = 30
pi = 3.14159
# 방법 1: % 연산자 (Python 2 시대, C printf 스타일)
msg1 = "이름: %s, 나이: %d, 원주율: %.2f" % (name, age, pi)
print(msg1) # 이름: 홍길동, 나이: 30, 원주율: 3.14
# 방법 2: str.format() (Python 2.6+)
msg2 = "이름: {}, 나이: {}, 원주율: {:.2f}".format(name, age, pi)
print(msg2) # 이름: 홍길동, 나이: 30, 원주율: 3.14
# 위치 인덱스와 이름 키워드
msg2b = "이름: {0}, 나이: {1}, 다시 이름: {0}".format(name, age)
msg2c = "이름: {name}, 나이: {age}".format(name=name, age=age)
# 방법 3: f-string (Python 3.6+, 권장)
msg3 = f"이름: {name}, 나이: {age}, 원주율: {pi:.2f}"
print(msg3) # 이름: 홍길동, 나이: 30, 원주율: 3.14
% 포맷팅의 한계: 인자 순서 실수, %s/%d/%f 타입 지정자 암기 필요, 가독성 저하. str.format()이 이를 개선했지만 여전히 장황합니다. f-string은 파이썬 3.6에서 도입되어 가장 읽기 쉽고 가장 빠릅니다.
🚀 f-string 기본 문법과 표현식
f-string의 {} 안에는 어떤 파이썬 표현식도 들어갈 수 있습니다:
x = 10
y = 20
# 변수
print(f"{x}") # 10
# 산술 표현식
print(f"{x + y}") # 30
print(f"{x * y}") # 200
# 함수 호출
words = ["hello", "world"]
print(f"{len(words)} 단어") # 2 단어
print(f"{words[0].upper()}") # HELLO
# 메서드 호출
name = "홍길동"
print(f"{'안녕하세요 ' + name}님") # 안녕하세요 홍길동님
# 조건 표현식 (삼항 연산자)
age = 17
print(f"{'성인' if age >= 18 else '미성년자'}") # 미성년자
# 딕셔너리 접근
person = {"name": "홍길동", "age": 30}
print(f"{person['name']}님은 {person['age']}세입니다")
# 중첩 f-string
precision = 3
print(f"{pi:.{precision}f}") # 3.142 (precision 변수로 소수점 자리 지정)
📐 형식 지정자 (Format Spec Mini-Language)
f-string의 콜론(:) 뒤에 형식 지정자를 붙입니다. 완전한 문법은 {값:[[채우기]정렬][부호][#][0][너비][그룹][.정밀도][타입]}입니다:
n = 42
pi = 3.14159265
# 너비와 정렬
print(f"{n:10}") # " 42" (오른쪽 정렬, 기본)
print(f"{n:<10}") # "42 " (왼쪽 정렬)
print(f"{n:^10}") # " 42 " (가운데 정렬)
print(f"{n:0>10}") # "0000000042" (0으로 채우기)
print(f"{n:*^10}") # "****42****" (* 문자로 채우기)
# 소수점
print(f"{pi:.2f}") # 3.14 (소수점 2자리)
print(f"{pi:.5f}") # 3.14159 (소수점 5자리)
print(f"{pi:10.3f}") # " 3.142" (너비 10, 소수점 3자리)
# 천 단위 구분자
big_num = 1234567890
print(f"{big_num:,}") # 1,234,567,890
print(f"{big_num:_}") # 1_234_567_890 (밑줄 구분자)
# 부호
print(f"{42:+}") # +42
print(f"{-42:+}") # -42
print(f"{42: }") # " 42" (양수에 공백 — 음수와 정렬 맞추기)
# 진법
n = 255
print(f"{n:b}") # 11111111 (2진수)
print(f"{n:o}") # 377 (8진수)
print(f"{n:x}") # ff (16진수, 소문자)
print(f"{n:X}") # FF (16진수, 대문자)
print(f"{n:#x}") # 0xff (0x 접두사 포함)
print(f"{n:#010b}") # 0b11111111 (접두사+너비10+2진수)
# 과학적 표기
big = 1234567.89
print(f"{big:e}") # 1.234568e+06
print(f"{big:.2e}") # 1.23e+06
print(f"{big:g}") # 1.23457e+06 (더 짧은 표현 자동 선택)
🐛 f-string 디버깅 모드 (Python 3.8+)
x = 42
lst = [1, 2, 3]
name = "파이썬"
# = 를 붙이면 변수명=값 형태로 출력
print(f"{x=}") # x=42
print(f"{lst=}") # lst=[1, 2, 3]
print(f"{name=}") # name='파이썬'
# 형식 지정자와 함께 사용
print(f"{x=:.2f}") # x=42.00
# 함수 호출 디버깅
import math
print(f"{math.sqrt(16)=}") # math.sqrt(16)=4.0
🔄 변환 플래그 (!r, !s, !a)
class Product:
def __init__(self, name):
self.name = name
def __str__(self):
return f"상품명: {self.name}"
def __repr__(self):
return f"Product({self.name!r})"
p = Product("파이썬 책")
print(f"{p}") # 상품명: 파이썬 책 (__str__ 호출)
print(f"{p!s}") # 상품명: 파이썬 책 (__str__ 강제)
print(f"{p!r}") # Product('파이썬 책') (__repr__ 강제)
print(f"{p!a}") # Product('\ud30c\uc774\uc36c \ucc45') (ASCII만 사용)
# 문자열에서 !r은 따옴표를 포함해서 출력
s = "hello
world"
print(f"{s}") # hello (줄바꿈)
# world
print(f"{s!r}") # 'hello\nworld' (이스케이프 문자 그대로)
⚡ 성능 비교 — f-string이 가장 빠른 이유
import timeit
name = "홍길동"
age = 30
# 세 가지 방법의 성능 비교
t1 = timeit.timeit(
"'이름: %s, 나이: %d' % (name, age)",
globals={"name": name, "age": age},
number=1_000_000
)
t2 = timeit.timeit(
"'이름: {}, 나이: {}'.format(name, age)",
globals={"name": name, "age": age},
number=1_000_000
)
t3 = timeit.timeit(
"f'이름: {name}, 나이: {age}'",
globals={"name": name, "age": age},
number=1_000_000
)
print(f"% 연산자: {t1:.3f}초")
print(f"str.format: {t2:.3f}초")
print(f"f-string: {t3:.3f}초")
# 일반적으로 f-string이 가장 빠름
# f-string은 컴파일 시점에 최적화된 바이트코드 생성
⚠️ 자주 하는 실수
- f-string 안에 따옴표 충돌: f-string이 큰따옴표로 시작하면 내부 표현식에서 큰따옴표 사용 불가. 작은따옴표로 전환하거나, Python 3.12+에서는 같은 종류의 따옴표도 중첩 허용.
- 복잡한 표현식을 f-string에 직접 작성: 가독성을 위해 복잡한 계산은 변수에 먼저 담고 f-string에서 변수를 참조하세요.
- % 연산자에서 인자가 하나일 때 튜플 빠뜨림:
"값: %s" % value에서 value가 튜플이면 오류 발생."값: %s" % (value,)처럼 항상 튜플로 감싸세요.
📝 정리 및 다음 강의 예고
- % 연산자 → str.format() → f-string 순으로 발전. 새 코드는 f-string을 사용하세요.
- f-string의 형식 지정자: 정렬(
<>^), 너비, 소수점(.nf), 구분자(,), 진법(b/o/x). f"{x=}"는 디버깅에 매우 유용한 Python 3.8+ 기능입니다.- f-string이 세 가지 중 가장 빠르고 가장 읽기 쉽습니다.
다음 강의: 조건문(if/elif/else)을 배웁니다. 들여쓰기가 블록을 정의하는 파이썬 철학, 가드 클로즈 패턴, 그리고 Python 3.10의 구조적 패턴 매칭(match-case)까지 다룹니다.
관련 주제
- f-string 문법
- 포맷 지정자(정렬·소수점)
- %연산자 포맷팅
- str.format()
- 디버깅 변수명=값 출력
- !r !s 변환플래그
- 개발·프로그래밍
- 개발·프로그래밍 강의
- 파이썬 기초 40강 — 처음 배우는 프로그래밍
- 무료강의
- 무료 온라인 강의
- NUGUNA
- 누구나
댓글
0/1000
불러오는 중...
