Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 292 – 더 단순한 문자열 치환

Author:
Barry Warsaw <barry at python.org>
Status:
Final
Type:
Standards Track
Created:
18-Jun-2002
Python-Version:
2.4
Post-History:
18-Jun-2002, 23-Mar-2004, 22-Aug-2004
Replaces:
215

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 문자열 보간이라고도 하는 더 단순한 문자열 치환 기능을 설명합니다. 이 PEP는 두 가지 측면에서 “더 단순”합니다:

  1. Python의 현재 문자열 치환 기능(즉, %-치환)은 복잡하고 오류가 발생하기 쉽습니다. 이 PEP는 표현력을 일부 희생하는 대신 더 단순합니다.
  2. PEP 215는 새로운 $ 문자열 접두사를 도입하는 대안적인 문자열 보간 기능을 제안했습니다. PEP 292는 문법 변경이 전혀 없고, 문자열 안에서 어떤 치환이 일어날 수 있는지에 대한 규칙도 훨씬 단순하므로 이보다 더 단순합니다.

근거

Python은 현재 C의 printf() ‘%’ 서식 문자에 기반한 문자열 치환 문법을 지원합니다 [1]. %-서식 코드는 상당히 풍부하지만, 숙련된 Python 프로그래머에게도 오류가 발생하기 쉽습니다. 흔한 실수는 끝에 오는 서식 문자를 빠뜨리는 것으로, 예를 들어 "%(name)s"의 ‘s’가 그렇습니다.

또한 % 기호 뒤에 올 수 있는 것에 대한 규칙은 상당히 복잡하지만, 일반적인 응용에서는 그러한 복잡성이 거의 필요하지 않습니다. 대부분의 스크립트는 어느 정도 문자열 보간을 해야 하지만, 그중 대부분은 단순한 ‘문자열화’ 서식, 즉 %s나 %(name)s를 사용합니다. 이 형식은 더 단순하고 오류가 덜 발생하도록 만들어야 합니다.

더 단순한 제안

Template이라는 새 클래스를 추가할 것을 제안합니다. 이 클래스는 문자열(string) 모듈에 위치하게 됩니다. Template 클래스는 문자열 치환을 위한 새로운 규칙을 지원합니다. 그 값에는 $ 문자로 시작하는 플레이스홀더가 포함됩니다. $-플레이스홀더에는 다음 규칙이 적용됩니다:

  1. $$는 이스케이프이며, 하나의 $로 대체됩니다.
  2. $identifier는 “identifier”(식별자)라는 매핑 키와 일치하는 치환 플레이스홀더를 나타냅니다. 기본적으로 “identifier”는 [2]에 정의된 Python 식별자여야 합니다. $ 문자 뒤에 처음 나오는, 식별자에 속하지 않는 문자가 이 플레이스홀더 명세를 끝냅니다.
  3. ${identifier}는 $identifier와 동등합니다. 이 형식은 유효한 식별자 문자가 플레이스홀더 뒤에 오지만 플레이스홀더의 일부가 아닌 경우에 필요합니다. 예를 들어 "${noun}ification"과 같은 경우입니다.

$ 문자가 줄 끝에 나타나거나 위에서 설명한 것 이외의 문자가 뒤에 오면, 보간 시점에 ValueError가 발생합니다. 매핑의 값은 자동으로 문자열로 변환됩니다.

다른 문자는 특별한 의미를 갖지 않지만, Template 클래스를 상속하여 다른 치환 규칙을 정의할 수 있습니다. 예를 들어, 파생 클래스는 플레이스홀더 안에 마침표를 허용하거나(예: 일종의 동적 네임스페이스 및 속성 경로 조회를 지원하기 위해), $ 이외의 구분 문자를 정의할 수 있습니다.

Template이 생성되면, 두 메서드 중 하나를 호출하여 치환을 수행할 수 있습니다:

  • substitute(). 이 메서드는 Template의 플레이스홀더를 매핑의 값으로 치환한 결과인 새 문자열을 반환합니다. 매핑에 없는 플레이스홀더가 있으면 KeyError가 발생합니다.
  • safe_substitute(). 이는 substitute() 메서드와 비슷하지만, (매핑에 플레이스홀더가 없어서) KeyErrors가 발생하는 일이 결코 없다는 점이 다릅니다. 플레이스홀더가 없으면 원래의 플레이스홀더가 결과 문자열에 그대로 나타납니다.

    다음은 몇 가지 예입니다:

    >>> from string import Template
    >>> s = Template('${name} was born in ${country}')
    >>> print s.substitute(name='Guido', country='the Netherlands')
    Guido was born in the Netherlands
    >>> print s.substitute(name='Guido')
    Traceback (most recent call last):
    [...]
    KeyError: 'country'
    >>> print s.safe_substitute(name='Guido')
    Guido was born in ${country}
    

substitute()와 safe_substitute()의 시그니처는 플레이스홀더와 값의 매핑을 첫 번째 위치 인자에 단일 딕셔너리 형태의 객체로 전달하거나, 위에서 보인 것처럼 키워드 인자로 전달할 수 있도록 합니다. 이 두 메서드의 정확한 세부 사항과 시그니처는 표준 라이브러리 문서에서 다룹니다.

왜 $와 중괄호를 사용합니까?

BDFL이 이를 가장 잘 표현했습니다 [3]: “$는 Perl 외에도 아주 많은 언어에서 “치환”을 뜻하는데, 대체 어디에 계셨던 건지 궁금할 정도입니다. […] 우리는 이것을 셸에서 가져오는 것입니다.”

따라서 치환 규칙은 수많은 다른 언어와 유사하다는 이유로 선택되었습니다. 이 덕분에 치환 규칙을 가르치고, 배우고, 기억하기가 더 쉬워집니다.

PEP 215와의 비교

PEP 215는 문자열 보간에 대한 다른 제안을 설명합니다. 그 PEP와 달리, 이 PEP는 Python에 어떠한 새로운 문법도 제안하지 않습니다. 제안된 모든 새 기능은 새로운 라이브러리 모듈에 구현되어 있습니다. PEP 215는 새로운 종류의 문자열이 있음을 Python에 알리는 $""와 같은 새로운 문자열 접두사 표현을 제안합니다. $-문자열은 기존의 r 접두사 및 u 접두사와 상호 작용해야 하므로, 사실상 문자열 접두사 조합의 수가 두 배로 늘어납니다.

PEP 215는 또한 $-문자열 안에 임의의 Python 표현식을 허용하므로, 다음과 같은 일을 할 수 있습니다:

import sys
print $"sys = $sys, sys = $sys.modules['sys']"

이는 다음을 반환합니다:

sys = <module 'sys' (built-in)>, sys = <module 'sys' (built-in)>

PEP 215의 규칙은 새로운 보안 문제를 일으키지 않는다는 의미에서 안전하다고 일반적으로 받아들여지고 있습니다(자세한 내용은 PEP 215의 “Security Issues”를 참조하십시오). 그러나 이 규칙은 여전히 상당히 복잡하며, 원래의 $-문자열에서 치환 플레이스홀더를 알아보기 더 어렵게 만듭니다.

흥미로운 점은 이 PEP에서 정의한 Template 클래스가 상속을 고려하여 설계되었으며, 약간의 추가 작업만으로 기존 Python 문법을 사용해 PEP 215의 기능을 지원할 수 있다는 것입니다.

예를 들어, 더 복잡한 플레이스홀더 문법을 허용하는 Template의 서브클래스와, 그 플레이스홀더를 평가하는 매핑인 dict의 서브클래스를 정의할 수 있습니다.

국제화

이 구현은 원래의 템플릿 문자열을 Template 인스턴스의 template 속성에 기록함으로써 국제화를 지원합니다. 이 속성은 gettext 기반 카탈로그에서 조회 키 역할을 합니다. 결과 문자열을 치환을 위해 다시 Template으로 바꾸는 것은 애플리케이션의 몫입니다.

그러나 Template 클래스는 Template과 unicode(유니코드) 서브클래스를 함께 믹스인하는 것을 지원함으로써, 국제화된 애플리케이션에서 더 직관적으로 동작하도록 설계되었습니다. 따라서 국제화된 애플리케이션은 Template과 unicode(유니코드)를 다중 상속하는 애플리케이션 전용 서브클래스를 만들고, 그 서브클래스의 인스턴스를 gettext 카탈로그 키로 사용할 수 있습니다. 또한 서브클래스는 특수 메서드 __mod__()를 .substitute()나 .safe_substitute()의 별칭으로 지정하여, 보다 전통적인 문자열/유니코드 방식의 % 연산자 치환 문법을 제공할 수 있습니다.

참조 구현

이 구현 [4]은 Python 2.4 소스 트리에 커밋되었습니다.

참고 문헌