본문으로 건너뛰기
김신건의 로그

[Python] str: 문자열과 f-string

· 수정 · 📖 약 1분 · 489자/단어 #python #string #str #f-string #basics
python string, python str, f-string, 문자열 포매팅, string formatting

정의

Python의 str불변(immutable) 유니코드 문자열이다. 내부는 PEP 393 이후 “유연한 문자열 표현(flexible string representation)“으로, 문자열이 사용하는 최대 코드포인트에 따라 1, 2, 4바이트 폭을 자동 선택한다.

리터럴 종류

s1 = 'single quotes'
s2 = "double quotes"
s3 = '''triple
multiline'''
s4 = """triple double"""

# raw string: 이스케이프 미적용
r = r"C:\Users\koa\file.txt"

# bytes (str 아님)
b = b"hello"

# f-string (formatted)
name = "Alice"
f = f"Hello, {name}"

f-string (PEP 498)

Python 3.6+ 의 핵심 포매팅 방식.

python
name = "Alice"
age = 30
pi = 3.14159

print(f"Hello, {name}, age {age}")
print(f"{pi:.2f}")           # 소수점 2자리
print(f"{age:05d}")          # 0 패딩 5자리
print(f"{name:>10}")         # 우측 정렬 10폭
print(f"{name!r}")           # repr() 적용
print(f"{age=}")             # 3.8+: 이름과 값 동시 출력
결과
Hello, Alice, age 30
3.14
00030
   Alice
'Alice'
age=30

f-string 안의 표현식

items = [1, 2, 3, 4]
f"합계: {sum(items)}"          # 임의 표현식 가능
f"{'-' * 20}"                  # 연산도 가능
f"{ {1, 2, 3} }"               # 중괄호 충돌은 공백으로 분리

Python 3.12+ 에서는 같은 인용부호 중첩, 백슬래시, 멀티라인이 허용되었다(PEP 701).

문자열 메서드 핵심

메서드동작예시
.upper() / .lower()대/소문자 변환"abc".upper() == "ABC"
.strip([chars])양끝 공백/문자 제거" x ".strip() == "x"
.lstrip() / .rstrip()왼쪽/오른쪽만
.split(sep)분할 → 리스트"a,b,c".split(",") == ["a", "b", "c"]
.join(iterable)결합",".join(["a", "b"]) == "a,b"
.replace(old, new)치환"aaa".replace("a", "b") == "bbb"
.startswith() / .endswith()접두/접미 검사
.find(sub) / .index(sub)위치, -1 / 예외
.count(sub)출현 횟수
.isdigit() / .isalpha() / .isspace()문자 종류
.title() / .capitalize() / .swapcase()케이스 변환
.zfill(n)0 패딩"7".zfill(3) == "007"
.format(*args, **kwargs)구식 포매팅
python
s = "Hello, World"
print(s.lower())
print(s.replace("World", "Python"))
print(s.split(", "))
print("-".join(["a", "b", "c"]))
print(s.find("World"))
결과
hello, world
Hello, Python
['Hello', 'World']
a-b-c
7

슬라이싱과 인덱싱

문자열은 시퀀스라서 정수 인덱스와 슬라이스가 가능하다.

python
s = "Python"
print(s[0])
print(s[-1])
print(s[1:4])
print(s[::-1])     # 뒤집기
print(s[::2])      # 2칸씩
결과
P
n
yth
nohtyP
Pto

불변성과 연결 성능

# BAD: 매번 새 객체 생성, O(n^2)
result = ""
for s in many_strings:
    result += s

# GOOD: join, O(n)
result = "".join(many_strings)

# 또는 io.StringIO
from io import StringIO
buf = StringIO()
for s in many_strings:
    buf.write(s)
result = buf.getvalue()

CPython 구현 최적화로 += 누적도 빠를 수 있지만 보장되지 않는다. join 사용이 정석.

인코딩

str는 유니코드 추상이고, 실제 바이트는 bytes다.

python
s = "안녕"
b = s.encode("utf-8")
print(b)
print(len(s), "chars,", len(b), "bytes")

# 다시 str로
print(b.decode("utf-8"))
결과
b'\xec\x95\x88\xeb\x85\x95'
2 chars, 6 bytes
안녕

len(str)코드포인트 수, len(bytes)바이트 수다. 한글은 UTF-8에서 코드포인트 1개당 3바이트.

문자열 정규화

같은 글자가 다른 코드포인트 조합으로 표현될 수 있다 (macOS NFD 등).

import unicodedata
nfc = unicodedata.normalize("NFC", text)  # 결합형
nfd = unicodedata.normalize("NFD", text)  # 분해형

파일명/유저 입력 비교 시 정규화하지 않으면 같은 글자도 다르게 보일 수 있다.

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기