모듈의 존재 이유: 텍스트 처리를 위한 상수와 클래스를 포함한다.
string
모듈은 파이썬 초기 버전부터 이어져 왔다. 이 모듈의 많은 기능들이 str
객체의 메서드로 옮겨졌다. 이제 string
모듈은 str
객체를 처리하기 위한 유용한 상수와 클래스들을 가지고 있다. 오늘은 이에 대해 얘기를 해볼까 한다.
capword()
메서드는 문자열의 각 어절(단어)의 첫번째 문자를 대문자로 만든다.
# string_capwords.py
import string
s = 'The quick brown fox jumped over the lazy dog.'
print(s)
print(string.capwords(s))
이 메서드는 split()
메서드로 문자열을 나눈 뒤 단어들의 첫글자를 대문자로 만들고 다시 join()
메서드를 호출하여 결과를 하나의 문자열로 묶는 것과 동일한 결과를 만든다.
$ python3 string_capwords.py
The quick brown fox jumped over the lazy dog.
The Quick Brown Fox Jumped Over The Lazy Dog.
문자열 템플릿은 PEP 292의 일부 사항이며, 내장된 내삽(interpolation) 구문을 대체하기 위해 만들어졌다. string.Template
으로 내삽을 할 때, 변수들은 $
문자로 시작하는 이름을 가진다 (e.g. $var). 변수들을 좀 더 눈에 띄게 구분짓고 싶다면, 중괄호안에 변수를 넣어도 된다 (e.g. ${var}).
아래는 %
연산자를 사용하는 string.Template
사용, 문자열 내삽법, 그리고 str.format()
메서드를 사용한 문자열 포맷팅을 비교하는 예제이다.
# string_template.py
import string
values = {'var': 'foo'}
t = string.Template("""
Variable : $var
Escape : $$
Variable in text: ${var}iable
""")
print('TEMPLATE:', t.substitute(values))
s = """
Variable : %(var)s
Escape : %%
Variable in text: %(var)siable
"""
print('INTERPOLATION:', s % values)
s = """
Variable : {var}
Escape : {{}}
Variable in text: {var}iable
"""
print('FORMAT:', s.format(**values))
트리거 캐릭터들 ($, % or {})은 두 번씩 사용되면 escaped 된다.
$ python3 string_template.py
TEMPLATE:
Variable : foo
Escape : $
Variable in text: fooiable
INTERPOLATION:
Variable : foo
Escape : %
Variable in text: fooiable
FORMAT:
Variable : foo
Escape : {}
Variable in text: fooiable
단순 템플릿 (위의 예제의 첫번째 방법)에서 변수의 타입은 별로 중요하지 않다. 문자열로 타입으로 변환되어 삽입되는 것 뿐이며 사용할 수 있는 포맷팅 옵션이 없다. 예를 들어, 부동 소수점 값을 나타내는데 사용되는 자릿수를 제어할 방법이 없다.
한 가지 이점이 있다면, 템플릿에 필요한 모든 인수가 준비되어 있지 않을 때 발생할 수 있는 예외를 safe_substitute()
메서드를 사용하여 피해갈 수 있다.
# string_template_missing.py
import string
values = {'var': 'foo'}
t = string.Template("$var is here but $missing is not provided")
try:
print('substitute() :', t.substitute(values))
except KeyError as err:
print('ERROR:', str(err))
print('safe_substitute():', t.safe_substitute(values))
missing
인수가 제공되지 않았기 때문에, substitute()
메서드를 사용하면 KeyError
가 발생한다. 대신 safe_substitute()
를 사용해 변수표현을 그냥 문자열로 바꾸어 에러를 피해간다.
$ python3 string_template_missing.py
ERROR: 'missing'
safe_substitute(): foo is here but $missing is not provided
string.Template
의 결과 문자열은 템플릿 바디에서 변수 이름을 찾는 정규 표현식의 패턴을 어떻게 설정하는지에 따라 달라진다. delimeter
와 idpattern
클래스 속성을 정하는 간단한 방법이 있다.
#string_template_advanced.py
import string
class MyTemplate(string.Template):
delimiter = '%'
idpattern = '[a-z]+_[a-z]+'
template_text = '''
Delimiter : %%
Replaced : %with_underscore
Ignored : %notunderscored
'''
d = {
'with_underscore': 'replaced',
'notunderscored': 'not replaced',
}
t = MyTemplate(template_text)
print('Modified ID pattern:')
print(t.safe_substitute(d))
위의 예제에서, 치환하는 변수의 구분자는 $
에서 %
로, 변수 이름은 중간에 언더스코어(_
)를 포함하는 것이로 바뀌었다. %notunderscored
는 언더스코어를 포함하지 않기 때문에 무시된다.
$ python3 string_template_advanced.py
Modified ID pattern:
Delimiter : %
Replaced : replaced
Ignored : %notunderscored
# string_template_defaultpattern.py
import string
t = string.Template('$var')
print(t.pattern.pattern)
t.pattern
의 값은 컴파일된 정규 표현식이다. 하지만 pattern
속성을 사용하면 오리지널 문자열을 볼 수 있다.
\$(?:
(?P<escaped>\$) | # two delimiters
(?P<named>[_a-z][_a-z0-9]*) | # identifier
{(?P<braced>[_a-z][_a-z0-9]*)} | # braced identifier
(?P<invalid>) # ill-formed delimiter exprs
)
아래는 {{var}}
을 변수 구문으로 사용하는 새로운 템플릿을 만들기 위한 새로운 패턴을 정의한 예제이다.
# string_template_newsyntax.py
import re
import string
class MyTemplate(string.Template):
delimiter = '{{'
pattern = r'''
\{\{(?:
(?P<escaped>\{\{)|
(?P<named>[_a-z][_a-z0-9]*)\}\}|
(?P<braced>[_a-z][_a-z0-9]*)\}\}|
(?P<invalid>)
)
'''
t = MyTemplate('''
{{{{
{{var}}
''')
print('MATCHES:', t.pattern.findall(t.template))
print('SUBSTITUTED:', t.safe_substitute(var='replacement'))
named
와 braced
패턴은 똑같더라도 반드시 각각 작성해야 한다. 아래는 해당 프로그램을 실행시킨 아웃풋이다:
$ python3 string_template_newsyntax.py
MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]
SUBSTITUTED:
{{
replacement
Formatter
클래스는 str
의 format()
메서드와 같은 사양(仕樣)을 구현합니다. 형 변환, 정렬, 속성과 필드 레퍼런스, 템플릿 매개변수의 이름과 위치, 그리고 특정 타입에 대한 포맷팅 옵션 등의 기능을 가지고 있다. 대부분의 경우에 format()
메서드의 간단한 인터페이스를 사용하지만 Formatter
클래스는 필요시 서브클래스를 만들어 활용할 수 있는 장점이 있다.
string
모듈은 아스키 코드와 다수의 문자셋에 대한 다수의 상수를 포함하고 있다.
# string_constants.py
import inspect
import string
def is_str(value):
return isinstance(value, str)
for name, value in inspect.getmembers(string, is_str):
if name.startswith('_'):
continue
print('%s=%r\n' % (name, value))
이러한 상수들은 아스키 코드로된 데이터를 처리할 때 유용하나 유니코드의 사용이 보편화되면서 사용에 제한적이다.
$ python3 string_constants.py
ascii_letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
XYZ'
ascii_lowercase='abcdefghijklmnopqrstuvwxyz'
ascii_uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits='0123456789'
hexdigits='0123456789abcdefABCDEF'
octdigits='01234567'
printable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ
RSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
punctuation='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
whitespace=' \t\n\r\x0b\x0c'
string
모듈에서 deprecated된 기능을 대체하는 str
객체의 메서드들Formatter
클래스와 str.format()
메서드에서 사용한 공식적인 사양