트랙
/
Python
Python
/
학습 과정
/
문자열 서식 지정
문자

문자열 서식 지정 에서 Python

1개의 연습 문제

문자열 서식 지정 소개

Python에서의 문자열 포매팅

문자열 포매팅은 값을 문자열로 변환해서 문자열 템플릿에 넣는 과정이에요. The Zen of Python은 "Python에서 어떤 일을 하는 명백한 방법은 하나여야 한다"고 말해요. 그런데 문자열 포매팅에서는 사정이 조금... 덜 선(zen)해요.

Python에서 문자열 포매팅을 하는 주요 방법이 네 가지나 된다는 사실은 놀라울 수 있어요. 각각 다른 상황을 위한 방법이거든요. 이는 일부는 Python의 긴 역사 때문이고, 일부는 국제화나 입력 정제 같은 고려 사항 때문이에요. 문자열 포매팅 도구 상자에 가장 최근에 추가된 것부터 시작해서, "옛 스타일" 또는 "printf() 스타일" 문자열 포매팅으로 거슬러 올라가 볼게요.

리터럴 문자열 보간: f-string

Python 3.6에 도입된 f-string("formatted string"의 줄임말) 또는 리터럴 문자열 보간은, 따옴표 앞에 f(또는 F) 접두사를 붙여 표현식과 문자열을 str 타입으로 빠르고 효율적으로 평가(하고 포매팅)하는 방법이에요(이렇게요: f'{object}').

f-string은 한 줄(' 또는 ")과 여러 줄(''' 또는 """)을 비롯한 모든 따옴표 종류와 함께 쓸 수 있어요. {} 안에 넣은 변수, 표현식 또는 다른 타입은 먼저 평가되고, 그다음 str로 변환되며, 마지막으로 중괄호 밖의 str과 이어 붙여져요.

이 예제에서는 문장에 두 변수 값(str 하나와 float 하나)을 넣어요:

>>> name = 'eighth'
>>> value = 1/8

# The f-string, using the two values.
# The .2f format code truncates, so the value displays as 0.12.
>>> f'An {name} is approximately {value:.2f}.'
'An eighth is approximately 0.12.'

평가할 수 있는 표현식은 거의 무엇이든 될 수 있어요. 평가할 수 있는 (아주 다양한) 가능성 중 일부는 str, 숫자, 변수, 산술 표현식, 조건 표현식, 내장 타입, 슬라이스, 함수, 람다, 컴프리헨션, 또는 __str__이나 __repr__ 메서드가 정의된 모든 객체예요.

간단한 것부터 복잡한 것까지 살펴볼게요:

변수 넣기: f-string의 가장 간단한 사용법은 변수를 문자열에 바로 넣는 거예요.

# Assigning a variable.
>>> name = "World"

# Inserting that variable.
>>> f'Hello, {name}!'
'Hello, World!'

{} 안의 표현식: 중괄호 안에서는 유효한 Python 표현식이라면 무엇이든 평가할 수 있어요. 작은따옴표로 묶은 f-string 안에서 큰따옴표를 쓰면(또는 그 반대로) 이스케이프 시퀀스가 필요 없다는 점을 기억해 두세요:

# A dictionary of key:value pairs.
>>> waves = {'water': 1, 'light': 3, 'sound': 5}

# Inserting the whole dict.
>>> f'Wave ranks: {waves}'
"Wave ranks: {'water': 1, 'light': 3, 'sound': 5}"

# An expression can be evaluated inline:
>>> f"Tenfold the value of 'light' is {waves['light'] * 10}."
"Tenfold the value of 'light' is 30."

# A method call can also be evaluated inline:
>>> f'{"hello world!".title()} is a classic greeting.'
'Hello World! is a classic greeting.'

# An f-string can be nested inside another f-string:
>>> f"{f'hello world!'.title()} is a classic greeting."
'Hello World! is a classic greeting.'

출력 포매팅: 형식 지정 미니 언어로 정렬, 숫자 정밀도 등을 제어할 수 있어요. 형식 지정은 값 뒤에 :로 구분해서 써요.

# Right-align a value to ten characters, and round it to 3 decimal places.
>>> value = 1 / 7
>>> f'One seventh is {value:10.3f}.'
'One seventh is      0.143.'

# A format specification can be set using variables as well.
>>> padding = 10
>>> precision = 3
>>> f'One seventh is {value:{padding}.{precision}f}.'
'One seventh is      0.143.'

전부 합치기: 변수, 표현식, 함수 호출, 출력 포매팅:

>>> precision = 3
>>> f"{30e8 * 111_000:6.{precision}e}"
'3.330e+14'

>>> verb = 'meet'
>>> the_end = ['end', 'of', 'transmission']
>>> f'"Have a {"NICE".lower()} day, I will {verb} you after {30e8 * 111_000:6.{precision}e} light-years."{the_end}'
'"Have a nice day, I will meet you after 3.330e+14 light-years."[\'end\', \'of\', \'transmission\']'

# Did you notice the escaped single-quotes in the previous example?
# Using double quotes instead of single quotes for the f-string means the list's single-quoted strings print cleanly.
>>> f"Have a nice day. {the_end}"
"Have a nice day. ['end', 'of', 'transmission']"

알아 둘 두 가지 주요 제약이 있어요. f-string 표현식은 비워 둘 수 없어요. 또한 Python 3.12 이전에는 주석을 포함할 수 없었어요.

>>> f"An empty expression will error: {}"
SyntaxError: f-string: empty expression not allowed

>>> word = 'word'
>>> f"""A comment in a triple quoted f-string: {
    word # I chose a nice variable
}"""
'A comment in a triple quoted f-string: word'
Caution

문자열 보간은 국제화(I18N)와 지역화(L10N)를 위한 GNU gettext API와 함께 쓸 수 없어요. 그래서 "문자열을 감싸는" 번역 상황에서는 f-string 대신 아래에서 설명하는 string.Template 클래스나 str.format() 메서드를 쓰는 것이 권장돼요.

또한 f-string의 중괄호 {} 안에서 표현식을 쓰는 것은 eval()이나 exec()을 쓰는 것과 비슷하다는 점도 기억해 두세요. 그리 안전하지 않아서 사용자 입력과 함께 써서는 절대 안 돼요.

str.format() 메서드

str.format() 메서드는 문자열 안의 자리 표시자를 함수에 인자로 넘긴 값으로 바꿔요. 자리 표시자는 이름({price}), 숫자({0} 또는 인덱스), 또는 빈(위치 기반) 자리 표시자 {}로 지정해요.

예를 들어:

# A named placeholder and a positional placeholder.
>>> 'My text: {placeholder_1} and {}.'.format(12, placeholder_1='named placeholder')
'My text: named placeholder and 12.'

f-string과 마찬가지로, Python의 str.format()은 텍스트를 정렬하고 실수를 자르는 등 다양한 미니 언어 형식 지정자를 지원해요.

전체 형식 지정자 패턴은 {[<name>][!<conversion>][:<format_specifier>]}예요:

  • <name>은 이름이 있는 자리 표시자, 숫자, 또는 빈 값일 수 있어요.
  • !<conversion>은 선택 사항이며, 다음 세 변환 중 하나여야 해요: str()은 !s, repr()은 !r, ascii()은 !a예요. 기본값으로는 str()이 쓰여요.
  • :<format_specifier>는 선택 사항이며 값이 어떻게 표시될지 제어해요. 가능한 옵션에 대한 자세한 내용은 여기에서 볼 수 있어요.

분음 부호가 있는 문자의 변환 예제:

# Fills in the object at index zero, converted to a string.
>>> 'An e with an umlaut: {0!s}'.format('ë')
'An e with an umlaut: ë'


# Fills in the object at index zero, converted to a repr.
>>> 'An e with an umlaut (object representation): {0!r}'.format('ë')
"An e with an umlaut (object representation): 'ë'"


# Fills in the object at index zero, converted to ASCII.
>>> 'An e with an umlaut converted into ASCII: {0!a}'.format('ë')
"An e with an umlaut converted into ASCII: '\xeb'"


# Fills in the object in the first position,
# then fills in the object in the second position formatted as a repr.
>>> 'She said her name is not {} but {!r}.'.format('Chloe', 'Zoë')
"She said her name is not Chloe but 'Zoë'."

자주 쓰이는 형식 지정자의 예:

# Integer and binary/hex representations of the same number.
>>> my_num = 42
>>> f"{my_num} in binary is {my_num:b}. In hex, it is {my_num:x}"
"42 in binary is 101010. In hex, it is 2a"

# Alignment: left (<), right (>), and center (^) using up to ten characters total.
>>> f"[{"left":<10}] [{"right":>10}] [{"center":^10}]"
"[left      ] [     right] [  center  ]"

# Float precision and scientific notation (up to three decimal places).
>>> pi = 3.141592653589793
>>> f"Fixed: {pi:.3}  Scientific: {pi:.3e}"
"Fixed: 3.142  Scientific: 3.142e+00"

# Thousands separator and percentage.
>>> balance = 1000
>>> rate = 0.0225
>>> f"Balance: ${balance:,.0f}  Interest rate: {rate:.1%}"
"Balance: $1,000  Interest rate: 2.2%"

# Putting it all together:
>>> items = [("Widget", 1250, 9.991), ("Gadget", 37, 24.503), ("Doohickey", 4, 149.002)]
>>> header = f"{"Item":<12} {"Qty":>6} {"Price":>9}"
>>> print(header)
Item            Qty     Price
>>> for name, qty, price in items:
...     print(f"{name:<12} {qty:>6} {price:>9.2f}")
Widget         1250      9.99
Gadget           37     24.50
Doohickey         4    149.00

더 많은 예제는 이 문서 끝부분에 나와 있어요.

% 포매팅, 또는 printf() 스타일 포매팅

포매팅에 % 연산자를 사용하는 것은 Python에서 가장 오래된 문자열 포매팅 방법이에요. C 언어에서 왔으며, 위치 기반 인자를 사용해 str을 만들 수 있어요.

이 방법은 f-string과 str.format()에 밀려났고, 그래서 % 포매팅의 별명이 _"옛 스타일"_이에요. 여전히 Python 2나 레거시 코드에서 찾아볼 수 있어요. 이 방법은 Python 3.x에서도 동작하지만, 오류가 나기 쉽고 효율이 떨어지며 사용할 수 있는 옵션도 적고 자리 표시자와 인자가 맞지 않으면 예외가 발생할 수 있어서 보통은 피해요. % 연산자를 쓰는 것은 printf()와 비슷해서 _printf 포매팅_이라고도 불려요.

# Assigning a variable.
>>> name = "Anna-conda"

# Building a string using %.
>>> "The snake's name is %s." % name
"The snake's name is Anna-conda."

위 예제에서 % 연산자는 런타임에 자리 표시자 %s를 변수 name으로 바꿔요. 문자열에 여러 변수를 넣고 싶다면, % 뒤에 자리 표시자마다 객체 하나씩 담은 튜플을 넘겨야 해요:

# Assigning variables.
>>> name = "Billy the Kid"
>>> fruit = "grapes"

# Building a string using %.
>>> "Surprisingly, %s's favorite snack was %s." %(name, fruit)
"Surprisingly, Billy the Kid's favorite snack was grapes."

템플릿 문자열

string.Template()는 (Python 3.14의 t-strings와 혼동하면 안 돼요) string 모듈(내장 str 타입과는 달라요)의 클래스로, Python 표준 라이브러리에 속하지만 사용하려면 임포트해야 해요. 템플릿 문자열은 $ 기반 치환을 지원하며, 여기서 언급한 다른 방법들보다 훨씬 단순하고 기능도 적어요. 하지만 복잡한 국제화나 외부 입력 정제에는 아주 유용할 수 있어요.

string.Template은 임의의 표현식을 평가하거나 객체 속성에 접근하는 것을 막아서 형식 문자열 주입 공격을 완화하므로, 신뢰할 수 없는 사용자 입력에 더 안전한 것으로 여겨져요.

>>> from string import Template

>>> name = "Anna-Conda"

# Creating a Template with placeholder text.
>>> template_string = Template("The snake called `$snake_name` has escaped!")

# Calling .substitute() to replace the placeholder with a value.
>>> template_string.substitute(snake_name=name)
'The snake called `Anna-Conda` has escaped!'

string.Template에 대한 더 자세한 내용은 Python 문서에서 볼 수 있어요.

어떤 포매팅 방법을 선택해야 할까요?

이렇게 많은 옵션과 미니 언어가 있는데, Python 문자열을 포매팅할 때 무엇을 골라야 할까요? 빠르게 참고할 몇 가지 지침이에요:

  1. f-string은 가장 최신이고 읽기 가장 쉬워요. 국제화가 필요 없다면 Python 3.6 이상에서는 이것을 우선적으로 쓰는 게 좋아요.

  2. str.format()은 다재다능하고 강력하며, gnu gettext와 대부분의 Python 버전 모두와 호환돼요.

  3. 단순함, 안전성, 또는 많은 국제화가 필요하다면, 사용자 입력을 다뤄야 할 때 위험을 줄이고 번역 문자열을 감싸는 데 string.Template()을 쓸 수 있어요.

  4. % 연산자는 최신 Python에서도 동작하지만, 새 코드에서는 보통 사용을 지양해요. 주로 오래된 코드베이스와의 호환성을 위해 써요. % 포매팅은 다른 방법보다 오류가 나기 쉽고(기능도 적으며), ASCII가 아닌 문자를 표시할 때 문제가 생길 수 있어요. 사용할 생각이라면 지원 세부 사항을 해당 Python 배포판에서 확인해 보세요.

더 나아가고 싶다면, 포매팅에 관한 모든 것과 Python 문자열 포매팅 모범 사례가 좋은 출발점이에요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요