Skip to content

Latest commit

Β 

History

History
523 lines (379 loc) Β· 11.5 KB

File metadata and controls

523 lines (379 loc) Β· 11.5 KB

Python f-string

Java의 String.format()μ΄λ‚˜ + 연결보닀 더 읽기 쉽고 λΉ λ₯Έ λ¬Έμžμ—΄ ν¬λ§€νŒ….

κ²°λ‘ λΆ€ν„° λ§ν•˜λ©΄

f-string은 κ°€μž₯ λΉ λ₯΄κ³  읽기 μ‰¬μš΄ λ¬Έμžμ—΄ ν¬λ§€νŒ… λ°©λ²•μž…λ‹ˆλ‹€.

name = "홍길동"
age = 30

# f-string (ꢌμž₯)
f"이름: {name}, λ‚˜μ΄: {age}"  # "이름: 홍길동, λ‚˜μ΄: 30"

# λ‹€λ₯Έ 방법듀 (ꡬ식)
"이름: %s, λ‚˜μ΄: %d" % (name, age)           # % ν¬λ§€νŒ…
"이름: {}, λ‚˜μ΄: {}".format(name, age)       # .format()
"이름: " + name + ", λ‚˜μ΄: " + str(age)      # λ¬Έμžμ—΄ μ—°κ²°

1. κΈ°λ³Έ μ‚¬μš©λ²•

λ³€μˆ˜ μ‚½μž…

name = "홍길동"
city = "μ„œμšΈ"

# f-string
message = f"{name}λ‹˜μ€ {city}에 μ‚½λ‹ˆλ‹€"
print(message)  # "ν™κΈΈλ™λ‹˜μ€ μ„œμšΈμ— μ‚½λ‹ˆλ‹€"

# μ—¬λŸ¬ 쀄
text = f"""
이름: {name}
λ„μ‹œ: {city}
"""

ν‘œν˜„μ‹ μ‚¬μš©

a = 10
b = 20

# 계산
print(f"{a} + {b} = {a + b}")  # "10 + 20 = 30"

# ν•¨μˆ˜ 호좜
print(f"λŒ€λ¬Έμž: {name.upper()}")  # "λŒ€λ¬Έμž: 홍길동"

# λ©”μ„œλ“œ 체이닝
text = "  hello  "
print(f"정리: '{text.strip().upper()}'")  # "정리: 'HELLO'"

쑰건식

score = 85
result = f"{'합격' if score >= 60 else 'λΆˆν•©κ²©'}"
print(result)  # "합격"

# λ³΅μž‘ν•œ ν‘œν˜„μ‹
age = 15
status = f"{'성인' if age >= 18 else 'λ―Έμ„±λ…„μž'} ({age}μ„Έ)"
print(status)  # "λ―Έμ„±λ…„μž (15μ„Έ)"

2. ν¬λ§€νŒ… μ˜΅μ…˜

숫자 ν¬λ§€νŒ…

number = 1234567.89

# 천 λ‹¨μœ„ κ΅¬λΆ„μž
print(f"{number:,}")           # "1,234,567.89"

# μ†Œμˆ˜μ  자리수
print(f"{number:.2f}")         # "1234567.89"
print(f"{number:,.2f}")        # "1,234,567.89"

# νΌμ„ΌνŠΈ
rate = 0.856
print(f"{rate:.1%}")           # "85.6%"

# μ§€μˆ˜ ν‘œκΈ°
print(f"{number:.2e}")         # "1.23e+06"

μ •λ ¬κ³Ό νŒ¨λ”©

text = "Python"

# μ™Όμͺ½ μ •λ ¬ (κΈ°λ³Έ)
print(f"{text:<10}|")          # "Python    |"

# 였λ₯Έμͺ½ μ •λ ¬
print(f"{text:>10}|")          # "    Python|"

# κ°€μš΄λ° μ •λ ¬
print(f"{text:^10}|")          # "  Python  |"

# νŠΉμ • 문자둜 μ±„μš°κΈ°
print(f"{text:*<10}")          # "Python****"
print(f"{text:->10}")          # "----Python"
print(f"{text:=^10}")          # "==Python=="

숫자 μ •λ ¬κ³Ό λΆ€ν˜Έ

numbers = [42, -17, 100, -5]

for num in numbers:
    # 였λ₯Έμͺ½ μ •λ ¬, 5자리
    print(f"{num:5d}")
# 좜λ ₯:
#    42
#   -17
#   100
#    -5

# λΆ€ν˜Έ ν‘œμ‹œ
positive = 42
print(f"{positive:+d}")        # "+42"
print(f"{positive: d}")        # " 42" (μ–‘μˆ˜λŠ” 곡백)

# 0으둜 νŒ¨λ”©
num = 42
print(f"{num:05d}")            # "00042"

3. λ³€ν™˜ μ§€μ •μž: !s, !r, !a

!s (str)

class Person:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"Person: {self.name}"

person = Person("홍길동")

print(f"{person}")             # "Person: 홍길동"
print(f"{person!s}")           # "Person: 홍길동" (동일)

# μ˜ˆμ™Έ λ©”μ‹œμ§€
try:
    1 / 0
except Exception as e:
    print(f"였λ₯˜: {e!s}")      # "였λ₯˜: division by zero"

!r (repr) - λ””λ²„κΉ…μš©

text = "Hello\nWorld"

print(f"{text!s}")             # Hello
                               # World (μ‹€μ œ μ€„λ°”κΏˆ)

print(f"{text!r}")             # 'Hello\nWorld' (μ΄μŠ€μΌ€μ΄ν”„ 문자 λ³΄μž„)

# λ¬Έμžμ—΄ 디버깅
name = "홍길동"
print(f"{name!s}")             # 홍길동
print(f"{name!r}")             # '홍길동' (λ”°μ˜΄ν‘œ 포함)

# None, 숫자 λ“±
value = None
print(f"κ°’: {value!r}")        # "κ°’: None"

!a (ascii)

text = "μ•ˆλ…•ν•˜μ„Έμš” πŸ˜€"

print(f"{text!s}")             # "μ•ˆλ…•ν•˜μ„Έμš” πŸ˜€"
print(f"{text!a}")             # "'\uc548\ub155\ud558\uc138\uc694 \U0001f600'"

# ASCII만 ν¬ν•¨λœ 둜그 파일 생성 μ‹œ 유용

비ꡐ: str() vs !s

exception = ValueError("잘λͺ»λœ κ°’")

# ❌ λΆˆν•„μš”ν•œ ν•¨μˆ˜ 호좜 (RUFFκ°€ 지적)
f"였λ₯˜: {str(exception)}"

# βœ… 더 κ°„κ²° (RUFF ꢌμž₯)
f"였λ₯˜: {exception!s}"

# βœ… κ°€μž₯ 간단 (일반적으둜 μΆ©λΆ„)
f"였λ₯˜: {exception}"

4. μ€‘κ΄„ν˜Έ μ΄μŠ€μΌ€μ΄ν”„

# μ€‘κ΄„ν˜Έλ₯Ό 문자둜 μ‚¬μš©ν•˜λ €λ©΄ 두 번 써야 함
print(f"{{μ€‘κ΄„ν˜Έ}}")           # "{μ€‘κ΄„ν˜Έ}"
print(f"{{{{이쀑}}}}")         # "{{이쀑}}"

# λ³€μˆ˜μ™€ μ„žμ–΄μ„œ
value = 42
print(f"κ°’ = {{{value}}}")     # "κ°’ = {42}"

5. λ”•μ…”λ„ˆλ¦¬μ™€ ν•¨κ»˜ μ‚¬μš©

user = {"name": "홍길동", "age": 30, "city": "μ„œμšΈ"}

# κΈ°λ³Έ
print(f"이름: {user['name']}")  # "이름: 홍길동"

# μ—¬λŸ¬ κ°’
print(f"{user['name']}({user['age']}μ„Έ)λŠ” {user['city']}에 μ‚½λ‹ˆλ‹€")
# "홍길동(30μ„Έ)λŠ” μ„œμšΈμ— μ‚½λ‹ˆλ‹€"

# ** unpacking (λ³€μˆ˜λͺ…이 킀와 같을 λ•Œ)
name = user["name"]
age = user["age"]
print(f"{name}λ‹˜μ€ {age}μ„Έμž…λ‹ˆλ‹€")

6. λ‚ μ§œ/μ‹œκ°„ ν¬λ§€νŒ…

from datetime import datetime

now = datetime.now()

# κΈ°λ³Έ
print(f"ν˜„μž¬: {now}")
# "ν˜„μž¬: 2025-01-11 14:30:45.123456"

# μ»€μŠ€ν…€ 포맷
print(f"{now:%Y-%m-%d}")                    # "2025-01-11"
print(f"{now:%Yλ…„ %mμ›” %d일}")              # "2025λ…„ 01μ›” 11일"
print(f"{now:%H:%M:%S}")                    # "14:30:45"
print(f"{now:%Y-%m-%d %H:%M:%S}")           # "2025-01-11 14:30:45"

# μš”μΌ
print(f"{now:%A}")                          # "Saturday"
print(f"{now:%a}")                          # "Sat"

7. μ‹€μ „ μ˜ˆμ‹œ

ν…Œμ΄λΈ” 좜λ ₯

products = [
    {"name": "λ…ΈνŠΈλΆ", "price": 1200000, "stock": 5},
    {"name": "마우슀", "price": 35000, "stock": 150},
    {"name": "ν‚€λ³΄λ“œ", "price": 89000, "stock": 42},
]

# 헀더
print(f"{'μƒν’ˆλͺ…':<10} {'가격':>10} {'재고':>5}")
print("-" * 30)

# 데이터
for p in products:
    print(f"{p['name']:<10} {p['price']:>10,}원 {p['stock']:>5}개")

# 좜λ ₯:
# μƒν’ˆλͺ…            가격    재고
# ------------------------------
# λ…ΈνŠΈλΆ       1,200,000원     5개
# 마우슀          35,000원   150개
# ν‚€λ³΄λ“œ          89,000원    42개

μ§„ν–‰λ₯  ν‘œμ‹œ

def show_progress(current, total):
    percent = current / total
    bar_length = 20
    filled = int(bar_length * percent)
    bar = "β–ˆ" * filled + "β–‘" * (bar_length - filled)

    return f"[{bar}] {percent:.1%} ({current}/{total})"

print(show_progress(30, 100))
# [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] 30.0% (30/100)

print(show_progress(75, 100))
# [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘] 75.0% (75/100)

둜그 λ©”μ‹œμ§€

import logging
from datetime import datetime

def log(level, message, **context):
    timestamp = datetime.now()
    ctx = ", ".join(f"{k}={v!r}" for k, v in context.items())
    log_msg = f"[{timestamp:%Y-%m-%d %H:%M:%S}] {level:8} | {message}"
    if ctx:
        log_msg += f" | {ctx}"
    print(log_msg)

log("INFO", "μ„œλ²„ μ‹œμž‘")
# [2025-01-11 14:30:45] INFO     | μ„œλ²„ μ‹œμž‘

log("ERROR", "DB μ—°κ²° μ‹€νŒ¨", host="localhost", port=5432, retry=3)
# [2025-01-11 14:30:45] ERROR    | DB μ—°κ²° μ‹€νŒ¨ | host='localhost', port=5432, retry=3

κΈˆμ•‘ ν‘œμ‹œ

def format_money(amount):
    return f"{amount:,}원"

def format_card_number(number):
    # μΉ΄λ“œλ²ˆν˜Έ: 1234-5678-9012-3456
    return f"{number[0:4]}-{number[4:8]}-{number[8:12]}-{number[12:16]}"

print(format_money(1234567))              # "1,234,567원"
print(format_card_number("1234567890123456"))
# "1234-5678-9012-3456"

8. μ„±λŠ₯ 비ꡐ

name = "홍길동"
age = 30

# 1. f-string (κ°€μž₯ 빠름)
f"{name}λ‹˜μ€ {age}μ„Έμž…λ‹ˆλ‹€"

# 2. .format() (쀑간)
"{}λ‹˜μ€ {}μ„Έμž…λ‹ˆλ‹€".format(name, age)

# 3. % ν¬λ§€νŒ… (느림)
"%sλ‹˜μ€ %dμ„Έμž…λ‹ˆλ‹€" % (name, age)

# 4. λ¬Έμžμ—΄ μ—°κ²° (κ°€μž₯ 느림)
name + "λ‹˜μ€ " + str(age) + "μ„Έμž…λ‹ˆλ‹€"

f-string이 κ°€μž₯ λΉ λ₯΄κ³  읽기 μ‰½μŠ΅λ‹ˆλ‹€!

9. κ³ κΈ‰ 기법

μ€‘μ²©λœ ν¬λ§€νŒ…

width = 10
precision = 2
value = 12.34567

# 동적 width와 precision
print(f"{value:{width}.{precision}f}")  # "     12.35"

# 동적 μ •λ ¬
align = "^"
print(f"{'Python':{align}{width}}")     # "  Python  "

λ”•μ…”λ„ˆλ¦¬ ν‚€ μ ‘κ·Ό

data = {
    "user": {
        "name": "홍길동",
        "profile": {
            "age": 30,
            "city": "μ„œμšΈ"
        }
    }
}

# μ€‘μ²©λœ λ”•μ…”λ„ˆλ¦¬
print(f"{data['user']['profile']['city']}")  # "μ„œμšΈ"

ν‘œν˜„μ‹ 디버깅 (Python 3.8+)

x = 10
y = 20

# = λ₯Ό 뢙이면 λ³€μˆ˜λͺ…κ³Ό 값을 λͺ¨λ‘ 좜λ ₯
print(f"{x=}")              # "x=10"
print(f"{y=}")              # "y=20"
print(f"{x + y=}")          # "x + y=30"

# ν•¨μˆ˜ 호좜
def square(n):
    return n ** 2

print(f"{square(5)=}")      # "square(5)=25"

# ν¬λ§€νŒ…κ³Ό ν•¨κ»˜
print(f"{x=:5d}")           # "x=   10"

10. μ£Όμ˜μ‚¬ν•­ (Python 3.12 이전과 이후)

PEP 701(Python 3.12, 2023.10)μ—μ„œ f-string의 μ—¬λŸ¬ μ œμ•½μ΄ ν•œκΊΌλ²ˆμ— μ œκ±°λ˜μ—ˆλ‹€. μ•„λž˜ 두 ν•­λͺ©μ€ 3.12+μ—μ„œλŠ” 더 이상 SyntaxErrorκ°€ μ•„λ‹ˆλ‹€.

λ°±μŠ¬λž˜μ‹œ μ‚¬μš©

items = ["a", "b", "c"]

# Python 3.11 μ΄ν•˜: ❌ SyntaxError
# Python 3.12 이상: βœ… 정상 λ™μž‘
print(f"{'\n'.join(items)}")

# 3.11 μ΄ν•˜ ν˜Έν™˜μ΄ ν•„μš”ν•˜λ‹€λ©΄ 미리 λ³€μˆ˜μ— ν• λ‹Ή
newline = "\n"
print(f"{newline.join(items)}")

주석과 멀티라인 ν‘œν˜„μ‹

value = 42

# Python 3.11 μ΄ν•˜: ❌ SyntaxError
# Python 3.12 이상: βœ… ν‘œν˜„μ‹ 내뢀에 주석/μ€„λ°”κΏˆ ν—ˆμš©
print(f"""{
    value  # 이 값은 μ€‘μš”ν•©λ‹ˆλ‹€
    + 1
}""")

같은 λ”°μ˜΄ν‘œ μž¬μ‚¬μš© (3.12+)

data = {"name": "홍길동"}

# Python 3.11 μ΄ν•˜: ❌ SyntaxError (μ™ΈλΆ€ f"...", λ‚΄λΆ€ "..." 좩돌)
# Python 3.12 이상: βœ… 정상 λ™μž‘
print(f"{data["name"]}")

ν˜Έν™˜μ„± 주의: μœ„ κΈ°λŠ₯듀은 Python 3.12+μ—μ„œλ§Œ λ™μž‘ν•œλ‹€. 3.11 μ΄ν•˜λ₯Ό 지원해야 ν•˜λŠ” 라이브러리/슀크립트라면 μ—¬μ „νžˆ PEP 701 이전 νŒ¨ν„΄(미리 λ³€μˆ˜μ— ν• λ‹Ή, λ‹€λ₯Έ λ”°μ˜΄ν‘œ μ‚¬μš© λ“±)을 따라야 ν•œλ‹€.

μš”μ•½ 정리

κΈ°λ³Έ 문법

name = "홍길동"
age = 30

f"{name}"                    # λ³€μˆ˜
f"{name.upper()}"            # λ©”μ„œλ“œ 호좜
f"{age + 10}"                # ν‘œν˜„μ‹
f"{'성인' if age >= 18 else 'λ―Έμ„±λ…„μž'}"  # 쑰건식

ν¬λ§€νŒ…

number = 1234567.89

f"{number:,}"                # 1,234,567.89 (천 λ‹¨μœ„)
f"{number:.2f}"              # 1234567.89 (μ†Œμˆ˜μ  2자리)
f"{number:,.2f}"             # 1,234,567.89 (μ‘°ν•©)

text = "Python"
f"{text:<10}"                # μ™Όμͺ½ μ •λ ¬
f"{text:>10}"                # 였λ₯Έμͺ½ μ •λ ¬
f"{text:^10}"                # κ°€μš΄λ° μ •λ ¬

λ³€ν™˜ μ§€μ •μž

value = "Hello\nWorld"

f"{value}"                   # 일반 (str)
f"{value!s}"                 # str() λͺ…μ‹œμ 
f"{value!r}"                 # repr() - λ””λ²„κΉ…μš©
f"{value!a}"                 # ascii() - ASCII λ³€ν™˜

디버깅 (Python 3.8+)

x = 10
f"{x=}"                      # "x=10"
f"{x + 5=}"                  # "x + 5=15"

λΉ λ₯Έ μ°Έμ‘°ν‘œ

μš©λ„ μ˜ˆμ‹œ κ²°κ³Ό
κΈ°λ³Έ f"{name}" 홍길동
천 λ‹¨μœ„ f"{1234567:,}" 1,234,567
μ†Œμˆ˜μ  f"{3.14159:.2f}" 3.14
νΌμ„ΌνŠΈ f"{0.856:.1%}" 85.6%
μ •λ ¬ f"{'Hi':<5}" Hi
λ‚ μ§œ f"{now:%Y-%m-%d}" 2025-01-11
디버깅 f"{x=}" x=10

참고 자료