Python F-Strings: 문자열 포맷팅 완벽 가이드
Updated on
문자열 포맷팅은 Python에서 가장 흔한 연산 중 하나이지만, 수년 동안 좌절의 원인이었습니다. % 연산자는 C에서 유래한 난해한 형식 코드를 사용합니다. .format() 메서드는 값을 템플릿에서 실제로 나타나는 위치에서 멀리 떨어뜨려 놓습니다. +를 사용한 문자열 연결은 수동으로 타입을 변환해야 하고 지저분하며 읽기 어려운 코드를 생산합니다. 모든 접근 방식은 값을 문자열 안에 넣는 단순한 작업에 마찰을 더하는 것처럼 느껴집니다.
실제 프로젝트에서는 문제가 더 심각해집니다. 통화를 소수점 둘째 자리까지 포맷팅하고, 보고서에서 열을 정렬하고, 선행 영으로 숫자를 패딩하고, 백분율을 표시하며, 타임스탬프를 포맷팅해야 하는데, 동시에 코드의 가독성을 유지해야 합니다. 이전 포맷팅 방법을 사용하면 템플릿 문자열과 인자 목록이라는 두 개의 병렬 구조를 유지 관리하게 됩니다. 단순히 순서를 재배열하는 실수 하나가 모든 것을 조용히 망가뜨려 오류 대신 잘못된 출력을 생성합니다.
Python 3.6은 f-strings(형식화 문자열 리터럴, formatted string literals)를 도입했고, 이는 문자열 포맷팅을 영구적으로 바꾸었습니다. 문자열에 f 접두사를 붙이고 {중괄호} 안에 표현식을 직접 내장함으로써, f-strings는 값이 나타나는 위치 바로 옆에 값을 유지합니다. 이들은 다른 모든 포맷팅 방법보다 빠릅니다. 전체 범위의 형식 지정을 지원합니다. 그리고 Python 3.8에서는 = 지정자를 통해 내장 디버깅 기능을 얻었습니다. 이 가이드는 실행 가능한 실용적인 예제와 함께 모든 f-string 기능을 다룹니다.
F-Strings란 무엇인가?
F-strings, 정식 명칭은 "형식화 문자열 리터럴(formatted string literals)"로, PEP 498 (opens in a new tab)에서 제안되었고 Python 3.6과 함께 출시되었습니다. 개념은 간단합니다: 문자열에 f(또는 F) 접두사를 붙이면, Python은 중괄호 {} 안의 모든 표현식을 런타임에 평가하여 결과를 문자열로 변환하고 출력에 삽입합니다.
name = "Alice"
age = 30
greeting = f"My name is {name} and I am {age} years old."
print(greeting)
# Output: My name is Alice and I am 30 years old.f 접두사는 작은따옴표, 큰따옴표, 삼중 따옴표 모두와 함께 작동합니다:
single = f'Hello, {name}'
double = f"Hello, {name}"
triple_double = f"""Hello, {name}"""
triple_single = f'''Hello, {name}'''내부적으로 Python은 f-strings를 파싱 시점에 일련의 문자열 연결과 format() 연산으로 컴파일합니다. 이것이 f-strings가 직접 .format()을 호출하는 것보다 빠른 이유입니다 -- 인터프리터가 연산을 직접 최적화하기 때문입니다.
기본 F-String 문법
핵심 문법은 간단합니다: f"텍스트 {표현식} 추가 텍스트"처럼 작성하세요. Python은 표현식을 평가하고 결과에 str()을 호출하여 문자열에 삽입합니다.
# Variables
city = "Tokyo"
population = 13960000
print(f"{city} has a population of {population}.")
# Output: Tokyo has a population of 13960000.
# You can use either f or F
print(F"Welcome to {city}!")
# Output: Welcome to Tokyo!단일 f-string 안에 원하는 만큼의 표현식을 배치할 수 있습니다:
first = "Grace"
last = "Hopper"
title = "Rear Admiral"
year = 1906
bio = f"{title} {first} {last}, born {year}, lived to {1992 - year} years."
print(bio)
# Output: Rear Admiral Grace Hopper, born 1906, lived to 86 years.F-String 내부의 표현식
F-strings는 단순히 변수를 삽입하는 것이 아닙니다. 중괄호 사이의 유효한 Python 표현식을 평가합니다. 여기에는 산술, 메서드 호출, 함수 호출, 삼항 표현식, 리스트 인덱싱, 딕셔너리 접근 등이 포함됩니다.
산술 및 수학
x = 15
y = 4
print(f"{x} + {y} = {x + y}")
print(f"{x} / {y} = {x / y:.2f}")
print(f"{x} ** {y} = {x ** y}")
print(f"{x} % {y} = {x % y}")
# Output:
# 15 + 4 = 19
# 15 / 4 = 3.75
# 15 ** 4 = 50625
# 15 % 4 = 3메서드 호출
text = " hello, python world "
print(f"Stripped: '{text.strip()}'")
print(f"Title case: '{text.strip().title()}'")
print(f"Upper: '{text.strip().upper()}'")
print(f"Replace: '{text.strip().replace('python', 'f-string')}'")
# Output:
# Stripped: 'hello, python world'
# Title case: 'Hello, Python World'
# Upper: 'HELLO, PYTHON WORLD'
# Replace: 'hello, f-string world'함수 호출
def calculate_bmi(weight_kg, height_m):
return weight_kg / (height_m ** 2)
weight = 70
height = 1.75
print(f"BMI: {calculate_bmi(weight, height):.1f}")
# Output: BMI: 22.9
# Built-in functions
items = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"Items: {items}")
print(f"Count: {len(items)}, Sum: {sum(items)}, Min: {min(items)}, Max: {max(items)}")
# Output:
# Items: [3, 1, 4, 1, 5, 9, 2, 6]
# Count: 8, Sum: 31, Min: 1, Max: 9삼항(조건부) 표현식
score = 85
status = f"Result: {'PASS' if score >= 60 else 'FAIL'}"
print(status)
# Output: Result: PASS
temperature = -5
print(f"Water is {'frozen' if temperature <= 0 else 'liquid' if temperature < 100 else 'steam'}.")
# Output: Water is frozen.딕셔너리 및 리스트 접근
user = {"name": "Bob", "role": "engineer", "level": 3}
scores = [88, 92, 76, 95, 81]
print(f"{user['name']} is a level {user['level']} {user['role']}.")
# Output: Bob is a level 3 engineer.
print(f"First score: {scores[0]}, Last score: {scores[-1]}")
# Output: First score: 88, Last score: 81형식 지정: 숫자, 정렬 및 패딩
F-strings의 진정한 힘은 형식 지정 사양(format specifications)에서 나타납니다. 표현식 뒤에 콜론 :을 추가하고 그 뒤에 형식 사양을 붙이세요. 일반적인 문법은 다음과 같습니다:
{표현식:[[fill]align][sign][#][0][width][grouping_option][.precision][type]}이것은 복잡해 보이지만, 각 부분은 선택 사항입니다. 예제를 통해 하나씩 살펴보겠습니다.
소수점 및 부동소수점 정밀도
.Nf 지정자는 부동소수점 수가 표시되는 소수점 자릿수를 제어합니다:
pi = 3.141592653589793
print(f"Default: {pi}")
print(f"2 decimals: {pi:.2f}")
print(f"4 decimals: {pi:.4f}")
print(f"0 decimals: {pi:.0f}")
print(f"8 decimals: {pi:.8f}")
# Output:
# Default: 3.141592653589793
# 2 decimals: 3.14
# 4 decimals: 3.1416
# 0 decimals: 3
# 8 decimals: 3.14159265천 단위 구분 기호
큰 숫자를 쉼표나 밑줄 그룹화로 즉시 읽기 쉽게 만들 수 있습니다:
revenue = 1234567890
small_amount = 1234.5
print(f"Revenue: {revenue:,}")
print(f"Revenue: {revenue:_}")
print(f"Amount: ${small_amount:,.2f}")
# Output:
# Revenue: 1,234,567,890
# Revenue: 1_234_567_890
# Amount: $1,234.50백분율 포맷팅
% 타입은 값을 100배 곱하고 백분율 기호를 붙입니다:
completion = 0.876
error_rate = 0.034
growth = 1.25
print(f"Completion: {completion:.1%}")
print(f"Error rate: {error_rate:.2%}")
print(f"Growth: {growth:.0%}")
# Output:
# Completion: 87.6%
# Error rate: 3.40%
# Growth: 125%과학적 표기법
avogadro = 6.022e23
planck = 6.626e-34
print(f"Avogadro: {avogadro:.3e}")
print(f"Planck: {planck:.4E}")
# Output:
# Avogadro: 6.022e+23
# Planck: 6.6260E-34정수 진법: 이진수, 팔진수, 십육진수
value = 255
print(f"Decimal: {value:d}")
print(f"Binary: {value:b}")
print(f"Octal: {value:o}")
print(f"Hex (lower): {value:x}")
print(f"Hex (upper): {value:X}")
print(f"With prefix: {value:#b} {value:#o} {value:#x}")
# Output:
# Decimal: 255
# Binary: 11111111
# Octal: 377
# Hex (lower): ff
# Hex (upper): FF
# With prefix: 0b11111111 0o377 0xff정렬 및 패딩
정렬 지정자는 주어진 너비 내에서 값이 어떻게 위치하는지 제어합니다. 왼쪽 정렬에는 <, 오른쪽 정렬에는 >, 가운데 정렬에는 ^를 사용하세요:
label = "Python"
print(f"|{label:<20}|") # Left-align in 20 chars
print(f"|{label:>20}|") # Right-align
print(f"|{label:^20}|") # Center
print(f"|{label:*^20}|") # Center with * fill
print(f"|{label:->20}|") # Right with - fill
# Output:
# |Python |
# | Python|
# | Python |
# |*******Python*******|
# |--------------Python|숫자에 대한 영 패딩(zero-padding)은 보고서 포맷팅에서 흔합니다:
for i in [1, 42, 100, 7, 999]:
print(f"ID: {i:05d}")
# Output:
# ID: 00001
# ID: 00042
# ID: 00100
# ID: 00007
# ID: 00999정렬된 테이블 구축
정렬과 형식 사양을 결합하면 깔끔한 테이블을 생성할 수 있습니다:
products = [
("Laptop Pro", 1299.99, 45),
("Wireless Mouse", 29.50, 230),
("USB-C Hub", 54.95, 120),
("Monitor 27in", 449.00, 67),
]
print(f"{'Product':<18} {'Price':>10} {'Stock':>7}")
print("-" * 37)
for name, price, stock in products:
print(f"{name:<18} ${price:>9.2f} {stock:>7,}")
print("-" * 37)
total_value = sum(p * s for _, p, s in products)
print(f"{'Total Value':<18} ${total_value:>9,.2f}")
# Output:
# Product Price Stock
# -------------------------------------
# Laptop Pro $ 1,299.99 45
# Wireless Mouse $ 29.50 230
# USB-C Hub $ 54.95 120
# Monitor 27in $ 449.00 67
# -------------------------------------
# Total Value $91,498.05F-String을 활용한 날짜 및 시간 포맷팅
F-strings는 strftime 형식 코드를 직접 받아들이므로, .strftime()를 호출하지 않고도 datetime 객체를 포맷팅할 수 있습니다:
from datetime import datetime, date, timedelta
now = datetime.now()
print(f"ISO format: {now:%Y-%m-%d %H:%M:%S}")
print(f"US format: {now:%m/%d/%Y}")
print(f"Long format: {now:%B %d, %Y at %I:%M %p}")
print(f"Day of week: {now:%A}")
print(f"Short month: {now:%b %d}")
# Output (varies by current time):
# ISO format: 2026-02-13 14:30:00
# US format: 02/13/2026
# Long format: February 13, 2026 at 02:30 PM
# Day of week: Friday
# Short month: Feb 13이것은 date 객체에서도 작동합니다:
from datetime import date
birthday = date(1995, 8, 15)
today = date.today()
age_days = (today - birthday).days
print(f"Birthday: {birthday:%B %d, %Y}")
print(f"Days alive: {age_days:,}")
print(f"Years (approx): {age_days / 365.25:.1f}")
# Output:
# Birthday: August 15, 1995
# Days alive: 11,139
# Years (approx): 30.5멀티라인 F-Strings
삼중 따옴표 f-strings를 사용하면 형식화된 텍스트 블록을 구축할 수 있습니다. 삼중 따옴표 f-strings의 모든 줄은 {} 표현식을 포함할 수 있습니다:
project = "Data Pipeline"
owner = "Engineering Team"
status = "In Progress"
completion = 0.73
budget = 250000
spent = 182500
report = f"""
========================================
Project Status Report
========================================
Project: {project}
Owner: {owner}
Status: {status}
Completion: {completion:.0%}
Budget: ${budget:>12,}
Spent: ${spent:>12,}
Remaining: ${budget - spent:>12,}
========================================
"""
print(report)또한 암시적 문자열 연결(연산자 없이 서로 옆에 배치)을 사용하여 여러 f-strings를 연결함으로써 멀티라인 f-strings를 구축할 수도 있습니다:
name = "Alice"
role = "Data Scientist"
years = 5
bio = (
f"Name: {name}\n"
f"Role: {role}\n"
f"Experience: {years} years\n"
f"Seniority: {'Senior' if years >= 5 else 'Mid-level'}"
)
print(bio)
# Output:
# Name: Alice
# Role: Data Scientist
# Experience: 5 years
# Seniority: Senior두 번째 접근 방식은 삼중 따옴표 문자열과 함께 때때로 발생하는 선행 개행 및 들여쓰기 문제를 피합니다.
디버깅을 위한 = 지정자 (Python 3.8+)
Python 3.8은 f-strings에 = 지정자를 추가했고, 이는 언어에서 가장 유용한 디버깅 기능 중 하나입니다. f"{expression=}"라고 작성하면 Python은 표현식 텍스트와 그 값을 모두 출력합니다.
x = 42
y = 17
print(f"{x=}")
print(f"{y=}")
print(f"{x + y=}")
print(f"{x * y=}")
# Output:
# x=42
# y=17
# x + y=59
# x * y=714=는 형식 지정자와 결합할 수 있습니다:
price = 49.99
tax_rate = 0.0825
total = price * (1 + tax_rate)
print(f"{price=:.2f}")
print(f"{tax_rate=:.1%}")
print(f"{total=:.2f}")
# Output:
# price=49.99
# tax_rate=8.2%
# total=54.12= 지정자는 주변의 공백을 보존합니다. = 앞에 공백을 추가하면 출력이 형식화됩니다:
name = "Alice"
score = 95
print(f"{name = }")
print(f"{score = }")
# Output:
# name = 'Alice'
# score = 95문자열의 경우 =는 기본적으로 repr()을 사용합니다(따옴표 표시). 숫자의 경우 str()을 사용합니다.
복잡한 표현식 디버깅
= 지정자는 모든 표현식에서 작동하여 중간 값을 검사하는 빠른 방법을 제공합니다:
data = [23, 45, 12, 67, 34, 89, 56]
print(f"{len(data)=}")
print(f"{sum(data)=}")
print(f"{sum(data)/len(data)=:.2f}")
print(f"{sorted(data)=}")
print(f"{max(data) - min(data)=}")
# Output:
# len(data)=7
# sum(data)=326
# sum(data)/len(data)=46.57
# sorted(data)=[12, 23, 34, 45, 56, 67, 89]
# max(data) - min(data)=77Jupyter 노트북에서 작업하면서 디버깅을 위해 끊임없이 print(f"{variable=}") 호출을 추가하고 있다면, Jupyter 내부에서 직접 실행되는 AI 에이전트인 RunCell (opens in a new tab)을 고려해 보세요. RunCell은 노트북 메모리의 변수를 이해하고 디버그 문을 수동으로 작성하지 않고도 검사하고 설명하며 수정 사항을 제안할 수 있습니다. 여러 셀에 걸쳐 중간 값을 검증해야 하는 데이터 변환을 단계별로 진행할 때 특히 유용합니다.
중첩 F-Strings
F-strings 안에 f-strings를 중첩할 수 있습니다. 가장 흔한 사용 사례는 동적 형식 사양입니다. 여기서 너비나 정밀도가 변수에서 옵니다:
# Dynamic precision
value = 3.14159265
for precision in range(1, 6):
print(f" {precision} decimals: {value:.{precision}f}")
# Output:
# 1 decimals: 3.1
# 2 decimals: 3.14
# 3 decimals: 3.142
# 4 decimals: 3.1416
# 5 decimals: 3.14159# Dynamic width
header = "Report"
for width in [20, 30, 40]:
print(f"|{header:^{width}}|")
# Output:
# | Report |
# | Report |
# | Report |# Nested f-string for formatting a list
values = [1.234, 56.789, 0.001, 999.999]
decimals = 2
formatted = f"Results: {', '.join(f'{v:.{decimals}f}' for v in values)}"
print(formatted)
# Output: Results: 1.23, 56.79, 0.00, 1000.00중첩은 절제해서 사용하세요. f-strings가 두 단계 이상의 중첩을 필요로 한다면, 내부 로직을 변수나 함수로 추출하여 가독성을 높이세요.
F-Strings vs 다른 문자열 포맷팅 방법
Python에는 문자열 포맷팅을 위한 네 가지 주요 접근 방식이 있습니다. 직접적인 비교는 다음과 같습니다:
| 기능 | f-string f"...{x}..." | .format() "...{}...".format(x) | % 연산자 "...%s..." % x | Template Template("...$x...") |
|---|---|---|---|---|
| Python 버전 | 3.6+ | 2.6+ | All | All |
| 가독성 | 우수 -- 값이 인라인 | 좋음 -- 번호/이름 있는 자리 표시자 | 보통 -- 위치 코드 | 좋음 -- 이름 있는 자리 표시자 |
| 성능 | 가장 빠름 | ~1.5-2배 느림 | ~1.3-1.8배 느림 | 가장 느림 |
| 임의 표현식 | 예 | 제한적 | 아니오 | 아니오 |
| 디버그 지정자 (=) | 예 (3.8+) | 아니오 | 아니오 | 아니오 |
| 재사용 가능한 템플릿 | 아니오 | 예 | 예 | 예 |
| 사용자 입력에 안전 | 아니오 | 아니오 | 아니오 | 예 (safe_substitute) |
| 타입 포맷팅 | 전체 | 전체 | 부분 | 없음 |
name = "Charlie"
balance = 1234.56
# f-string (recommended)
print(f"{name} has ${balance:,.2f}")
# .format()
print("{} has ${:,.2f}".format(name, balance))
# % formatting
print("%s has $%,.2f" % (name, balance)) # Note: % does not support comma grouping
# Template (from string module)
from string import Template
t = Template("$name has $balance")
print(t.substitute(name=name, balance=f"${balance:,.2f}"))각각을 사용하는 경우:
- F-strings: Python 3.6+를 실행할 때마다 새 코드의 기본 선택.
.format(): 변수나 구성 파일에 저장된 재사용 가능한 템플릿이 필요할 때 사용.%포맷팅: 레거시 코드 전용. 새 프로젝트에서 사용할 이유가 없음.Template: 형식 문자열이 신뢰할 수 없는 사용자 입력에서 올 때 사용(임의 표현식을 실행할 수 없음).
성능 비교
F-strings는 파싱 시점에 최적화된 바이트코드로 컴파일되어 .format()과 %에 필요한 메서드 호출 및 인자 파싱 오버헤드를 피하기 때문에 더 빠릅니다.
import timeit
name = "Alice"
age = 30
score = 95.5
# Benchmark each method with 1 million iterations
fstring_time = timeit.timeit(
'f"{name} scored {score:.1f} at age {age}"',
globals={"name": name, "age": age, "score": score},
number=1_000_000
)
format_time = timeit.timeit(
'"{} scored {:.1f} at age {}".format(name, score, age)',
globals={"name": name, "age": age, "score": score},
number=1_000_000
)
percent_time = timeit.timeit(
'"%s scored %.1f at age %d" % (name, score, age)',
globals={"name": name, "age": age, "score": score},
number=1_000_000
)
concat_time = timeit.timeit(
'name + " scored " + str(score) + " at age " + str(age)',
globals={"name": name, "age": age, "score": score},
number=1_000_000
)
print(f"f-string: {fstring_time:.4f}s (baseline)")
print(f"str.format(): {format_time:.4f}s ({format_time/fstring_time:.2f}x slower)")
print(f"% formatting: {percent_time:.4f}s ({percent_time/fstring_time:.2f}x slower)")
print(f"concatenation: {concat_time:.4f}s ({concat_time/fstring_time:.2f}x slower)")
# Typical results:
# f-string: 0.0850s (baseline)
# str.format(): 0.1450s (1.71x slower)
# % formatting: 0.1100s (1.29x slower)
# concatenation: 0.1200s (1.41x slower)성능 격차는 표현식이 더 복잡해질수록 커집니다. 수천 개의 레코드를 처리하는 타이트한 루프에서 f-strings는 측정 가능한 차이를 만듭니다.
흔한 실수와 주의사항
중괄호 이스케이프
F-string에 리터럴 { 또는 }를 포함하려면 두 배로 하세요:
value = 42
# Literal braces around a value
print(f"{{{value}}}")
# Output: {42}
# JSON-like output
key = "name"
val = "Alice"
print(f'{{"{key}": "{val}"}}')
# Output: {"name": "Alice"}
# Just literal braces, no interpolation
print(f"Use {{variable}} syntax in f-strings")
# Output: Use {variable} syntax in f-strings표현식 내부의 백슬래시
F-string의 {} 표현식 부분에는 백슬래시 문자를 사용할 수 없습니다. 이는 가독성을 위한 의도적인 설계 선택입니다:
items = ["apple", "banana", "cherry"]
# This causes a SyntaxError:
# print(f"{'\\n'.join(items)}")
# Solution 1: assign to a variable first
newline = "\n"
print(f"{newline.join(items)}")
# Solution 2: use a separate operation
joined = "\n".join(items)
print(f"Items:\n{joined}")
# Solution 3: use chr()
print(f"{chr(10).join(items)}")따옴표 충돌
F-string이 큰따옴표를 사용할 때, 내부의 표현식은 작은따옴표를 사용해야 합니다(또는 그 반대):
data = {"name": "Alice", "age": 30}
# Use single quotes inside when f-string uses double quotes
print(f"Name: {data['name']}, Age: {data['age']}")
# Or use double quotes inside when f-string uses single quotes
print(f'Name: {data["name"]}, Age: {data["age"]}')
# With triple quotes, you have more flexibility
print(f"""Name: {data["name"]}, Age: {data["age"]}""")F-Strings는 상수가 아닙니다
F-strings는 런타임에 평가되므로, 런타임 상태에 의존하는 기본 인자 값이나 모듈 수준 상수로 사용할 수 없습니다:
# This works but evaluates at call time, not definition time
def greet(name, template=None):
if template is None:
template = f"Hello, {name}!" # Evaluated here
return template
# For true templates, use str.format()
TEMPLATE = "Hello, {name}! You have {count} messages."
print(TEMPLATE.format(name="Alice", count=5))큰 표현식 조심하기
F-string 안에 어떤 표현식이든 넣을 수 있다고 해서 그래야 하는 것은 아닙니다. F-string 표현식을 단순하게 유지하세요:
# Hard to read -- too much logic inside the f-string
result = f"{'%.2f' % (sum(x**2 for x in range(100)) / 100)}"
# Much better -- compute first, then format
mean_square = sum(x**2 for x in range(100)) / 100
result = f"{mean_square:.2f}"Raw F-Strings
r(raw)와 f 접두사를 결합하면 백슬래시가 문자 그대로 처리되는(이스케이프 시퀀스 없음) raw f-string을 생성하면서도 표현식은 여전히 평가됩니다:
user = "admin"
folder = "projects"
# Raw f-string for Windows paths
path = rf"C:\Users\{user}\{folder}\data.csv"
print(path)
# Output: C:\Users\admin\projects\data.csv
# Useful for regex patterns with dynamic parts
import re
prefix = "user"
pattern = rf"\b{prefix}_\d+\b"
text = "Found user_123 and user_456 in the log"
matches = re.findall(pattern, text)
print(f"Matches: {matches}")
# Output: Matches: ['user_123', 'user_456']rf"..."와 fr"..." 모두 유효합니다 -- 접두사의 순서는 중요하지 않습니다.
데이터 사이언스 워크플로우에서의 F-Strings
F-strings는 출력 포맷팅, 동적 레이블 구축, 숫자 결과에서 읽기 쉬운 요약 생성을 위해 데이터 사이언스에서 매우 valuable합니다.
숫자 출력 포맷팅
import statistics
data = [23.4, 45.1, 31.8, 52.3, 41.7, 38.9, 29.6, 47.2]
mean = statistics.mean(data)
median = statistics.median(data)
stdev = statistics.stdev(data)
cv = stdev / mean # coefficient of variation
print(f"Sample size: {len(data)}")
print(f"Mean: {mean:.2f}")
print(f"Median: {median:.2f}")
print(f"Std deviation: {stdev:.2f}")
print(f"CV: {cv:.1%}")
print(f"Range: {min(data):.1f} - {max(data):.1f}")
# Output:
# Sample size: 8
# Mean: 38.75
# Median: 40.30
# Std deviation: 9.87
# CV: 25.5%
# Range: 23.4 - 52.3Pandas DataFrame과 함께 사용하기
import pandas as pd
df = pd.DataFrame({
"product": ["Widget A", "Widget B", "Widget C", "Widget D"],
"revenue": [125000, 89000, 234000, 67000],
"units": [1250, 2100, 980, 3400],
})
# Summary statistics with f-strings
total_rev = df["revenue"].sum()
avg_price = (df["revenue"] / df["units"]).mean()
print(f"Total Revenue: ${total_rev:>12,}")
print(f"Avg Unit Price: ${avg_price:>12,.2f}")
print(f"Products: {len(df):>12,}")
# Dynamic column formatting
for _, row in df.iterrows():
unit_price = row["revenue"] / row["units"]
print(f" {row['product']:<12} | Revenue: ${row['revenue']:>9,} | Units: {row['units']:>5,} | $/unit: ${unit_price:.2f}")
# Output:
# Total Revenue: $ 515,000
# Avg Unit Price: $ 56.00
# Products: 4
# Widget A | Revenue: $ 125,000 | Units: 1,250 | $/unit: $100.00
# Widget B | Revenue: $ 89,000 | Units: 2,100 | $/unit: $42.38
# Widget C | Revenue: $ 234,000 | Units: 980 | $/unit: $238.78
# Widget D | Revenue: $ 67,000 | Units: 3,400 | $/unit: $19.71텍스트 요약을 넘어서서 대화형 탐색이 필요할 때, PyGWalker (opens in a new tab)는 모든 pandas DataFrame을 단 한 줄의 코드로 Tableau와 같은 대화형 시각화로 변환할 수 있습니다. 정적 보고서를 위해 숫자를 수동으로 포맷팅하는 대신, 열을 드래그 앤 드롭하여 차트를 구축하고, 필터를 적용하며, 시각적으로 패턴을 탐색할 수 있습니다 -- 모두 Jupyter 노트북 내부에서.
import pandas as pd
import pygwalker as pyg
# After preparing your DataFrame with well-formatted columns
df = pd.DataFrame({
"Month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
"Revenue": [125000, 134000, 158000, 142000, 167000, 189000],
"Growth": [0.05, 0.072, 0.179, -0.101, 0.176, 0.132],
})
# Add formatted columns for display
df["Revenue_Display"] = df["Revenue"].apply(lambda x: f"${x:,.0f}")
df["Growth_Display"] = df["Growth"].apply(lambda x: f"{x:+.1%}")
# Launch interactive visualization
# pyg.walk(df)모델 결과 포맷팅
# Formatting machine learning results
metrics = {
"accuracy": 0.9234,
"precision": 0.8891,
"recall": 0.9456,
"f1_score": 0.9164,
"auc_roc": 0.9678,
}
print("Model Evaluation Results")
print("=" * 35)
for metric, value in metrics.items():
bar_length = int(value * 20)
bar = "#" * bar_length + "-" * (20 - bar_length)
print(f" {metric:<12} {value:.4f} [{bar}]")
# Output:
# Model Evaluation Results
# ===================================
# accuracy 0.9234 [##################--]
# precision 0.8891 [#################---]
# recall 0.9456 [##################--]
# f1_score 0.9164 [##################--]
# auc_roc 0.9678 [###################-]변환 플래그: !s, !r, 그리고 !a
F-strings는 표현식 값이 포맷팅되기 전에 변환되는 방식을 제어하는 세 가지 변환 플래그를 지원합니다:
!s는 값에str()을 호출합니다(기본 동작)!r은 값에repr()을 호출합니다!a는 값에ascii()를 호출합니다
text = "Hello\tWorld"
name = "Caf\u00e9"
print(f"str: {text!s}")
print(f"repr: {text!r}")
print(f"ascii: {name!a}")
# Output:
# str: Hello World
# repr: 'Hello\tWorld'
# ascii: 'Caf\xe9'!r 플래그는 디버깅에 특히 유용합니다. 왜냐하면 따옴표와 이스케이프 문자를 포함한 원시 표현을 보여주기 때문입니다. = 지정자와 함께 잘 작동합니다.
자주 묻는 질문
Python f-strings란 무엇이며 언제 도입되었나요?
F-strings(형식화 문자열 리터럴)는 PEP 498을 통해 Python 3.6에서 도입된 문자열 포맷팅 메커니즘입니다. 문자열에 f 접두사를 붙이고 중괄호 안에 표현식을 배치함으로써 Python 표현식을 문자열 리터럴 내부에 직접 내장할 수 있게 해줍니다. F-strings는 런타임에 평가되며, 모든 포맷팅 옵션 중 최고의 가독성을 제공하고, 파싱 시점에 최적화된 바이트코드로 컴파일되므로 str.format()과 % 포맷팅보다 빠릅니다.
F-strings에서 숫자를 쉼표와 소수점으로 포맷팅하려면 어떻게 하나요?
중괄호 내부에서 콜론 뒤에 형식 사양을 사용하세요. 천 단위 구분 기호로 쉼표를 사용하려면 :,를 사용하세요 -- 예: f"{1234567:,}"는 "1,234,567"을 생성합니다. 소수점 자릿수는 :Nf를 사용하며, 여기서 N은 자릿수입니다 -- 예: f"{3.14159:.2f}"는 "3.14"를 줍니다. 둘을 결합하세요: f"{1234.5:,.2f}"는 "1,234.50"을 출력합니다. 백분율의 경우 :.N%를 사용하는데, 이는 100을 곱하고 백분율 기호를 붙입니다: f"{0.85:.1%}"는 "85.0%"를 생성합니다.
f-string = 지정자는 무엇이며 디버깅에 어떻게 도움이 되나요?
= 지정자는 Python 3.8에 추가되었고 표현식 텍스트와 그 값을 모두 출력합니다. f"{variable=}"을 작성하면 variable=value가 출력됩니다. 이는 디버깅 시 변수 이름을 두 번 입력할 필요를 없애줍니다. 모든 표현식에서 작동하며 f"{price=:.2f}"처럼 형식 사양과 결합할 수 있습니다.
멀티라인 문자열에서 f-strings를 사용할 수 있나요?
예. 멀티라인 f-strings에는 삼중 따옴표(f"""...""" 또는 f'''...''')를 사용하세요. 모든 줄은 {expression} 자리 표시자를 포함할 수 있습니다. 대안으로 괄호 안에 서로 옆에 배치하여 암시적 문자열 연결을 사용하여 여러 f-strings를 연결할 수도 있습니다.
f-strings가 str.format()과 % 포맷팅보다 빠른가요?
예. F-strings는 Python에서 일관되게 가장 빠른 문자열 포맷팅 방법입니다. 일반적으로 str.format()보다 1.52배 빠르며 1.8배 빠릅니다. 속도 이점은 Python이 f-strings를 런타임 메서드 조회 및 인자 파싱 없이 직접 효율적인 바이트코드로 변환하는 컴파일 타임 최적화에서 비롯됩니다.% 포맷팅보다 1.3
F-string에 리터럴 중괄호를 포함하려면 어떻게 하나요?
중괄호를 두 배로 하세요. 리터럴 {에는 {{를, 리터럴 }에는 }}를 사용하세요. 예: f"{{value}}"는 일반 텍스트로 {value}를 출력합니다. 보간된 값을 중괄호로 감싸려면 f"{{{variable}}}"를 사용하세요 -- 바깥쪽 이중 중괄호는 리터럴 중괄호를 생성하고, 안쪽 단일 중괄호는 보간을 트리거합니다.
결론
F-strings는 현대 Python에서 문자열을 포맷팅하는 표준 방법입니다. 이들은 모든 포맷팅 접근 방식 중 최고의 가독성과 최고의 성능을 결합하며, 소수점 정밀도, 천 단위 구분 기호, 백분율, 과학적 표기법, 정렬, 패딩, 날짜 포맷팅, 진법 변환의 전체 범위를 지원합니다.
기억해야 할 핵심 사항:
f접두사를 붙이고{중괄호}안에 표현식을 넣으세요.- 정밀한 출력 제어를 위해
:뒤에 형식 사양을 사용하세요(:.2f,:,:.1%,:<20). - 디버깅을 위해 표현식 뒤에
=를 사용하세요(f"{variable=}"). Python 3.8+가 필요합니다. - 리터럴 중괄호는 두 배로 하세요:
{{와}}. {}표현식 내부에는 백슬래시를 넣지 마세요. 먼저 변수에 할당하세요.- 표현식을 단순하게 유지하세요.
{}내부의 로직이 읽기 어렵다면 추출하세요. - 변수에 저장된 재사용 가능한 템플릿이 필요할 때만
.format()을 사용하세요.
F-strings는 빠른 print() 디버깅부터 프로덕션 보고서 생성까지 모든 것을 처리합니다. 한번 채택하면 이전 포맷팅 방법으로 돌아갈 이유가 없습니다. 데이터 파이프라인 구축, ML 모델 출력 포맷팅, 또는 재무 보고서 생성에 관계없이, f-strings는 깔끔하고 빠르며 읽기 쉬운 코드를 제공합니다.