Skip to content
This page has been auto-translated and may contain errors.View in English

문자열

거의 모든 프로그램에는 텍스트가 나타납니다. 이름, 메시지, 점수, 레이블 등이 있습니다. Python에서는 따옴표로 감싼 모든 텍스트를 문자열이라고 부릅니다. 작은따옴표든 큰따옴표든 같은 방식으로 작동합니다.

문자열은 Python의 기본 텍스트 타입입니다. 사용자 이름부터 URL 경로, 형식화된 출력까지 모든 것을 다룹니다. 작은따옴표와 큰따옴표 모두 동일한 결과를 만들며, 선택은 스타일의 문제입니다.

str은 모든 시스템 경계에 존재합니다: 터미널 입출력, 파일 내용, 네트워크 응답, 직렬화된 데이터에 말이죠. 이는 Python의 불변(생성 후 변경 불가능)인 유니코드 시퀀스 타입입니다. 두 따옴표 스타일 모두 동일한 객체를 생성하므로 선택은 순전히 스타일 문제입니다.

python
greeting = "Hello, world"
username = 'alice'

따옴표 선택이 중요한 경우는 텍스트에 따옴표가 포함되어 있을 때입니다. 반대 스타일을 사용하면 이스케이프 처리할 필요가 없습니다:

커뮤니티의 관례는 큰따옴표를 사용하는 것입니다. 스타일을 바꿀 실질적인 이유는 내용에 그 문자가 포함되어 있을 때 백슬래시 이스케이프를 피하기 위함입니다:

관례는 큰따옴표이고, Black이나 Ruff 같은 포맷터는 자동으로 이를 강제합니다. 직접 작성할 때 스타일을 바꾸는 유일한 이유는 내용에 구분자가 포함되어 있을 때 백슬래시 이스케이프를 피하기 위함입니다:

python
note = "It's a great day"      # apostrophe inside, use double quotes
message = 'She said "hello"'   # double quotes inside, use single quotes
escaped = "She said \"hello\""  # or escape with a backslash

불변성

문자열은 불변입니다: 한 번 생성하면 변경할 수 없습니다. 문자열을 만드는 순간 영구적으로 고정되어 있다고 생각하세요. 문자열을 수정하는 것처럼 보이는 모든 연산은 실제로 완전히 새로운 것을 생성합니다. 원본은 정확히 그대로 유지됩니다.

문자열은 불변입니다: 어떤 메서드도 문자열을 제자리에서 수정하지 않습니다. 텍스트를 변환하는 모든 연산은 새로운 문자열을 반환하고 원본은 그대로 둡니다. 실질적인 결과는 어디에도 할당하지 않은 메서드 호출이 아무것도 영향을 주지 않는다는 것입니다.

str 객체는 불변이므로, 생성 후 내용이 고정되고 아무것도 이를 변경할 수 없습니다. 이는 문자열에 두 가지 특성을 부여합니다: 해시 가능(내용이 절대 변하지 않는 값을 그 내용으로 분류할 수 있으며, 이것이 문자열을 딕셔너리 키나 집합 멤버로 사용할 수 있게 합니다)하고, 이름 간에 공유된 문자열을 아무도 변경할 수 없으므로 복사 없이 안전하게 주고받을 수 있습니다.

python
name = "alice"
name = name.upper()   # "ALICE" is a new string; "alice" is unchanged

직접적인 결과: 특정 위치의 문자를 변경할 수 없습니다. 시도하면 Python이 오류를 발생시킵니다.

python
name = "alice"
name[0] = "A"   # TypeError: 'str' object does not support item assignment

수정된 문자열을 얻으려면 슬라이싱이나 메서드를 사용하여 새로운 문자열을 만드세요. 둘 다 아래에서 다룹니다.

문자 할당을 시도하면 제약을 직접 보여줍니다:

python
name = "alice"
name[0] = "A"   # TypeError: 'str' object does not support item assignment

수정된 버전이 필요할 때 표준 도구는 위치 편집을 위한 슬라이싱과 연결, 치환을 위한 replace()입니다. 둘 다 새로운 문자열을 생성하고 원본은 그대로 둡니다.

위치에 할당(name[0] = "A")하면 항상 TypeError를 발생시키며, 예외가 없습니다. 위치 편집을 위해서는 변경하려는 부분 주변을 슬라이싱하여 새 문자열을 만드세요: name[:1].upper() + name[1:]은 첫 문자를 대문자로 만듭니다. 문자열의 아무 곳에나 있는 치환을 위해서는 replace()를 사용합니다.

Juno불변성 문자열은 존재한 후 절대 변하지 않습니다. 이를 편집하는 것처럼 보이는 모든 것은 대신 새로운 문자열을 돌려주므로, 결과를 할당하지 않으면 사라집니다. 초기에 나를 당황하게 했던 하나: name[0] = "A"는 작동하지 않고 TypeError를 발생시킵니다.
Juno불변성 어떤 문자열 메서드도 제자리에서 편집하지 않으며, 모두 새로운 문자열을 반환하고 원본은 그대로 둡니다. 따라서 name.upper() 혼자서는 유용한 작업을 하지 않으며, 반드시 할당해야 합니다. 그리고 name[0] = "A"TypeError를 발생시키므로, 제자리 문자 교환이 없습니다.
Juno불변성 불변성이 문자열을 해시 가능하게 만들어서 딕셔너리 키로 작동하고, 복사 없이 공유하기에 안전합니다. 실질적인 결과: 모든 변환 메서드의 결과를 할당하세요. 원본을 건드리지 않으니까요. 위치 편집을 위해서는 해당 자리 주변을 슬라이싱하여 재구성하세요. 항목 할당은 항상 TypeError를 발생시키니까요.

인덱싱과 슬라이싱

문자열의 모든 문자에는 0부터 시작하는 번호 위치가 있습니다. 대괄호 안에 그 위치 번호를 넣어 개별 문자를 읽을 수 있습니다. 음수는 끝에서 거꾸로 셉니다.

문자열은 0 기반 인덱싱을 가진 시퀀스입니다. 음수 인덱스는 끝에서 역순으로 셉니다. 슬라이싱은 단일 표현식에서 연속된 범위를 추출하며, 범위를 벗어난 값에 대해 절대 오류를 발생시키지 않습니다.

문자열은 인덱싱하고 슬라이싱할 수 있는 정렬된 시퀀스처럼 작동합니다. 단일 위치 읽기(s[i])는 인덱스가 끝을 넘으면 IndexError를 발생시킵니다. 슬라이싱(s[start:stop:step])은 다르게 작동합니다: 범위를 벗어난 경계는 자동으로 존재하는 것으로 압축되므로, 슬라이스는 절대 IndexError를 발생시킬 수 없습니다. 그 차이가 실질적인 것입니다: 인덱스 접근은 엄격하고, 슬라이싱은 관대합니다.

python
word = "Python"
#       012345

print(word[0])    # "P"
print(word[2])    # "t"
print(word[5])    # "n"
print(word[-1])   # "n"  (last character)
print(word[-2])   # "o"  (second to last)

-1은 항상 마지막 문자, -2는 마지막에서 두 번째이고, 계속 그렇습니다. 정확한 길이를 알지 못할 때 문자열의 끝에 접근하려고 할 때 유용합니다.

음수 인덱스는 래핑됩니다: -1len(s) - 1, -2len(s) - 2입니다. 길이를 수동으로 계산하고 싶지 않을 때 끝 기준 접근에 가장 유용합니다. 범위를 벗어난 음수 인덱스는 여전히 IndexError를 발생시키며, 양수도 마찬가지입니다.

음수 인덱스는 경계 확인 전에 len(s) + i로 변환되므로, -1은 마지막 문자에, -2는 그 이전 문자에 도달합니다. 범위를 벗어나면 양수든 음수든 IndexError를 발생시킵니다: 오직 슬라이싱만 그를 용서합니다. 평문 인덱싱은 그렇지 않습니다.

슬라이싱은 청크를 추출합니다. [start:stop]start를 포함하고 stop을 제외합니다:

python
word = "Python"

print(word[0:2])   # "Py"     (positions 0 and 1)
print(word[2:])    # "thon"   (position 2 to end)
print(word[:3])    # "Pyt"    (start to position 2)
print(word[:])     # "Python" (a copy of the whole string)
print(word[::2])   # "Pto"    (every second character)
print(word[::-1])  # "nohtyP" (reversed)

가장 많이 사용할 세 가지 패턴: 처음 n개 문자를 위한 word[:n], 위치 n 이후의 모든 것을 위한 word[n:], 마지막 n개 문자를 위한 word[-n:]. word[::-1]은 문자열을 역순으로 합니다. 처음에는 이상해 보이지만 관례적인 Python이고, 자주 볼 수 있습니다.

직접 인덱싱과 달리 슬라이싱은 절대 IndexError를 발생시키지 않습니다. Python은 범위를 벗어난 인덱스를 자동으로 압축하므로, 짧은 문자열에 word[100:]을 사용하면 충돌하는 대신 ""를 반환합니다. step 인수는 스트라이드를 제어합니다: word[::2]는 모든 다른 문자를 가져가고, word[::-1]은 역순으로 이동합니다.

s[start:stop:step]에서, 생략한 부분은 "이동 방향의 자연스러운 끝"으로 기본값이 설정되며, 고정된 0len()이 아닙니다. 양수 step은 처음부터 끝을 의미하고, 음수 step은 뒤집혀서 start는 마지막 문자가 되고 stop은 앞에서 벗어납니다. 이것이 s[::-1]이 경계를 작성하지 않고도 전체 문자열을 역순으로 이동하는 이유이고, s[::-2]가 역순으로 모든 다른 문자를 주는 이유입니다.

Juno인덱싱과 슬라이싱 위치는 0부터 시작하므로, word[0]은 첫 문자이고 word[-1]은 마지막 문자입니다. 슬라이스는 범위를 가져갑니다: word[start:stop]start를 유지하고 stop 바로 앞에서 멈춥니다. word[::-1]은 문자열을 역순으로 하는데, 처음에는 이상해 보이다가 계속 사용하게 됩니다.
Juno인덱싱과 슬라이싱 0부터 인덱싱하거나 음수로 끝에서부터 인덱싱하세요. word[-1]은 마지막 문자입니다. 슬라이스는 start를 포함하고 stop을 제외하는 범위를 가지며, 세 번째 step은 스트라이드를 설정하므로 word[::-1]은 역순으로 합니다. 기억할 가치가 있는 함정: 끝을 넘어 인덱싱하면 IndexError를 발생시키지만, 슬라이싱하면 실패하는 대신 있는 것을 반환합니다.
Juno인덱싱과 슬라이싱 평문 인덱싱은 엄격하며 범위를 벗어나면 IndexError를 발생시키고, 슬라이싱은 관대하며 존재하는 것으로 압축되므로 word[100:]은 발생시키는 대신 ""를 반환합니다. 슬라이스 부분을 생략하면 step의 방향에 대한 자연스러운 끝으로 기본값이 설정됩니다. 이것이 word[::-1]이 작성된 경계 없이 역순으로 하는 이유입니다. 빈 또는 짧은 입력에서 충돌하고 싶지 않을 때 슬라이스에 도달하세요.

필수 문자열 메서드

문자열에는 내장된 메서드 집합이 있습니다: 모든 문자열 값에서 직접 호출하는 연산입니다. 문자열(또는 이를 보유한 변수)을 쓰고, 점을 쓴 다음, 메서드 이름을 씁니다. 각 메서드는 새로운 문자열을 반환합니다. 원본은 절대 변경되지 않습니다.

문자열 메서드는 str 타입에 부여된 함수입니다. 문자열이 불변이므로, 모든 메서드는 원본을 수정하는 대신 새로운 문자열을 반환합니다. 할당하거나 어디에도 전달하지 않은 메서드 호출은 지속적인 영향을 주지 않습니다.

모든 변환 메서드는 새로운 str을 반환하고 원본을 그대로 두며, 이는 불변성에서 직접 따릅니다. 또한 코드 포인트(원본 바이트가 아닌 문자 자체)에서 작동하므로, 메서드는 특별히 할 일 없이 악센트 표시와 비라틴 텍스트에서 올바르게 작동합니다. 유지할 트레이드오프: 각 메서드는 새로운 문자열을 할당하므로, 많은 메서드를 큰 텍스트에서 연결하면 많은 할당을 의미합니다.

대소문자

python
text = "Hello, World"

text.lower()       # "hello, world"
text.upper()       # "HELLO, WORLD"
text.title()       # "Hello, World"  (each word capitalised)
text.capitalize()  # "Hello, world"  (first word only)

lower()upper()는 가장 많이 사용할 두 메서드입니다. lower()는 특히 텍스트 비교에 유용합니다: "Alice""alice"는 양쪽에서 .lower()를 호출하면 같은 것이 됩니다.

lower()는 비교 또는 저장 전의 표준 정규화 단계입니다. title()은 축약형에서 실패하는 대략적인 규칙을 사용하여 각 단어의 첫 글자를 대문자로 만듭니다: "it's""It'S"가 됩니다. 이를 표시만 하는 형식으로 취급하세요.

lower()는 유니코드 전체 대소문자 변환을 적용합니다. 대소문자를 구분하지 않는 비교에는 casefold()가 더 정확합니다: lower()는 건너뛰는 추가 변환(예: 독일어 ß는 ss가 됨)을 적용합니다. title()은 비알파벳 문자 뒤에 대문자로 만들어서 축약형과 하이픈이 있는 이름을 잘못 처리합니다. 올바른 제목 대문자화를 위해서는 로직을 수동으로 구현하세요.

공백

python
text = "  hello  "

text.strip()    # "hello"    (both sides)
text.lstrip()   # "hello  "  (left only)
text.rstrip()   # "  hello"  (right only)

strip()은 문자열의 양쪽 끝에서 공백을 제거합니다. 사용자 입력이나 파일의 텍스트를 처리할 때마다 거의 사용할 것입니다. 왜냐하면 불필요한 공백이 조용한 실패를 일으키기 때문입니다: "alice" != "alice ".

strip()은 모든 선행 및 후행 공백을 제거합니다: 공간, 탭, 줄바꿈. 방향 변형은 한쪽만 청소하고 싶을 때 유용합니다. 예를 들어 들여쓰기는 건드리지 않고 후행 줄바꿈만 제거합니다. 셋 모두 특정 문자를 대신 제거하도록 선택적 문자 인수를 허용합니다.

인수가 없으면, strip()은 순수 공간뿐만 아니라 비ASCII 공백을 포함하여 양쪽 끝의 모든 종류의 공백을 제거합니다. 문자 인수를 사용하면 그 끝에서 모든 그 문자를 제거하고, 이것이 함정입니다: 인수는 프리픽스를 일치시키는 것이 아니라 제거할 문자 집합입니다. "xxhelloxx".strip("x")"hello"를 반환하지만, "https://".strip("https")는 프리픽스 "https"를 제거하지 않으며, 양쪽 끝에서 모든 h, t, p, s를 제거하고 "://"를 반환합니다. 알려진 프리픽스나 서픽스를 제거하려면 대신 removeprefix()removesuffix()를 사용하세요.

찾기

python
text = "Hello, world"

text.find("world")         # 7
text.find("Python")        # -1  (not found)
text.count("l")            # 3
text.startswith("Hello")   # True
text.endswith("world")     # True

find()는 문자열 내에서 텍스트 부분이 시작되는 위치를 반환합니다. 없으면 -1을 반환합니다. 문자열이 특정 항목으로 시작하거나 끝나는지만 신경 쓸 때 startswith()endswith()를 사용하세요.

find()는 첫 일치의 시작 인덱스를 반환하거나 -1을 반환합니다. -1 규칙을 사용하면 확인 없이 슬라이싱이나 산술에서 결과를 직접 사용할 수 있습니다. startswith()endswith()는 각각 문자열의 튜플을 허용하므로, 한 호출에서 여러 프리픽스나 서픽스를 테스트할 수 있습니다.

find()는 왼쪽에서 오른쪽으로 스캔하고 일치가 없을 때 -1을 반환합니다. index()는 동일한 검색을 하지만 -1을 반환하는 대신 ValueError를 발생시킵니다: 일치가 없으면 코드에 버그가 있고 멈추기를 원할 때는 index()를 선택하세요. 부재가 정상 입력이고 확인할 때는 find()를 선택하세요. 순수한 "이것으로 시작하거나 끝나는가" 질문에는 startswith()endswith()를 사용하세요. find()in 확인보다 의도를 명확히 하고 첫 불일치에서 멈추니까요.

교체

python
text = "Hello, world"

text.replace("world", "Python")   # "Hello, Python"
text.replace("l", "L")            # "HeLLo, worLd"  (all occurrences)
text.replace("l", "L", 1)         # "HeLlo, world"  (first only)

replace()는 텍스트의 한 부분을 다른 것으로 교체하고 새로운 문자열을 돌려줍니다. 원본은 변경되지 않습니다. 첫 번째 발생만 교체하려면 세 번째 인수를 전달하세요.

replace()는 기본적으로 모든 겹치지 않는 발생을 교체합니다. count 인수는 교체되는 갯수를 제한합니다. 새로운 문자열을 반환하므로, 호출을 연결할 수 있습니다: text.replace("a", "A").replace("e", "E")는 두 치환을 순서대로 적용합니다.

replace()는 패턴이 아닌 리터럴 부분 문자열과 일치하므로, 정규식을 수행하지 않고 인수의 모든 문자를 그 자체로 취급합니다. 왼쪽에서 오른쪽으로 겹치지 않는 일치를 교체하는데, 놀랄 수 있습니다: "aaa".replace("aa", "b")"ba"를 제공하며 "bb"는 아닙니다. 왜냐하면 두 번째 aa가 첫 일치와 겹치기 때문입니다. count 인수는 교체 갯수를 제한하고, 모든 호출이 새로운 문자열을 반환하므로 이를 연결할 수 있습니다: text.replace(",", "").replace(" ", "_").

분할과 결합

split()은 구분자에서 문자열을 조각으로 자르고 이를 리스트로 반환합니다. 무엇을 자를지 말합니다:

split()은 구분자에서 분할하고 세그먼트를 리스트로 반환합니다. 인수 없이 호출하면 모든 공백 실행에서 분할하고 여러 연속 공백의 빈 문자열을 버립니다:

split(sep)은 왼쪽에서 오른쪽으로 스캔하여 sep의 모든 겹치지 않는 발생에서 분할합니다. 인수가 없으면 다른 알고리즘을 사용합니다: 모든 공백 실행에서 분할하고 결과에서 선행 및 후행 공백을 제거합니다. rsplit(sep, n)은 오른쪽에서 분할하며, 점으로 구분된 경로나 네임스페이스 식별자의 마지막 세그먼트를 분리하는 데 유용합니다.

python
csv_row = "Alice,28,서울"
parts = csv_row.split(",")     # ["Alice", "28", "서울"]

"  hello   world  ".split()   # ["hello", "world"]

split()은 리스트, 값의 정렬된 시퀀스를 반환합니다. 리스트는 자신의 리스트 장이 있으며, 지금은 split()이 생성하고 join()이 소비하는 부분의 시퀀스로 취급하세요.

join()은 역을 합니다: 문자열 리스트를 하나로 결합합니다. join() 앞의 문자열은 각 항목 사이에 배치됩니다:

python
words = ["Hello", "world"]

" ".join(words)    # "Hello world"
", ".join(words)   # "Hello, world"
"".join(words)     # "Helloworld"

기억할 패턴: separator.join(list_of_strings). 구분자는 왼쪽에, 리스트는 오른쪽에 있습니다. " ".join(words)는 각 단어 사이에 공백을 넣습니다. "".join(words)는 사이에 아무것도 없이 이를 접합니다.

join()은 여러 조각에서 단일 문자열을 조립할 때마다 올바른 도구입니다. 각 단계에서 새로운 문자열을 만드는 대신 단일 할당을 수행합니다. 두세 개의 문자열의 경우, +는 완벽하게 괜찮습니다. 상당한 크기의 리스트를 갖고 있으면 join()에 도달하세요.

join()은 조각을 한 번 이동하고, 총 크기를 계산하고, 결과를 한 번만 할당하고, 모든 것을 작성합니다. 반복된 +를 루프에서 같은 문자열을 만드는 것은 비싼 형태입니다: 문자열이 변경될 수 없으므로, 각 +는 신선한 문자열을 할당하고 지금까지 모든 것을 이 안으로 복사하므로, 비용은 조각 갯수의 제곱으로 증가합니다. 소수의 문자열에서는 아무도 주목하지 않지만, 수천 개에서는 빠른 연산을 느린 것으로 바꿉니다. 이를 방지하는 규칙: 조각을 리스트에 수집하고 끝에서 join()을 한 번 하세요. 루프에서 절대 문자열 +=를 하지 마세요.

Juno필수 문자열 메서드 이들 각각은 새로운 문자열을 반환하므로, 결과를 할당하거나 사라집니다. 매일 도달할 소수: 대소문자를 위한 .lower().upper(), 불필요한 공백을 다듬기 위한 .strip(), 텍스트를 찾기 위한 .find()(없을 때 -1 반환), 텍스트를 교체하기 위한 .replace(), 문자열을 분리하고 다시 모으기 위한 .split()sep.join().
Juno필수 문자열 메서드 이들 모두 새로운 문자열을 반환하고 어떤 것도 변경하지 않으므로, 이를 연결하거나 할당하세요. 함정들을 명확하게 해두세요: .strip("x")는 프리픽스가 아닌 다듬을 문자 집합을 가져가고, .split() 인수 없음은 공백 실행을 무너뜨립니다. 많은 조각을 조립하려면, 리스트를 만들고 sep.join()을 하세요.
Juno필수 문자열 메서드 실제 코드를 물어뜯는 두 함정: .strip(chars)는 프리픽스가 아닌 끝에서 문자 집합을 제거하므로 프리픽스를 의도할 때는 removeprefix()를 사용하세요. 루프에서 +=로 문자열을 만드는 것은 느린 형태이므로, 리스트에 수집하고 한 번만 join()을 하세요. 비교를 위해서는 .lower()보다는 .casefold()로 정규화하세요. .title()은 축약형을 망쳐서 표시만 하는 것으로 취급하세요.

f-문자열

f-문자열은 값을 텍스트 직접 내에 포함합니다. 여는 따옴표 전에 f를 넣고, 중괄호에 모든 변수나 표현식을 감쌉니다. Python은 코드가 실행될 때 이를 채워 넣습니다. 값 뒤에 콜론을 추가하여 표시 방식을 제어할 수도 있습니다.

f-문자열은 런타임에 {} 안의 모든 표현식을 평가하고 결과를 문자열로 변환합니다. 중괄호 안의 콜론은 형식 스펙을 도입합니다: 소수 자리, 정렬, 숫자 형식을 제어하는 컴팩트 문법입니다.

f-문자열의 각 {}는 결과적으로 값의 자신의 __format__ 메서드(Python이 값을 형식화할 때 뒤에서 호출하는 던더, 이중 밑줄 메서드)를 호출하며, 콜론 뒤에 무엇을 썼는지를 따라갑니다. 따라서 작성하는 모든 클래스는 __format__을 정의하여 f-문자열 내에서 어떻게 나타날지를 결정할 수 있습니다. 변환 플래그 !r, !s, !a는 먼저 repr(), str(), ascii()를 값에서 실행합니다; !r이 유지할 것입니다. 코드에서 타이핑하는 방식으로 값을 보여주므로, 인용과 이스케이프를 포함하며, 아래의 실행 예제에서 표시됩니다.

python
name = "민수"
score = 94.5

print(f"Hello, {name}!")           # "Hello, 민수!"
print(f"Score: {score:.1f}%")      # "Score: 94.5%"
print(f"2 + 2 = {2 + 2}")          # "2 + 2 = 4"
print(f"Name: {name.upper()}")     # "Name: 민수"

: 후의 형식 스펙은 값이 표시되는 방식을 제어합니다:

스펙의미예시
.2f2 소수 자리f"{3.14159:.2f}""3.14"
.0%백분율, 소수 없음f"{0.94:.0%}""94%"
,천 단위 구분기호f"{1000000:,}""1,000,000"
>1010자 안에서 오른쪽 정렬f"{'hi':>10}"" hi"

대부분 .2f를 사용할 것입니다: 십진수를 표시하고 긴 숫자 실행 대신 정리된 숫자를 원할 때마다. 표에 있는 다른 모든 것은 필요할 때 있습니다. {}에 모든 변수, 산술, 메서드 호출을 넣을 수 있습니다.

.2f.0%는 대부분의 표시 형식을 다룹니다. 정렬 지정자(>, <, ^)는 너비와 결합할 때 표로 표현된 출력을 생성합니다. 일반 패턴은 {value:[align][width][.precision][type]}입니다. 조각을 인식하면, 모든 조합을 암기하지 않고 모든 스펙을 읽을 수 있습니다.

동일한 스펙이 다른 타입에 다른 것을 의미할 수 있습니다. 각 타입이 자신을 형식화하기 때문입니다: f"{'hi':5}"는 오른쪽 텍스트를 채우는 동안 f"{42:5}"는 왼쪽 숫자를 채웁니다. 동일한 :5, 반대 결과. 습관으로 가치 있는 변환 플래그는 !r: 형식화 전에 repr()를 실행하여 문자열을 따옴표로 감싸고 보이지 않는 문자(탭, 후행 공간, 줄바꿈)을 보이는 이스케이프 시퀀스로 바꿉니다. 출력이 미묘하게 잘못 보이면, {value}{value!r}로 교체하는 것이 실제로 거기에 있는 것을 보는 가장 빠른 방법입니다.

Junof-문자열 여는 따옴표 전에 f를 넣고, 중괄호에 모든 변수, 합계, 메서드 호출을 감싸면 Python이 줄이 실행될 때 결과를 내려놓습니다. 중괄호 안의 콜론은 모양을 제어합니다: :.2f 2 소수 자리는 당신이 기댈 것입니다. +로 텍스트를 접합니다것보다 훨씬 깔끔합니다.
Junof-문자열f"..."{} 안의 모든 표현식을 평가하고 결과를 직접 내려놓으며, str()이 필요 없습니다. 콜론 뒤에는 형식 스펙이 옵니다: :.2f, :,, :>10 및 친구들. 모두 {value:[align][width][.precision][type]}를 따릅니다. 한 번 부분을 배우면 모든 것을 암기하지 않고 어떤 스펙이든 읽을 수 있습니다.
Junof-문자열{}은 값의 자신의 __format__을 호출하므로, 콜론 뒤의 스펙은 그 타입이 결정하는 무엇을 의미하며, 이것이 :5가 텍스트와 숫자를 반대 방향에서 채우는 이유입니다. 유지할 플래그는 !r: 타이핑하는 방식으로 값을 보여주므로, 불필요한 공백과 기타 보이지 않는 쓰레기는 출력이 이상해 보이는 순간 나타납니다.

여러 줄 문자열

한 줄 이상에 걸쳐 있는 문자열을 작성하려면 세 개의 따옴표 표를 사용하세요: 시작 시 3개의 "과 끝에 3개. Python은 모든 줄바꿈과 공백을 정확히 작성한 대로 유지합니다.

세 따옴표 문자열은 모든 공백과 줄바꿈을 문자 그대로 유지합니다. 이들은 이메일 템플릿과 SQL 쿼리 같은 긴 텍스트 블록의 표준이고, docstring의 경우: 함수나 클래스 본문의 시작에 배치된 인라인 문서입니다.

세 따옴표 문자열은 각 줄의 선행 공간을 포함하여 모든 문자를 정확히 유지하며, 이것이 함정입니다: 리터럴을 코드와 일치하도록 들여쓰면 그 들여쓰기가 텍스트 내에 도달합니다. 함수, 클래스 또는 모듈의 본문의 첫 문이 될 때, Python은 이를 그 객체의 docstring(그것에 대해 help()이 표시하는 문서)로 유지하므로, 관례는 짧은 요약을 거기에 넣는 것입니다. 리터럴을 주변과 일치하도록 들여쓰되 들여쓰기가 값으로 샐 수 없도록 하려면, 런타임에 textwrap.dedent()로 제거하세요. 세 개의 '''"""은 동일하게 작동합니다; """은 관례입니다.

python
message = """
Dear 민수,

Thank you for your order.

Best regards,
The Team
"""
Juno여러 줄 문자열 각 끝에 세 따옴표를 사용하면 문자열이 여러 줄에 걸쳐 실행될 수 있으며, Python은 모든 줄바꿈과 공백을 정확히 타이핑한 대로 유지합니다. 메시지나 템플릿처럼 한 줄에 편안하게 맞지 않는 텍스트 블록을 갖고 있을 때마다 이에 도달하세요.
Juno여러 줄 문자열 세 따옴표는 줄바꿈과 공백을 그대로 유지하므로, 이메일 템플릿, SQL, 긴 블록에 적합합니다. 함수나 클래스의 맨 위에서 세 따옴표 문자열이고 이는 인라인 문서가 되는 것이 docstring 작동 방식이기도 합니다. 들여쓰기를 조심하세요. 정렬을 위해 추가하는 공간이 텍스트 내에 끝나갑니다.
Juno여러 줄 문자열 세 따옴표 안의 모든 것이 문자 그대로 유지되며, 선행 공백도 유지되는데, 이것이 함정입니다: 리터럴을 코드와 일치하도록 들여쓰면 그 들여쓰기가 값에 도달합니다. 함수나 클래스의 맨 위에 짧은 것을 넣으면 help()이 표시하는 docstring이 됩니다. 원본에서 들여쓰기하지만 값에서 청소할 필요가 있으면, textwrap.dedent()를 실행하세요.

이스케이프 시퀀스

일부 문자는 문자열 내에서 직접 입력하기 어렵습니다. Python은 이스케이프 시퀀스를 사용합니다: 무언가를 나타내는 문자 뒤에 백슬래시가 옵니다. 끊임없이 사용할 두 가지는 새 줄을 위한 \n과 탭을 위한 \t입니다.

이스케이프 시퀀스는 그렇지 않으면 구문을 깨거나 직접 입력할 수 없는 문자를 포함할 수 있게 합니다. 도달할 것들: \n(줄바꿈), \t(탭), \\(리터럴 백슬래시), \"\'(일치하는 구분기호 문자열 내 따옴표). Windows 경로는 이스케이프 처리와 충돌하는 백슬래시를 필요로 합니다. 이를 비활성화하려면 r로 접두사를 붙이세요.

매일 \n\t를 넘어, Python은 직접 입력할 수 없는 문자의 유니코드 이스케이프를 지원합니다: \uXXXX\UXXXXXXXX는 숫자로 문자를 이름 짓고, \N{name}은 단어로 이름을 짓습니다(예: \N{GREEK SMALL LETTER ALPHA}). 실제 코드에서 도달할 것은 raw string, r"..."로 작성되며, 이스케이프 처리를 완전히 비활성화하고 모든 백슬래시를 변경되지 않게 전달합니다. Windows 경로와 정규식 패턴에 사용하세요. 백슬래시는 Python이 아닌 그 소비자를 위한 것이고, r을 잊으면 조용히 잘못된 것과 일치하는 패턴이 생깁니다.

시퀀스문자
\n줄바꿈
\t
\\리터럴 백슬래시
\"큰따옴표
\'작은따옴표
python
print("Line one\nLine two")        # two lines of output
print("Name:\t민수")              # Name:   민수
path = r"C:\Users\Alice\Documents" # raw string, no escape processing
Juno이스케이프 시퀀스 문자열 안의 백슬래시는 "다음 문자를 특별히 읽으세요"를 의미합니다: \n은 새 줄을 시작하고, \t는 탭을 삽입하고, \\은 하나의 진짜 백슬래시입니다. 그 두 개, \n\t는 실제로 타이핑할 것들입니다. 따옴표 앞에 r을 팝하면 백슬래시는 평문으로 돌아가고, Windows 경로에 편리합니다.
Juno이스케이프 시퀀스\n, \t, \\, \"은 매일의 이스케이프를 다룹니다. 두통을 구하는 것: raw string, r"...", 이스케이프 처리를 전환하여 모든 백슬래시가 리터럴을 유지하도록 합니다. Windows 경로와 정규식 패턴에 사용하세요. 백슬래시는 Python 이외의 무언가를 위한 것입니다.
Juno이스케이프 시퀀스\n\t를 지나 \N{name} 같은 유니코드 이스케이프가 있지만, 워크호스는 raw string r"..."이며, 모든 백슬래시를 수정되지 않게 전달합니다. 정규식 패턴과 Windows 경로에 도달하세요. r을 잊으면 오류를 말해주는 대신 조용히 잘못된 것과 일치하는 패턴이 생깁니다.

문자열 내용 확인

Python은 문자열이 무엇을 포함하는지에 대해 예/아니오 질문에 답하는 메서드를 갖습니다. True 또는 False를 반환합니다. 초기에 가장 유용한 것: isdigit()은 변환하기 전에 문자열이 모두 숫자인지 확인하므로, 예상하지 못한 입력에서 충돌을 피할 수 있습니다.

is* 메서드는 각각 전체 문자열의 특정 속성을 테스트하고 모든 문자가 조건을 만족할 때만 True를 반환합니다. 주요 사용: 변환하기 전에 확인하여 예상하지 못한 입력에서 충돌을 피하세요. isdigit() 전에 int()파일과 예외 장에서 다룬 ValueError를 포착하는 대신 고전적인 패턴입니다.

이 확인은 순수 ASCII 문자와 숫자만이 아닌 모든 유니코드에 걸쳐 "이것이 이 종류인가"를 묻습니다. 이는 "2".isdigit()이 일반 "2" 뿐만 아니라 위첨자 2에도 True라는 뜻입니다. 이는 놀라운 입력이 검증 확인을 빠져나가게 할 수 있습니다. 엄격하게 숫자 0에서 9를 의미할 때, 결합하세요: s.isascii() and s.isdigit(). isnumeric()은 더 넓어서, 분수와 기타 숫자 값 문자를 세므로, 실제로 받아들이는 것과 일치하는 가장 좁은 확인에 도달하는 것보다 옳은 것처럼 보이는 첫 것을 선택하세요.

python
"42".isdigit()       # True
"hello".isalpha()    # True
"hello42".isalnum()  # True
"   ".isspace()      # True
"Hello".islower()    # False
"HELLO".isupper()    # True
Juno문자열 내용 확인is* 메서드는 예/아니오 질문에 답하고 모든 문자가 맞을 때만 True를 반환합니다. 먼저 사용할 것: isdigit()int() 전에 호출하여 텍스트가 정말 숫자인지 확인하세요. 이상한 입력이 충돌하지 않도록 합니다.
Juno문자열 내용 확인is* 메서드는 전체 문자열이 통과할 때만 True이며, 이는 변환하기 전에 입력을 검증하는 데 편리하게 합니다. 정수(int()isdigit())는 고전적인 경비입니다. 전체 문자열을 테스트하므로 빈 문자열은 모두에 대해 False를 반환합니다.
Juno문자열 내용 확인 이 확인은 순수 ASCII를 넘어 모든 유니코드에 걸쳐 있으므로, isdigit()은 당신이 받아들이지 않은 위첨자와 기타 숫자 문자를 통과합니다. 숫자 0에서 9를 의미할 때, 쌍을 만드세요: s.isascii() and s.isdigit(). 가까워 보이는 첫 것 대신 실제 입력과 일치하는 가장 좁은 확인을 선택합니다.

실제로

공백을 다듬고, 대소문자를 정규화하고, 필요한 것을 뽑아내세요. 이 순서는 거의 모든 사용자 제공 텍스트를 처리합니다:

python
raw_input = "  민수@example.com  "
email = raw_input.strip().lower()   # "민수@example.com"

at_pos = email.find("@")
username = email[:at_pos]
domain = email[at_pos + 1:]

print(f"User:   {username}")    # "민수"
print(f"Domain: {domain}")      # "example.com"

부분에서 URL을 만들고 즉시 검증하고 분석합니다:

python
BASE_URL = "https://api.example.com"
version = "v2"
resource = "users"
user_id = 42

url = f"{BASE_URL}/{version}/{resource}/{user_id}"
# "https://api.example.com/v2/users/42"

parts = url.split("://")              # ["https", "api.example.com/v2/users/42"]
protocol = parts[0]                   # "https"
secured = url.startswith("https")
domain = parts[1].split("/")[0]       # "api.example.com"

print(f"Protocol : {protocol}")
print(f"Secure   : {secured}")
print(f"Domain   : {domain}")

find(), 슬라이싱, f-문자열 정렬을 사용하여 구조화된 로그 줄을 분석합니다:

python
log_entry = "[2024-01-15 09:42:11] ERROR: File not found: report.csv"

timestamp = log_entry[1:20]
rest = log_entry[22:]                # "ERROR: File not found: report.csv"
colon_pos = rest.find(":")
level = rest[:colon_pos]             # "ERROR"
message = rest[colon_pos + 2:]       # "File not found: report.csv"

print(f"[{timestamp}] {level:>8}: {message}")
# [2024-01-15 09:42:11]    ERROR: File not found: report.csv

find()는 경계를 찾고, 슬라이싱은 부분을 추출하고, >8 형식 스펙은 심각도 레이블을 오른쪽 정렬하여 레벨 이름이 길이로 다를 때 열이 일관성 있게 유지합니다.

메서드 참조

메서드기능
.lower() / .upper()모두 소문자 / 모두 대문자로 변환
.title() / .capitalize()각 단어 / 첫 단어만 대문자화
.strip() / .lstrip() / .rstrip()둘레 공백 제거
.find(sub)첫 일치의 인덱스, 또는 -1
.count(sub)sub이 나타나는 횟수
.startswith(s) / .endswith(s)프리픽스 / 서픽스 확인
.replace(old, new)발생 교체
.split(sep)리스트로 분할
sep.join(iterable)문자열로 항목 결합
.isdigit() / .isalpha() / .isalnum()문자 타입 확인