[번역] string - Text Constants and Templates

폐쇄맨·2020년 7월 10일
0

번역

목록 보기
3/5
post-custom-banner

모듈의 존재 이유: 텍스트 처리를 위한 상수와 클래스를 포함한다.

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.

string.Template

문자열 템플릿은 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의 결과 문자열은 템플릿 바디에서 변수 이름을 찾는 정규 표현식의 패턴을 어떻게 설정하는지에 따라 달라진다. delimeteridpattern 클래스 속성을 정하는 간단한 방법이 있다.

#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

`pattern` 속성을 오버라이딩하고 완전히 새로운 정규 표현식을 정하는 것도 가능하다. 구분자로 사용될 이스케이프 문자, 변수명 패턴, 중괄호로 묶였을 때의 변수명 패턴, 유효하지 않는 구분자 패턴, 이 네가지를 반드시 포함하여 `pattern` 속성을 오버라이딩 해야한다.
# 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'))

namedbraced 패턴은 똑같더라도 반드시 각각 작성해야 한다. 아래는 해당 프로그램을 실행시킨 아웃풋이다:

$ python3 string_template_newsyntax.py

MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]
SUBSTITUTED:
{{
replacement

Formatter

Formatter 클래스는 strformat() 메서드와 같은 사양(仕樣)을 구현합니다. 형 변환, 정렬, 속성과 필드 레퍼런스, 템플릿 매개변수의 이름과 위치, 그리고 특정 타입에 대한 포맷팅 옵션 등의 기능을 가지고 있다. 대부분의 경우에 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'

참고자료

profile
폐쇄맨
post-custom-banner

0개의 댓글