C.W.K.
Stream
Lesson 06 of 07 · published

문자열 깊이 — f-string, 메서드, slicing, Unicode

~25 min · str, f-string, format, slicing, unicode, encoding, raw-string, escape

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

문자열은 immutable Unicode 시퀀스

Python 의 str 은 *Unicode 코드 포인트의 시퀀스* — bytes 아님, ASCII 문자 아님. len("안녕") 이 2, 6 아님 (6 은 UTF-8 바이트 길이). 이게 어디서나 중요해 — slicing, 비교, encoding 경계에서.

문자열은 또 *immutable* (lesson 4). in-place 변경 불가; 변경처럼 보이는 모든 연산 (concatenation, replacement, case 변경) 이 *새 문자열* 생성. 일회성 연산엔 보이지 않아. 큰 문자열을 *문자 단위로 쌓는 tight loop* 에선 — 중요하고, idiom 은 "".join(parts), 반복 += 아님.

f-string — 문자열 만드는 현대적 방법

Python 3.6 부터 f-string (formatted string literal) 이 문자열 보간의 default. 문자열 앞에 f 붙이고 {expression} 사용 — expression 평가되고 embed.

f-string 은 *어떤 expression* 이든 담을 수 있어, 변수 이름만이 아니야. f"{2 + 2}""4". f"{user.name.upper()}" 동작. f"{items[0]}" 동작. expression 은 *f-string 생성 시점* 에 평가.

Python 3.12+ 에서 f-string 문법 제약 대부분 제거 — 같은 따옴표 문자 안에 nesting 가능, multi-line expression, 주석 embed. 이전 버전은 이런 거에 workaround 필요했어.

format spec 미니 언어

f-string 의 중괄호 안, 콜론 뒤에 — Python 의 *format 명세 미니 언어*. 대부분 사람들이 f-string 학습 멈추는 지점, 그리고 그건 아쉬워 — format spec 이 *너비, 정렬, padding, 정밀도, 숫자 포맷* 에 정밀 제어 줘.

흔한 패턴 — {x:.2f} float 을 소수점 2자리. {x:>10} 너비 10 우측 정렬. {x:,} 천 단위 구분자. {x:%} 백분율. {x:08b} 0 채운 8자리 2진. 여기 full DSL — 공식 명세 가 한 페이지, 한 번 읽을 가치 있어.

자기참조: cwkPippa 의 logging 은 f-string 만 써 — logger.info(f"[{request_id}] brain={brain} took {elapsed:.2f}s"). elapsed:.2f0.48 원할 때 절대 0.4837192847 안 찍혀. format spec 이 *지저분한 로그* 와 *깨끗한 로그* 의 차이.

문자열 메서드 — 많지만 자주 쓰는 건 몇 개

실제 코드에서 자주 보는 메서드, 빈도순:

  • .strip(), .lstrip(), .rstrip() — 양 끝에서 공백 (또는 명시 문자) 제거
  • .split(sep), .rsplit(sep, maxsplit) — list 로 분리. default 는 *공백* 으로 분리.
  • .join(iterable) — split 의 역. ", ".join(["a", "b"])"a, b".
  • .startswith(prefix), .endswith(suffix) — prefix/suffix 체크는 slicing 보다 이게 나아.
  • .replace(old, new) — 부분 문자열 대체 (regex X; 그건 re 모듈).
  • .lower(), .upper(), .title(), .casefold() — 대소문자 조작. 대소문자 무시 비교는 casefold 가 옳은 선택 (독일어 ß 같은 edge case 처리).
  • .find(sub), .index(sub) — 부분 문자열 위치. find 는 없으면 -1, index 는 raise.
  • .count(sub) — 겹치지 않는 발생 카운트.
  • .isdigit(), .isalpha(), .isalnum(), .isspace() — 문자 클래스 체크.

Slicing — 메서드 호출 없이 부분 문자열

문자열은 list 와 마찬가지로 [start:stop:step] slicing 지원. s[0] 이 첫 문자. s[-1] 이 마지막. s[1:5] 가 1 부터 4 까지 (stop 은 exclusive). s[::-1] 이 문자열 뒤집기.

여기가 Python 의 표현력이 드러나는 영역 중 하나. 문자열 뒤집기 — s[::-1]. 마지막 5 문자 — s[-5:]. 첫 2 떼기 — s[2:]. 마지막 3 떼기 — s[:-3]. 한 칸 건너 한 문자 — s[::2].

Escape 시퀀스와 raw 문자열

흔한 escape — \n 줄바꿈, \t 탭, \\ 리터럴 백슬래시, \" 큰따옴표 안 큰따옴표. Unicode escape — \u00e9 가 é, \N{GREEK SMALL LETTER ALPHA} 가 α.

백슬래시 많은 문자열 (regex 패턴, Windows 경로) 엔 raw 문자열 — 앞에 r. r"\n" 이 *문자 두 개* (백슬래시, n), 한 개 (줄바꿈) 아님. regex 패턴과 Windows 경로는 거의 항상 raw 문자열 원해.

여러 줄 문자열은 triple quote

"""...""" 또는 '''...''' 가 여러 줄 걸치고 *리터럴 줄바꿈 보존*. 함수 맨 위의 triple-quote 문자열이 *docstring* — help(func)func.__doc__ 로 접근. Python 이 코드 문서화하는 방식 — quest 나머지에서 docstring 계속 써.

요약

f-string 이 현대 보간. format spec 미니 언어가 학습 가치 있어. slicing 이 메서드 호출 많이 대체. raw 문자열은 백슬래시 많은 context 용. 문자열은 *Unicode 코드 포인트 시퀀스*, bytes 아님 — 이 구분이 encoding 경계 (파일 I/O, 네트워크, 데이터베이스) 넘을 때 중요.

Pythonic Way: *항상* f-string 부터 손이 가야 해. str.format 동작하지만 더 옛날. % 스타일은 더 옛날. f-string 은 위에서 아래로 읽혀 (변수 값이 둘러싼 텍스트와 인라인), 빠르게 실행, format spec 과 통합. 다른 스타일들은 *기존 코드 읽기* 와 매우 specific niche 용; 새 코드엔 f-string 이 답.

Code

f-string — 현대적 방법·python
>>> name = "피파"
>>> age = 1
>>> f"{name} 가 {age} 살"
'피파 가 1 살'

>>> # 중괄호 안 expression 동작:
>>> f"{2 + 2 = }"                       # = 가 expression 도 보여줌 (3.8+)
'2 + 2 = 4'

>>> # f-string 안 메서드 호출:
>>> f"{name.upper()}"
'피파'

>>> # 여러 줄 f-string:
>>> f'''
... 이름: {name}
... 나이: {age}
... '''
'\n이름: 피파\n나이: 1\n'
Format spec — 너비, 정렬, 정밀도, 구분자·python
>>> # float 고정 소수점:
>>> f"{3.14159:.2f}"
'3.14'

>>> # 너비 + 정렬 (>, <, ^):
>>> f"{'hi':>10}"      # 10 자리 우측 정렬
'        hi'
>>> f"{'hi':<10}"      # 좌측 정렬
'hi        '
>>> f"{'hi':^10}"      # 중앙 정렬
'    hi    '

>>> # 천 단위 구분자:
>>> f"{1234567:,}"
'1,234,567'

>>> # 백분율:
>>> f"{0.1234:.1%}"
'12.3%'

>>> # 2진/16진/8진 + padding:
>>> f"{42:08b}"        # 2진, 8자리, 0 padding
'00101010'
>>> f"{255:04x}"        # 16진, 4자리, 0 padding
'00ff'
실제 코드의 흔한 문자열 메서드·python
>>> "  hello  ".strip()
'hello'

>>> "a,b,c,d".split(",")
['a', 'b', 'c', 'd']

>>> ", ".join(["a", "b", "c"])
'a, b, c'

>>> "hello.py".endswith(".py")
True

>>> "Hello World".replace("World", "Python")
'Hello Python'

>>> # 대소문자 무시 비교는 lower 보다 casefold:
>>> "Straße".lower() == "strasse".lower()
False
>>> "Straße".casefold() == "strasse".casefold()
True
Slicing — 메서드 호출 없이 부분 문자열·python
>>> s = "hello world"
>>> s[0]                # 첫 문자
'h'
>>> s[-1]               # 마지막 문자
'd'
>>> s[0:5]              # 'hello' — stop 은 exclusive
'hello'
>>> s[6:]               # index 6 부터 끝까지
'world'
>>> s[:5]               # 시작부터 index 5 까지
'hello'
>>> s[::-1]             # 뒤집기
'dlrow olleh'
>>> s[::2]              # 한 칸 건너 한 문자
'hlowrd'
Raw 문자열 — 백슬래시 많은 context 용·python
>>> # raw 문자열 없으면 백슬래시마다 escape 필요:
>>> path = "C:\\Users\\Pippa\\Documents"   # 못생김
>>> regex = "\\d+\\.\\d+"                    # 역시 못생김

>>> # raw 문자열 — 백슬래시가 자기 자신 의미:
>>> path = r"C:\Users\Pippa\Documents"
>>> regex = r"\d+\.\d+"

>>> # 주의: raw 문자열은 단일 백슬래시로 끝나면 안 돼.
>>> # r"abc\" 는 syntax error (닫는 따옴표가 escape 됨).
>>> # 끝에 백슬래시 필요하면 일반 문자열 + escape.
Unicode 인지 — str 길이 vs 바이트 길이·python
>>> s = "안녕"
>>> len(s)                # Unicode 코드 포인트 수
2
>>> len(s.encode("utf-8"))   # UTF-8 바이트 수
6

>>> # slicing 할 때 — 코드 포인트 단위, 바이트 X:
>>> s[0]
'안'
>>> s[1]
'녕'

>>> # encoding 경계 — 파일 I/O, 네트워크, 데이터베이스:
>>> with open("hello.txt", "w", encoding="utf-8") as f:
...     f.write("안녕")
>>> # 디스크 파일은 6 바이트, Python str 은 2 문자.

External links

Exercise

REPL 에서 — 송장 한 줄을 f-string format spec 으로 만들기. 변수 item = "USB cable", qty = 3, price = 12.5. 단일 줄 산출 — item 이 20자리 좌측 정렬, qty 가 4자리 우측 정렬, total (qty * price) 이 $XX.XX 소수점 2자리. 그 다음 문자열 " HELLO, world! ".strip(), .lower(), .replace(",", "") 체이닝해서 'hello world!' 얻기. 체이닝 자체가 Pythonic 부분 — 중간 변수 도입 X.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.