Python

Python 2.4의 새로운 기능

저자:

A.M. Kuchling

이 기사는 2005년 3월 30일에 출시된 Python 2.4.1의 새로운 기능들을 설명합니다.

Python 2.4는 중간 규모의 릴리스입니다. 혁신적인 Python 2.2만큼 많은 변화를 도입하지는 않지만, 보수적인 2.3 릴리스보다 더 많은 기능을 추가합니다. 가장 중요한 새로운 언어 기능은 함수 데코레이터와 제너레이터 표현식이며, 다른 대부분의 변경 사항은 표준 라이브러리에 해당합니다.

CVS 변경 로그에 따르면, Python 2.3과 2.4 사이에서 481개의 패치가 적용되었고 502개의 버그가 수정되었습니다. 두 수치 모두 실제보다 적게 집계된 것으로 보입니다.

이 기사는 모든 새로운 기능에 대한 완전한 명세를 제공하는 대신, 각 기능에 대한 간략한 소개를 제공합니다. 자세한 내용은 Python Library Reference 및 Python Reference Manual과 같은 Python 2.4 문서를 참조하십시오. 특정 신기능의 구현이나 설계 근거에 대한 설명은 해당 PEP를 참고하시면 됩니다.

PEP 218: 내장 집합 객체

Python 2.3은 sets 모듈을 도입했습니다. set 데이터 유형의 C 구현이 두 개의 새로운 내장 유형인 set(iterable)frozenset(iterable) 으로 Python 핵심에 추가되었습니다. 이들은 멤버십 테스트, 시퀀스에서 중복 제거, 그리고 합집합, 교집합, 차집합 및 대칭 차집합과 같은 수학적 연산을 위한 고속 연산을 제공합니다.

>>> a = set('abracadabra')              # 문자열로 세트 생성
>>> 'z' in a                            # 빠른 멤버십 테스트
False
>>> a                                       # a에 포함된 고유한 문자들
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a)                            # 다시 문자열로 변환
'arbcd'

>>> b = set('alacazam')                 # 두 번째 세트 생성
>>> a - b                               # a에는 있지만 b에는 없는 문자들
set(['r', 'd', 'b'])
>>> a | b                               # a 또는 b에 있는 문자들
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b                               # a와 b 모두에 있는 문자들
set(['a', 'c'])
>>> a ^ b                               # a 또는 b에 있지만 둘 다는 아닌 문자들
set(['r', 'd', 'b', 'm', 'z', 'l'])

>>> a.add('z')                          # 새로운 요소 추가
>>> a.update('wxy')                     # 여러 개의 새로운 요소 추가
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x')                       # 요소 하나 제거
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])

frozenset() 타입은 set() 의 불변 버전입니다. 불변(immutable)이고 해시 가능(hashable)하므로 딕셔너리 키나 다른 세트의 원소로 사용할 수 있습니다.

sets 모듈은 표준 라이브러리에 남아 있으며, Set 또는 ImmutableSet 클래스를 하위 클래스로 만들고자 할 때 유용할 수 있습니다. 현재 이 모듈을 더 이상 사용하지 않음(deprecated)으로 처리할 계획은 없습니다.

더 보기

PEP 218 - 내장 세트 객체 타입 추가

원래 Greg Wilson이 제안하였으며 최종적으로 Raymond Hettinger가 구현했습니다.

PEP 237: Long 정수 및 정수의 통합

Python 2.2에서 시작된 이 PEP의 긴 전환 과정이 Python 2.4에서 한 걸음 더 나아갑니다. 2.3 버전에서는 int/long 통합 이후 다르게 동작할 수 있는 특정 정수 연산들이 FutureWarning 경고를 발생시키고 플랫폼에 따라 32비트 또는 64비트로 제한된 값을 반환했습니다. 2.4 버전에서 이러한 표현식은 더 이상 경고를 생성하지 않으며 대신 보통 long 정수인 다른 결과를 생성합니다.

문제가 되는 표현식은 주로 왼쪽 시프트와 긴 16진수 및 8진수 상수입니다. 예를 들어, 2 << 32 는 2.3에서 경고를 발생시키며 32비트 플랫폼에서 0으로 평가됩니다. Python 2.4에서는 이 표현식이 이제 올바른 답인 8589934592를 반환합니다.

더 보기

PEP 237 - Long 정수 및 정수의 통합

원래 PEP는 Moshe Zadka와 GvR이 작성했습니다. 2.4를 위한 변경 사항은 Kalle Svensson이 구현했습니다.

PEP 289: 제너레이터 표현식

Python 2.2에 도입된 이터레이터 기능과 itertools 모듈을 사용하면 전체 데이터 세트를 한 번에 메모리에 올리지 않고도 대규모 데이터 세트를 루프 돌리는 프로그램을 작성하기 쉬워집니다. 리스트 컴프리헨션은 모든 항목을 포함하는 파이썬 리스트 객체를 생성하므로 이 상황에 잘 맞지 않습니다. 이는 필연적으로 모든 객체를 메모리로 불러오게 되며, 데이터 세트가 매우 클 경우 문제가 될 수 있습니다. 함수형 스타일의 프로그램을 작성하려고 할 때 다음과 같이 쓰는 것이 자연스러울 것입니다:

links = [link for link in get_all_links() if not link.followed]
for link in links:
    ...

대신에

for link in get_all_links():
    if link.followed:
        continue
    ...

첫 번째 형식이 더 간결하고 아마도 가독성이 더 좋지만, 수많은 링크 객체를 다루는 경우 모든 링크 객체가 동시에 메모리에 머무는 것을 방지하기 위해 두 번째 형식을 작성해야 합니다.

제너레이터 표현식은 리스트 컴프리헨션과 비슷하게 작동하지만 전체 리스트를 구체화하지 않습니다. 대신 요소들을 하나씩 반환하는 제너레이터를 생성합니다. 위의 예제는 다음과 같이 작성할 수 있습니다:

links = (link for link in get_all_links() if not link.followed)
for link in links:
    ...

제너레이터 표현식은 위 예시와 같이 항상 괄호 안에 작성해야 합니다. 함수 호출을 알리는 괄호도 포함되므로, 함수에 즉시 전달될 이터레이터를 생성하려면 다음과 같이 작성할 수 있습니다:

print sum(obj.count for obj in list_all_objects())

제너레이터 표현식은 리스트 컴프리헨션과 여러 가지 작은 면에서 차이가 있습니다. 가장 중요한 점은 루프 변수(위 예제의 obj)를 제너레이터 표현식 외부에서 접근할 수 없다는 것입니다. 리스트 컴프리헨션은 변수를 마지막 값으로 할당해 둡니다. 파이썬의 향후 버전에서는 이를 변경하여 이 측면에서 리스트 컴프리헨션이 제너레이터 표현식과 일치하게 될 것입니다.

더 보기

PEP 289 - 제너레이터 표현식

Raymond Hettinger가 제안하고, 초기 노력을 주도한 Hye-Shik Chang의 지도 아래 Jiwon Seo가 구현했습니다.

PEP 292: 더 간단한 문자열 치환

표준 라이브러리의 일부 새로운 클래스들은 문자열에 변수를 치환하는 대안적인 메커니즘을 제공합니다. 이러한 방식의 치환은 숙련되지 않은 사용자가 템플릿을 수정해야 하는 애플리케이션에서 더 적합할 수 있습니다.

이름에 따라 변수를 치환하는 일반적인 방법은 % 연산자입니다:

>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'

템플릿 문자열을 작성할 때 닫는 괄호 뒤에 is 를 빠뜨리기 쉽습니다. 템플릿이 파이썬 모듈 내에 있다면 코드를 실행해 “Unsupported format character” ValueError 를 확인하고 문제를 해결하면 되므로 큰 문제가 되지 않습니다. 그러나 Mailman과 같이 숙련되지 않은 사용자가 템플릿 문자열이나 번역을 수정하는 애플리케이션을 생각해 보십시오. 이러한 사용자들에게 포맷 문자열의 구문을 설명하기는 복잡하며, 그들이 실수했을 때 유용한 피드백을 제공하기도 어렵습니다.

PEP 292는 string 모듈에 $ 를 사용하여 치환을 나타내는 Template 클래스를 추가합니다:

>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'

딕셔너리에서 키가 누락된 경우, substitute() 메서드는 KeyError 를 발생시킵니다. 또한 누락된 키를 무시하는 safe_substitute() 메서드도 있습니다:

>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'

더 보기

PEP 292 - 더 간단한 문자열 치환

Barry Warsaw가 작성하고 구현했습니다.

PEP 318: 함수 및 메서드를 위한 데코레이터

Python 2.2는 정적 메서드와 클래스 메서드를 추가함으로써 파이썬의 객체 모델을 확장했지만, 정적 또는 클래스 메서드를 정의하는 새로운 방식을 제공하기 위해 파이썬의 문법을 확장하지는 않았습니다. 대신, 일반적인 방식으로 def 문을 작성하고, 결과로 나온 메서드를 새 타입의 메서드로 감싸주는 staticmethod() 또는 classmethod() 함수에 전달해야 했습니다. 코드는 다음과 같은 모습이었습니다:

class C:
   def meth (cls):
       ...

   meth = classmethod(meth)   # 래핑된 클래스 메서드로 이름 다시 바인딩

메서드가 매우 길 경우 함수 본문 뒤의 classmethod() 호출을 놓치거나 잊어버리기 쉽습니다.

이러한 정의를 더 읽기 쉽게 만드는 문법을 추가하는 것이 항상 의도였으나, 2.2 버전 출시 당시에는 적절한 구문이 명확하지 않았습니다. 오늘날에도 적절한 구문이 바로 떠오르지는 않지만 사용자들이 이 기능에 대한 더 쉬운 접근을 요구하고 있으며, 이러한 요구를 충족하기 위해 새로운 문법적 기능이 추가되었습니다.

새로운 기능은 “함수 데코레이터”라고 불립니다. 이 이름은 classmethod(), staticmethod() 등이 함수 객체에 추가 정보를 저장한다는 아이디어에서 유래했습니다. 즉, 이들은 함수에 더 많은 세부 정보를 *데코레이트(decorating)*하는 것입니다.

이 표기법은 Java에서 빌려온 것으로 '@' 문자를 표시자로 사용합니다. 새 구문을 사용하면 위 예제는 다음과 같이 작성됩니다:

class C:

   @classmethod
   def meth (cls):
       ...

@classmethod``은 ``meth=classmethod(meth) 할당의 약칭입니다. 더 일반적으로, 다음과 같은 경우가 있다면:

@A
@B
@C
def f ():
    ...

이는 다음 데코레이터 이전 코드와 동일합니다:

def f(): ...
f = A(B(C(f)))

데코레이터는 함수 정의 바로 윗줄에 위치해야 하며 한 줄에 하나씩 배치되어야 합니다. 또한 def 문과 같은 줄에 올 수 없으므로 @A def f(): ... 와 같은 방식은 허용되지 않습니다. 데코레이터는 모듈 수준이나 클래스 내부의 함수 정의만 적용할 수 있으며, 클래스 정의를 데코레이트할 수는 없습니다.

데코레이터는 데코레이트할 함수를 인자로 받아 동일한 함수나 새로운 객체를 반환하는 함수일 뿐입니다. 결과에 추가적인 데코레이터를 적용할 계획이 없다면 데코레이터의 반환값이 콜러블(callable)일 필요는 없습니다(하지만 대개 그러합니다). 자신만의 데코레이터를 만드는 것은 매우 쉽습니다. 다음 간단한 예제는 함수 객체에 속성을 설정하는 경우입니다:

>>> def deco(func):
...    func.attr = 'decorated'
...    return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>

조금 더 실제적인 사례로, 다음 데코레이터는 제공된 인자가 정수인지 확인합니다:

def require_int (func):
    def wrapper (arg):
        assert isinstance(arg, int)
        return func(arg)

    return wrapper

@require_int
def p1 (arg):
    print arg

@require_int
def p2(arg):
    print arg*2

PEP 318 의 예제에는 필요한 타입을 지정하고 반환된 타입을 확인하는 기능이 포함된 더 화려한 버전의 아이디어가 포함되어 있습니다.

데코레이터 함수는 인자를 가질 수 있습니다. 인자가 제공되는 경우 데코레이터 함수는 해당 인자들만 사용하여 호출되며, 반드시 새로운 데코레이터 함수를 반환해야 합니다. 이 함수는 앞서 설명한 대로 단일 함수를 받아 함수를 반환해야 합니다. 즉, @A @B @C(args) 는 다음과 같이 됩니다:

def f(): ...
_deco = C(args)
f = A(B(_deco(f)))

이것을 정확히 구현하는 것이 약간 머리 아플 수 있지만, 그리 어렵지는 않습니다.

관련된 작은 변경으로 함수의 func_name 속성을 쓰기 가능하게 만들었습니다. 이 속성은 트레이스백에서 함수 이름을 표시하는 데 사용되므로, 데코레이터는 생성 및 반환되는 모든 새 함수의 이름을 변경해야 합니다.

더 보기

PEP 318 - 함수, 메서드 및 클래스를 위한 데코레이터

Kevin D. Smith, Jim Jewett, 그리고 Skip Montanaro가 작성했습니다. 여러 사람이 함수 데코레이터를 구현하는 패치를 작성했지만, 실제로 반영된 것은 Mark Russell이 작성한 패치 #979728입니다.

https://wiki.python.org/moin/PythonDecoratorLibrary

이 위키 페이지에는 데코레이터의 여러 예제가 포함되어 있습니다.

PEP 322: 역순 이터레이션

새로운 내장 함수인 reversed(seq) 는 시퀀스를 받아 요소들을 역순으로 순회하는 이터레이터를 반환합니다.

>>> for i in reversed(xrange(1,4)):
...    print i
...
3
2
1

range(1,4)[::-1] 와 같은 확장 슬라이싱과 비교할 때, reversed() 는 읽기 더 쉽고 실행 속도가 빠르며 메모리를 훨씬 적게 사용합니다.

reversed() 는 임의의 이터레이터가 아닌 시퀀스만 허용한다는 점에 유의하십시오. 이터레이터를 역순으로 처리하려면 먼저 list() 를 사용하여 리스트로 변환해야 합니다.

>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
...   print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
  ...

더 보기

PEP 322 - 역순 이터레이션

Raymond Hettinger가 작성하고 구현했습니다.

PEP 324: 새로운 subprocess 모듈

표준 라이브러리는 다양한 기능과 복잡도 수준을 제공하는 여러 가지 방식으로 서브프로세스를 실행할 수 있는 방법을 제공합니다. os.system(command) 는 사용하기 쉽지만 느리고(명령을 실행하는 셸 프로세스를 실행함) 위험합니다(셸의 메타문자를 이스케이프 처리하는 데 주의해야 함). popen2 모듈은 서브프로세스로부터 표준 출력과 표준 오류를 캡처할 수 있는 클래스들을 제공하지만 이름이 혼동될 수 있습니다. subprocess 모듈은 이를 정리하여 필요할 수 있는 모든 기능을 제공하는 통합된 인터페이스를 제공합니다.

popen2 의 클래스 모음 대신, subprocess 는 다양한 키워드 인자를 지원하는 생성자를 가진 단일 클래스인 subprocess.Popen 을 포함합니다.

class Popen(args, bufsize=0, executable=None,
            stdin=None, stdout=None, stderr=None,
            preexec_fn=None, close_fds=False, shell=False,
            cwd=None, env=None, universal_newlines=False,
            startupinfo=None, creationflags=0):

args 는 일반적으로 서브 프로세스로 실행될 프로그램의 인자가 될 문자열 시퀀스입니다. (<em>shell</em> 인자가 참인 경우, argsos.system() 과 동일하게 해석을 위해 셸로 전달되는 문자열일 수 있습니다.)

stdin, stdout, 그리고 stderr 은 서브 프로세스의 입력, 출력 및 에러 스트림을 지정합니다. 파일 객체나 파일 디스크립터를 제공할 수도 있고, subprocess.PIPE 상수를 사용하여 서브 프로세스와 부모 프로세스 사이에 파이프를 생성할 수도 있습니다.

생성자에는 다음과 같은 유용한 옵션들이 있습니다:

  • close_fds 는 서브 프로세스를 실행하기 전에 모든 파일 디스크립터를 닫도록 요청합니다.

  • cwd 는 서브 프로세스가 실행될 작업 디렉터리를 지정합니다 (기본값은 부모의 작업 디렉터리로 설정됩니다).

  • env 는 환경 변수를 정의하는 딕셔너리입니다.

  • preexec_fn 은 자식 프로세스가 시작되기 전에 호출되는 함수입니다.

  • universal_newlines 는 Python의 universal newlines 기능을 사용하여 자식의 입출력을 엽니다.

Popen 인스턴스를 생성한 후, 서브프로세스가 종료될 때까지 일시 중지하려면 wait() 메서드를 호출하거나, 일시 중지 없이 종료 여부를 확인하려면 ``communicate(data)``는 서브프로세스가 표준 출력 또는 표준 오류로 보낸 모든 데이터를 읽어 ``(stdout_data, stderr_data)`() 튜플을 반환합니다.

call() 은 인수를 Popen 생성자에 전달하고 명령이 완료될 때까지 대기한 다음 서브프로세스의 상태 코드를 반환하는 단축 경로입니다. 이는 os.system() 에 대한 더 안전한 대안으로 사용될 수 있습니다:

sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
    # 성공
    ...
else:
    # dpkg가 에러를 반환함
    ...

명령은 셸을 사용하지 않고 호출됩니다. 만약 실제로 셸을 사용하고자 한다면, 키워드 인자로 shell=True 를 추가하고 시퀀스 대신 문자열을 제공할 수 있습니다:

sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)

이 PEP는 다양한 셸 및 Python 코드 예제를 포함하며, 이들이 어떻게 subprocess 를 사용하는 Python 코드로 변환되는지 보여줍니다. 이 섹션을 읽어보는 것을 강력히 권장합니다.

더 보기

PEP 324 - subprocess - 새 프로세스 모듈

Peter Åstrand이 작성 및 구현하였으며, Fredrik Lundh 및 다른 이들이 도움을 주었습니다.

PEP 327: Decimal 데이터 타입

Python은 기초가 되는 C double 유형을 기반으로 부동 소수점(FP) 숫자를 데이터 타입으로 항상 지원해 왔습니다. 그러나 대부분의 프로그래밍 언어가 부동 소수점 타입을 제공함에도 불구하고, 많은 사람들(심지어 프로그래머들도 포함)은 부동 소수점 숫자가 특정 소수 분수를 정확하게 표현하지 못한다는 사실을 알지 못합니다. 새로운 Decimal 타입은 이러한 분수를 사용자 지정 정밀도 한도 내에서 정확하게 나타낼 수 있습니다.

왜 Decimal이 필요한가?

이러한 제한은 부동 소수점 숫자에 사용되는 표기 방식에서 발생합니다. FP 숫자는 세 가지 구성 요소로 이루어집니다:

  • 양성 또는 음성을 나타내는 부호.

  • 소수 부분이 뒤따르는 단일 자리 이진수입니다. 예를 들어, 2진법 표기법의 1.011 + 0/2 + 1/4 이며, 이는 십진법으로 1.25입니다.

  • 표현된 수에서 소수점의 위치를 알려주는 지수.

예를 들어, 숫자 1.25는 양의 부호, 1.01(이진법)의 가수 값, 그리고 0의 지수를 가집니다(소수점 이동이 필요하지 않음). 숫자 5는 동일한 부호와 가수를 갖지만, 가수가 지수 2만큼 곱해지므로(지수 2에 대한 2의 거듭제곱인 4를 곱함) 지수는 2입니다. 1.25 * 4는 5가 됩니다.

현대 시스템은 일반적으로 IEEE 754 표준을 따르는 부동 소수점 지원을 제공합니다. C의 double 타입은 보통 가수를 위해 52비트 공간을 사용하는 64비트 IEEE 754 숫자로 구현됩니다. 이는 숫자가 최대 52비트 정밀도까지만 지정될 수 있음을 의미합니다. 만약 무한히 반복되는 확장을 가진 숫자를 표현하려 한다면, 해당 확장은 52비트 이후에 잘리게 됩니다. 불행하게도 대부분의 소프트웨어는 10진법으로 출력을 생성해야 하며, 10진법의 일반적인 분수들은 이진법에서 종종 반복되는 소수가 됩니다. 예를 들어, 십진수 1.1은 이진수로 1.0001100110011 ... 이며, .1 = 1/16 + 1/32 + 1/256에 무한히 많은 추가 항이 더해진 값입니다. IEEE 754는 52자리가 지난 후 이 무한히 반복되는 소수를 잘라내야 하므로 표현이 약간 부정확합니다.

때때로 숫자를 출력할 때 이러한 부정확함을 확인할 수 있습니다:

>>> 1.1
1.1000000000000001

C 라이브러리에서 제공하는 FP-to-decimal-string 변환이 대부분의 C 라이브러리에서 합리적인 출력을 생성하려고 시도하기 때문에, 숫자를 출력할 때 이 부정확함이 항상 눈에 띄는 것은 아닙니다. 하지만 표시되지 않더라도 부정확함은 여전히 존재하며 후속 연산에서 오류가 증폭될 수 있습니다.

많은 애플리케이션에서 이는 문제가 되지 않습니다. 점을 그래프로 그리고 모니터에 표시하는 경우, 1.1과 1.1000000000000001의 차이는 너무 작아 눈으로 식별할 수 없습니다. 보고서는 종종 출력을 특정 소수점 자릿수로 제한하며, 숫자를 두 자리 또는 세 자리, 심지어 여덟 자리까지 반올림하면 오류가 전혀 드러나지 않습니다. 그러나 이 문제가 중요한 애플리케이션의 경우, 자체 맞춤형 산술 루틴을 구현하는 것은 많은 노력이 필요합니다.

따라서, Decimal 유형이 생성되었습니다.

Decimal 유형

새로운 모듈인 decimal 이 Python 표준 라이브러리에 추가되었습니다. 이 모듈은 DecimalContext 두 가지 클래스를 포함합니다. Decimal 인스턴스는 숫자를 나타내고, Context 인스턴스는 정밀도 및 기본 반올림 모드와 같은 다양한 설정을 래핑하는 데 사용됩니다.

Decimal 인스턴스는 일반적인 Python 정수나 부동 소수점 숫자와 마찬가지로 불변이며, 일단 생성되면 해당 인스턴스가 나타내는 값을 변경할 수 없습니다. Decimal 인스턴스는 정수 또는 문자열로부터 생성될 수 있습니다:

>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")

또한 부호, 십진 자리의 튜플로 표현된 가수, 그리고 지수를 포함하는 튜플을 제공할 수도 있습니다:

>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")

주의: 부호 비트는 불리언(Boolean) 값이므로, 0은 양수이고 1은 음수입니다.

부동 소수점 숫자로부터 변환하는 것은 약간의 문제를 일으킵니다. 1.1을 나타내는 부동 소수점 숫자가 정확히 1.1을 나타내는 십진수(decimal)로 변환되어야 할지, 아니면 도입된 모든 오차를 포함한 수로 변환되어야 할지의 문제입니다. 이에 대한 결정은 이 문제를 피하기 위해 해당 변환을 API에서 제외하는 것이었습니다. 대신, 원하는 정밀도를 사용하여 부동 소수점 숫자를 문자열로 변환하고 그 문자열을 Decimal 생성자에 전달해야 합니다:

>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")

Decimal 인스턴스가 있으면 이를 통해 일반적인 산술 연산을 수행할 수 있습니다. 한 가지 제한 사항은 거듭제곱을 할 때 정수 지수가 필요하다는 것입니다:

>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
  ...
decimal.InvalidOperation: x ** (non-integer)

Decimal 인스턴스를 정수와 결합할 수 있지만, 부동 소수점 숫자와는 결합할 수 없습니다:

>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
  ...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>

Decimal 숫자는 mathcmath 모듈과 함께 사용할 수 있지만, 연산이 수행되기 전에 즉시 부동 소수점 숫자로 변환되어 정밀도와 정확성이 손실될 가능성이 있다는 점에 유의하십시오. 또한 결과로 얻는 값은 Decimal 이 아닌 일반적인 부동 소수점 숫자입니다.

>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j

Decimal 인스턴스는 Decimal 을 반환하는 sqrt() 메서드를 가지지만, 삼각함수와 같은 다른 기능이 필요한 경우에는 직접 구현해야 합니다.

>>> d.sqrt()
Decimal("351364.1828820134592177245001")

Context 타입

Context 클래스의 인스턴스는 십진 연산을 위한 여러 설정을 캡슐화합니다:

  • prec 은 소수점 자릿수인 정밀도입니다.

  • rounding specifies the rounding mode. The decimal module has constants for the various possibilities: ROUND_DOWN, ROUND_CEILING, ROUND_HALF_EVEN, and various others.

  • traps 는 특정 오류 조건이 발생했을 때 어떤 일이 일어나는지(예외가 발생하거나 값이 반환됨)를 지정하는 딕셔너리입니다. 오류 조건의 예로는 0으로 나누기, 정밀도 손실, 오버플로 등이 있습니다.

getcontext() 를 호출하여 사용할 수 있는 스레드 로컬 기본 컨텍스트가 있습니다. 이 컨텍스트의 속성을 변경하여 기본 정밀도, 반올림 방식 또는 트랩 처리를 변경할 수 있습니다. 다음 예제는 기본 컨텍스트의 정밀도를 변경했을 때의 효과를 보여줍니다:

>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")

오류 조건에 대한 기본 동작은 선택 가능합니다. 모듈은 무한대나 NaN과 같은 특수 값을 반환하거나 예외를 발생시킬 수 있습니다:

>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
  ...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>

Context 인스턴스는 또한 to_eng_string()to_sci_string() 과 같은 숫자를 형식화하는 다양한 메서드를 포함합니다.

더 자세한 정보는 decimal 모듈의 문서를 참조하십시오. 이 문서에는 빠른 시작 가이드와 레퍼런스가 포함되어 있습니다.

더 보기

PEP 327 - Decimal 데이터 타입

Facundo Batista가 작성하고 Facundo Batista, Eric Price, Raymond Hettinger, Aahz, Tim Peters가 구현했습니다.

http://www.lahey.com/float.htm

이 기사는 Fortran 코드를 사용하여 부동 소수점 부정확성으로 인해 발생할 수 있는 여러 문제를 설명합니다.

https://speleotrove.com/decimal/

Decimal 기반 표현에 대한 설명입니다. 이 표현은 표준으로 제안되고 있으며, 새로운 Python decimal 타입을 구성합니다. 이 내용의 상당 부분은 Rexx 언어의 설계자인 Mike Cowlishaw가 작성했습니다.

PEP 328: 다중 행 임포트

하나의 언어 변경 사항은 모듈에서 많은 이름을 더 쉽게 임포트할 수 있도록 하는 작은 구문 조정입니다. from module import names 문장에서 names 는 쉼표로 구분된 이름 시퀀스입니다. 시퀀스가 매우 길 경우, 동일한 모듈에서 여러 번의 임포트를 작성하거나 다음과 같이 백슬래시를 사용하여 줄 끝을 이스케이프할 수 있습니다:

from SimpleXMLRPCServer import SimpleXMLRPCServer,\
            SimpleXMLRPCRequestHandler,\
            CGIXMLRPCRequestHandler,\
            resolve_dotted_attribute

Python 2.4의 구문 변경은 단순히 이름을 괄호 안에 넣는 것을 허용합니다. Python은 괄호로 둘러싸인 표현식 내의 새 줄을 무시하므로 더 이상 백슬래시가 필요하지 않습니다:

from SimpleXMLRPCServer import (SimpleXMLRPCServer,
                                SimpleXMLRPCRequestHandler,
                                CGIXMLRPCRequestHandler,
                                resolve_dotted_attribute)

이 PEP는 모든 import 문이 절대 임포트여야 하며, 상대 임포트를 나타내기 위해 앞에 . 문자를 붙일 것을 제안합니다. 이 부분은 Python 2.4에서는 구현되지 않았으나, Python 2.5에서 완료되었습니다.

더 보기

PEP 328 - 임포트: 다중 행 및 절대/상대

Aahz가 작성하고 Dima Dorfman이 다중 행 임포트를 구현했습니다.

PEP 331: 로케일 독립적인 부동 소수점/문자열 변환

locale 모듈은 파이썬 소프트웨어가 특정 국가나 언어에 맞춰 로컬화된 다양한 변환 및 표시 규칙을 선택할 수 있게 합니다. 하지만, 파이썬 구현의 여러 함수가 숫자 로케일이 'C' 로케일로 유지될 것을 요구했기 때문에 이 모듈은 숫자 로케일을 변경하지 않도록 주의를 기울였습니다. 이는 종종 코드가 C 라이브러리의 atof() 함수를 사용하기 때문이었습니다.

숫자 로케일을 설정하지 않은 것은 타사 C 라이브러리를 사용하는 확장 기능에서 문제가 되었는데, 왜냐하면 올바른 로케일이 설정되지 않았기 때문입니다. 대표적인 사례는 사용자 인터페이스 위젯이 현재 로케일로 숫자를 표시하지 않는 GTK+였습니다.

PEP에 설명된 해결책은 Python API에 로케일 설정을 무시하고 ASCII 전용 변환을 수행하는 세 가지 새로운 함수를 추가하는 것입니다:

  • PyOS_ascii_strtod(str, ptr)PyOS_ascii_atof(str, ptr) 는 모두 문자열을 C double 로 변환합니다.

  • PyOS_ascii_formatd(buffer, buf_len, format, d)double 을 ASCII 문자열로 변환합니다.

이 함수들의 코드는 GLib 라이브러리(https://developer-old.gnome.org/glib/2.26/ )에서 가져왔으며, 해당 라이브러리의 개발자들이 관련 함수를 재라이선스하여 Python Software Foundation에 기부했습니다. 이제 locale 모듈은 숫자 로케일을 변경할 수 있어 GTK+와 같은 확장 기능이 올바른 결과를 생성할 수 있게 되었습니다.

더 보기

PEP 331 - 로케일 독립적인 부동 소수점/문자열 변환

Christian R. Reis가 작성하고 Gustavo Carneiro가 구현했습니다.

이외의 언어 변경 사항

다음은 Python 2.4가 핵심 Python 언어에 적용한 모든 변경 사항입니다.

  • 함수 및 메서드용 데코레이터가 추가되었습니다 (PEP 318).

  • 내장된 set()frozenset() 타입이 추가되었습니다 (PEP 218). 다른 새로운 내장 기능으로는 reversed(seq) 함수가 포함됩니다 (PEP 322).

  • 제너레이터 표현식이 추가되었습니다 (PEP 289).

  • 특정 숫자 표현이 더 이상 32비트 또는 64비트로 제한된 값을 반환하지 않습니다 (PEP 237).

  • 이제 from module import names 문장에서 이름 리스트를 괄호로 묶을 수 있습니다 (PEP 328).

  • The dict.update() 메서드가 이제 dict 생성자와 동일한 인자 형태를 수용합니다. 여기에는 모든 매핑, 키/값 쌍의 모든 이터러블 및 키워드 인자가 포함됩니다. (Raymond Hettinger가 기여함.)

  • 문자열 메서드인 ljust(), rjust(), 그리고 center() 는 이제 공백 이외의 채움 문자를 지정하는 선택적 인수를 받습니다. (Raymond Hetikker 기여)

  • 문자열은 또한 split() 메서드와 유사하게 작동하지만 문자열의 끝에서부터 분할하는 rsplit() 메서드를 얻게 되었습니다. (Sean Reifschneider 기여)

    >>> 'www.python.org'.split('.', 1)
    ['www', 'python.org']
    'www.python.org'.rsplit('.', 1)
    ['www.python', 'org']
    
  • 리스트의 sort() 메서드에 cmp, key, 그리고 reverse 라는 세 가지 키워드 매개변수가 추가되었습니다. 이 매개변수들은 sort() 의 몇몇 일반적인 사용 사례를 더 단순하게 만들어 줍니다. 이 모든 매개변수는 선택 사항입니다.

    cmp 매개변수의 경우, 값은 두 매개변수를 받아 그 비교 결과에 따라 -1, 0 또는 +1을 반환하는 비교 함수여야 합니다. 이 함수는 리스트를 정렬하는 데 사용됩니다. 이전에는 이것이 sort() 에 제공할 수 있는 유일한 매개변수였습니다.

    key 는 리스트 요소를 받아 해당 요소의 비교 키를 반환하는 단일 매개변수 함수여야 합니다. 그런 다음 리스트는 비교 키를 사용하여 정렬됩니다. 다음 예제는 대소문자를 구분하지 않고 리스트를 정렬합니다:

    >>> L = ['A', 'b', 'c', 'D']
    >>> L.sort()                 # 대소문자 구분 정렬
    >>> L
    ['A', 'D', 'b', 'c']
    >>> # 리스트를 정렬하기 위해 'key' 매개변수 사용
    >>> L.sort(key=lambda x: x.lower())
    >>> L
    ['A', 'b', 'c', 'D']
    >>> # 예전 방식
    >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))
    >>> L
    ['A', 'b', 'c', 'D']
    

    cmp 매개변수를 사용하는 마지막 예제는 대소문자를 구분하지 않는 정렬을 수행하는 옛 방식입니다. 작동은 하지만 key 매개변수를 사용하는 것보다 느립니다. key 를 사용하면 리스트의 각 요소에 대해 lower() 메서드를 한 번 호출하지만, cmp 를 사용하면 각 비교마다 두 번 호출하므로, key 를 사용하는 것이 lower() 메서드 호출 횟수를 줄여줍니다.

    단순한 키 함수와 비교 함수의 경우, 바인딩되지 않은 메서드를 사용하여 lambda 표현식을 피할 수 있는 경우가 많습니다. 예를 들어, 위의 대소문자 구분 없는 정렬은 다음과 같이 작성하는 것이 가장 좋습니다:

    >>> L.sort(key=str.lower)
    >>> L
    ['A', 'b', 'c', 'D']
    

    마지막으로, reverse 매개변수는 불리언 값을 가집니다. 값이 참이면 리스트가 역순으로 정렬됩니다. L.sort(); L.reverse() 대신 이제 L.sort(reverse=True) 라고 작성할 수 있습니다.

    정렬 결과가 이제 안정적임이 보장됩니다. 이는 키가 같은 두 항목이 입력된 순서와 동일하게 반환됨을 의미합니다. 예를 들어, 사람들의 리스트를 이름으로 정렬한 다음 나이로 정렬하면, 같은 나이의 사람들이 이름 순으로 정렬된 상태에서 나이순으로 정렬된 리스트를 얻을 수 있습니다.

    (sort() 에 대한 모든 변경 사항은 Raymond Hetikker가 기여했습니다.)

  • 그 자리에 있는 list.sort() 메서드와 유사하게 작동하지만 표현식에서 사용할 수 있는 새로운 내장 함수 sorted(iterable) 이 있습니다. 차이점은 다음과 같습니다:

  • 입력값이 어떤 이터러블이어도 될 수 있으며;

  • 새로 생성된 복사본이 정렬되어 원본은 그대로 유지됩니다. 그리고

  • 표현식이 새로 정렬된 복사본을 반환합니다.

    >>> L = [9,7,8,3,2,4,1,6,5]
    >>> [10+i for i in sorted(L)]       # 리스트 컴프리헨션에서 사용 가능
    [11, 12, 13, 14, 15, 16, 17, 18, 19]
    >>> L                               # 원본은 변경되지 않음
    [9,7,8,3,2,4,1,6,5]
    >>> sorted('Monty Python')          # 어떤 이터러블도 입력 가능
    [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y']
    
    >>> # 키 값으로 정렬된 딕셔너리의 내용을 나열
    >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5)
    >>> for k, v in sorted(colormap.iteritems()):
    ...     print k, v
    ...
    black 4
    blue 2
    green 3
    red 1
    yellow 5
    

    (Raymond Hettinger가 기여했습니다.)

  • 정수 연산이 더 이상 OverflowWarning`을 발생시키지 않습니다. :exc:!OverflowWarning` 경고는 파이썬 2.5에서 사라질 예정입니다.

  • 인터프리터가 이름을 받아 sys.path 에서 해당 모듈을 찾아 스크립트로 실행하는 새로운 옵션인 -m 을 추가했습니다. 예를 들어, 이제 python -m profile 명령으로 Python 프로파일러를 실행할 수 있습니다. (Nick Coghlan이 기여함.)

  • eval(expr, globals, locals)execfile(filename, globals, locals) 함수와 exec 문은 이제 locals 매개변수로 모든 매핑 타입을 허용합니다. 이전에는 반드시 일반 Python 딕셔너리여야 했습니다. (Raymond Hettinger가 기여함.)

  • zip() 내장 함수와 itertools.izip() 은 이제 인자 없이 호출될 때 빈 리스트를 반환합니다. 이전에는 TypeError 예외를 발생시켰습니다. 이를 통해 가변 길이 인수 목록과 함께 사용하기에 더 적합해졌습니다:

    >>> def transpose(array):
    ...    return zip(*array)
    ...
    >>> transpose([(1,2,3), (4,5,6)])
    [(1, 4), (2, 5), (3, 6)]
    >>> transpose([])
    []
    

    (Raymond Hettinger가 기여했습니다.)

  • 모듈을 임포트하는 중에 실패가 발생해도 더 이상 sys.modules 에 부분적으로 초기화된 모듈 객체가 남지 않습니다. 뒤에 남겨진 불완전한 모듈 객체는 동일한 모듈의 추가 임포트를 성공으로 오인하게 만들어 혼란스러운 오류를 유발할 수 있습니다. (Tim Peters가 해결함.)

  • None is now a constant; code that binds a new value to the name None is now a syntax error. (Contributed by Raymond Hettinger.)

최적화들`

  • 리스트 및 튜플 슬라이싱의 내부 루프가 최적화되어 이제 약 3분의 1 더 빠르게 실행됩니다. 딕셔너리의 내부 루프도 최적화되어 keys(), values(), items(), iterkeys(), itervalues(), 및 iteritems() 의 성능이 향상되었습니다. (Raymond Hetikker 기여)

  • 리스트를 늘리고 줄이는 메커니즘이 속도와 공간 효율을 위해 최적화되었습니다. 리스트에서 요소 추가(Append) 및 제거(Pop)가 더 효율적인 코드 경로와 빈번하지 않은 하위 시스템 realloc() 사용 덕분에 더 빠르게 작동합니다. 리스트 컴프리헨션 또한 혜택을 받습니다. list.extend() 또한 최적화되어 기본 리스트를 확장하기 전에 인자를 임시 리스트로 변환하지 않습니다. (Raymond Hetlinger가 기여함.)

  • list(), tuple(), map(), filter(), 및 zip() 은 이제 __len__() 메서드를 제공하는 비시퀀스 인자를 사용할 때 몇 배 더 빠르게 실행됩니다. (Raymond Hetikker 기여)

  • list.__getitem__(), dict.__getitem__(), 및 dict.__contains__() 메서드가 이제 wrapper_descriptor 객체가 아닌 method_descriptor 객체로 구현됩니다. 이러한 형태의 액세스는 성능을 두 배로 높이며, map(mydict.__getitem__, keylist) 와 같이 함수형 프로그래밍의 인자로 사용하기에 더 적합하게 만듭니다. (Raymond Hetikker 기여)

  • 리스트 컴프리헨션을 위한 생성된 바이트코드를 단순화하고 속도를 약 3분의 1 향상시키는 새로운 opcode인 LIST_APPEND 가 추가되었습니다. (Raymond Hettinger 기여)

  • 피프홀(peephole) 바이트코드 최적화 도구가 개선되어 더 짧고 빠른 바이트코드를 생성하며, 결과적으로 생성된 바이트코드가 가독성도 훨씬 좋아졌습니다. (Raymond Hettinger 강화)

  • s = s + "abc"s += "abc" 형태의 구문에서 문자열 결합이 특정 상황에서 더 효율적으로 수행됩니다. 이 최적화는 Jython과 같은 다른 파이썬 구현체에서는 지원되지 않으므로 이에 의존해서는 안 되며, 많은 수의 문자열을 효율적으로 이어 붙이고 싶을 때는 여전히 문자열의 join() 메서드를 사용하는 것이 권장됩니다. (Armin Rigo 기여)

2.4 최적화의 결과로, Python 2.4는 pystone 벤치마크에서 Python 2.3보다 약 5%, Python 2.2보다 35% 더 빠르게 실행됩니다. (pystone이 아주 뛰어난 벤치마크는 아니지만, Python 성능 측정에 가장 흔히 사용되는 도구입니다. 귀하의 애플리케이션에 따라 Python 2.4에서 얻을 수 있는 이점은 더 크거나 작을 수 있습니다.)

새로운, 개선된, 그리고 더 이상 사용되지 않는 모듈

여느 때와 마찬가지로 Python 표준 라이브러리에 다수의 개선 사항과 버그 수정이 포함되었습니다. 다음은 모듈 이름의 알파벳 순서에 따른 주요 변경 사항의 일부입니다. 더 상세한 목록을 확인하려면 소스 트리의 Misc/NEWS 파일을 참조하거나 CVS 로그를 통해 자세한 내용을 확인할 수 있습니다.

  • asyncore 모듈의 loop() 함수에 폴링 루프를 제한된 횟수만큼 수행할 수 있게 하는 count 매개변수가 추가되었습니다. 기본값은 여전히 무한 반복입니다.

  • base64 모듈이 선택적 대소문자 통합(case folding) 및 선택적인 대체 알파벳을 포함하여 Base64, Base32, Base16 인코딩 및 디코딩에 대해 더욱 완전한 RFC 3548 지원을 제공합니다. (Barry Warsaw 기여)

  • bisect 모듈이 성능 향상을 위해 기초가 되는 C 구현을 갖추게 되었습니다. (Dmitry Vasiliev 기여)

  • Hye-Shik Chang이 관리하는 동아시아 코드셋 모음인 CJKCodecs가 2.4에 통합되었습니다. 새로운 인코딩은 다음과 같습니다.

  • 중국(PRC): gb2312, gbk, gb18030, big5hkscs, hz

  • 중국(ROC): big5, cp950

  • 일본어: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,

    iso-2022-jp-1, iso-2022-jp-2, iso-2022-jp-3, iso-2022-jp-ext, iso-2022-jp-2004, shift-jis, shift-jisx0213, shift-jis-2004

  • 한국어: cp949, euc-kr, johab, iso-2022-kr

  • 기타 새로운 인코딩들이 추가되었습니다: HP Roman8, ISO_8859-11, ISO_8859-16, PCTP-154, TIS-620.

  • The UTF-8 and UTF-16 codecs now cope better with receiving partial input. Previously the StreamReader class would try to read more data, making it impossible to resume decoding from the stream. The read() method will now return as much data as it can and future calls will resume decoding where previous ones left off. (Implemented by Walter Dörwald.)

  • 다양한 특수 컬렉션 데이터 타입을 위한 새로운 collections 모듈이 있습니다. 현재 이 모듈은 어느 쪽 끝에서든 요소를 효율적으로 추가하고 제거하는 것을 지원하는 양방향 큐인 deque 한 종류만 포함합니다:

    >>> from collections import deque
    >>> d = deque('ghi')        # 세 항목을 가진 새 데크를 만듭니다
    >>> d.append('j')           # 오른쪽에 새로운 항목을 추가합니다
    >>> d.appendleft('f')       # 왼쪽에 새로운 항목을 추가합니다
    >>> d                       # 데크의 표현을 보여줍니다
    deque(['f', 'g', 'h', 'i', 'j'])
    >>> d.pop()                 # 가장 오른쪽 항목을 제거하고 반환합니다
    'j'
    >>> d.popleft()             # 가장 왼쪽 항목을 제거하고 반환합니다
    'f'
    >>> list(d)                 # 데크의 내용을 리스트로 변환합니다
    ['g', 'h', 'i']
    >>> 'h' in d                # 데크를 검색합니다
    True
    

    queuethreading 모듈과 같은 여러 모듈이 성능 향상을 위해 collections.deque 를 활용합니다. (Raymond Hettinger 기여)

  • ConfigParser 클래스가 약간 개선되었습니다. read() 메서드는 이제 성공적으로 파싱된 파일들의 리스트를 반환하며, set() 메서드는 문자열이 아닌 value 인자를 전달받을 경우 TypeError 를 발생시킵니다. (John Belmonte와 David Goodger 기여)

  • curses 모듈은 이제 ncurses 확장 기능인 use_default_colors() 를 지원합니다. 터미널이 투명도를 지원하는 플랫폼에서 이를 통해 투명한 배경을 사용할 수 있습니다. (Jörg Lehmann 기여)

  • difflib 모듈에 이제 텍스트의 두 버전을 나란히 비교하여 보여주는 HTML 테이블을 생성하는 HtmlDiff 클래스가 포함됩니다. (Dan Gass 기여)

  • email 패키지가 3.0 버전으로 업데이트되었으며, 이 버전에서는 더 이상 사용되지 않는 여러 API를 제거하고 파이썬 2.3 이전 버전에 대한 지원을 중단했습니다. 해당 패키지의 3.0 버전은 email.FeedParser 모듈에서 사용할 수 있는 MIME 메시지용 새로운 점진적(incremental) 파서를 사용합니다. 이 새 파서는 전체 메시지를 메모리에 로드할 필요가 없으며, 메시지 형식이 잘못되었을 때 예외를 발생시키지 않습니다. 대신 메시지의 defect 속성에 문제를 기록합니다. (Anthony Baxter, Barry 워쇼, Thomas Wouters 등이 개발)

  • heapq 모듈이 C로 전환되었습니다. 그 결과 속도가 10배 향상되어 대량의 데이터를 처리하는 데 적합해졌습니다. 또한, 이 모듈은 전체를 정렬하는 비용 없이 데이터 세트에서 가장 큰 또는 작은 N개의 값을 찾기 위해 힙을 사용하는 두 개의 새로운 함수 nlargest()nsmallest() 를 제공합니다. (Raymond Hetikker 기여)

  • httplib 모듈에 이제 다양한 HTTP 관련 RFC 문서에 정의된 HTTP 상태 코드용 상수들이 포함됩니다. 상수는 OK, CREATED, CONTINUE, 그리고 MOVED_PERMANENTLY 와 같은 이름을 가집니다; 전체 목록은 pydoc을 사용하여 확인할 수 있습니다. (Andrew Eland 기여)

  • imaplib 모듈은 이제 IMAP의 THREAD 명령(Yves Dionne 기여)과 새로운 deleteacl()myrights() 메서드(Arnaud Mazin 기여)를 지원합니다.

  • itertools 모듈에 groupby(iterable[, *func*]) 함수가 추가되었습니다. iterable 은 요소 스트림을 반환하기 위해 반복할 수 있는 대상이며, 선택적인 func 매개변수는 요소를 받아 키 값을 반환하는 함수입니다; 생략된 경우 키는 단순히 요소 자신이 됩니다. 그 후 groupby() 는 일치하는 키 값을 가진 요소들을 하위 시퀀스로 그룹화하고, 키 값과 해당 하위 시퀀스에 대한 반복자를 포함하는 2-튜플 시리즈를 반환합니다.

    이것을 더 명확하게 보여주는 예시입니다. key 함수는 숫자가 짝수인지 홀수인지 여부만 반환하며, 따라서 groupby() 의 결과는 연속된 홀수 또는 짝수 그룹을 반환하는 것입니다.

    >>> import itertools
    >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14]
    >>> for key_val, it in itertools.groupby(L, lambda x: x % 2):
    ...    print key_val, list(it)
    ...
    0 [2, 4, 6]
    1 [7]
    0 [8]
    1 [9, 11]
    0 [12, 14]
    >>>
    

    groupby() 는 대개 정렬된 입력과 함께 사용됩니다. groupby() 의 논리는 유닉스의 uniq 필터와 유사하여 중복 요소를 제거하거나, 개수를 세거나, 식별하는 데 매우 편리합니다:

    >>> word = 'abracadabra'
    >>> letters = sorted(word)   # 문자열을 정렬된 문자 리스트로 변환
    >>> letters
    ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']
    >>> for k, g in itertools.groupby(letters):
    ...    print k, list(g)
    ...
    a ['a', 'a', 'a', 'a', 'a']
    b ['b', 'b']
    c ['c']
    d ['d']
    r ['r', 'r']
    >>> # 고유한 문자 목록 추출
    >>> [k for k, g in groupby(letters)]
    ['a', 'b', 'c', 'd', 'r']
    >>> # 문자의 출현 횟수 계산
    >>> [(k, len(list(g))) for k, g in groupby(letters)]
    [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
    

    (Hye-Shik Chang 기여)

  • itertools 에는 또한 iterator 를 복제하는 N 개의 독립적인 이터레이터를 반환하는 tee(iterator, N) 함수가 추가되었습니다. N 이 생략되면 기본값은 2입니다.

    >>> L = [1,2,3]
    >>> i1, i2 = itertools.tee(L)
    >>> i1,i2
    (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>)
    >>> list(i1)               # 첫 번째 이터레이터를 끝까지 실행
    [1, 2, 3]
    >>> list(i2)               # 두 번째 이터레이터를 끝까지 실행
    [1, 2, 3]
    

    tee() 는 반복자가 반환하는 값의 복사본을 유지해야 하며, 최악의 경우 모든 값을 보유해야 할 수도 있음을 유의하십시오. 따라서 긴 입력 스트림에서 앞선 이터레이터가 뒤따르는 이터레이터보다 훨씬 앞서 나갈 가능성이 있는 경우 주의해서 사용해야 합니다. 차이가 크다면 대신 list() 를 사용하는 것이 좋습니다. 이터레이터들이 서로 가깝게 추적하는 경우에는 tee() 가 이상적입니다. 가능한 응용 사례로는 북마크, 윈도잉 또는 미리 보기(lookahead) 이터레이터 등이 있습니다. (Raymond Hetikker 기여)

  • 특정 인코딩을 지정하는 bind_textdomain_codeset`과 선택한 인코딩으로 메시지를 반환하는 일련의 :func:()!l*gettext` 함수와 같은 여러 함수가 locale 모듈에 추가되었습니다. (Gustavo Niemeyer 기여)

  • 로그 구성을 단순화하기 위해 logging 패키지의 basicConfig() 함수에 몇 가지 키워드 인수가 추가되었습니다. 기본 동작은 메시지를 표준 에러로 기록하는 것이지만, 다양한 키워드 인수를 지정하여 특정 파일에 기록하거나 로그 형식을 변경하거나 로깅 수준을 설정할 수 있습니다. 예를 들어:

    import logging
    logging.basicConfig(filename='/var/log/application.log',
        level=0,  # 모든 메시지 기록
        format='%(levelname):%(process):%(thread):%(message)')
    

    logging 패키지의 다른 추가 사항으로는 편리한 log(level, msg) 메서드와 시간 간격에 따라 로그 파일을 교체하는 TimedRotatingFileHandler 클래스가 있습니다. 해당 모듈은 이미 파일이 특정 크기를 초과할 때 로그를 교체하는 RotatingFileHandler 를 포함하고 있었습니다. 두 클래스 모두 다른 교체형 핸들러를 구현하는 데 사용될 수 있는 새로운 BaseRotatingHandler 클래스에서 파생됩니다.

    (Vinay Sajip에 의해 구현된 변경 사항.)

  • marshal 모듈은 이제 데이터 구조를 언패킹할 때 인터닝된(interned) 문자열을 공유합니다. 이로 인해 특정 피클 문자열의 크기가 줄어들 수 있으며, 주요 효과는 .pyc 파일의 크기가 크게 감소하는 것입니다. (Martin von Löwis 기여)

  • nntplib 모듈의 NNTP 클래스가 단일 그룹 또는 일련의 그룹에 대한 뉴스그룹 설명을 가져오는 description()descriptions() 메서드를 갖게 되었습니다. (Jürgen A. Erhard 기여)

  • operator 모듈에 attrgetter(attr)itemgetter(index) 라는 두 개의 새로운 함수가 추가되었습니다. 두 함수 모두 단일 인자를 받아 해당 속성이나 항목을 반환하는 호출 가능 객체(callable)를 반환하며, 이러한 호출 가능 객체는 map() 또는 sorted() 와 함께 사용할 때 훌륭한 데이터 추출기가 됩니다. 예를 들어:

    >>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]
    >>> map(operator.itemgetter(0), L)
    ['c', 'd', 'a', 'b']
    >>> map(operator.itemgetter(1), L)
    [2, 1, 4, 3]
    >>> sorted(L, key=operator.itemgetter(1)) # 두 번째 튜플 항목을 기준으로 목록 정렬
    [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
    

    (Raymond Hettinger가 기여했습니다.)

  • optparse 모듈이 여러 방식으로 업데이트되었습니다. 이제 이 모듈은 메시지를 gettext.gettext`를 통해 전달하며, 이를 통해 Optik의 도움말과 오류 메시지를 국제화할 있습니다. 옵션에 대한 도움말 메시지에 `()’%default’`` 문자열을 포함할 수 있으며, 이는 해당 옵션의 기본값으로 대체됩니다. (Greg Ward 기여)

  • The long-term plan is to deprecate the rfc822 module in some future Python release in favor of the email package. To this end, the email.Utils.formatdate function has been changed to make it usable as a replacement for rfc822.formatdate(). You may want to write new e-mail processing code with this in mind. (Change implemented by Anthony Baxter.)

  • os 모듈에 n 바이트의 무작위 데이터를 포함하는 문자열을 반환하는 새로운 urandom(n) 함수가 추가되었습니다. 이 함수는 Linux의 /dev/urandom 또는 Windows의 CryptoAPI와 같은 플랫폼별 무작위 소스에 접근할 수 있도록 합니다. (Trevor Perrin 기여)

  • 또 다른 새 기능으로, os.path.lexists(path)``는 *path*로 지정된 파일이 심볼릭 링크 여부와 상관없이 존재하는 경우 True를 반환합니다. 이는 존재하지 않는 대상을 가리키는 심볼릭 링크인 경우 False를 반환하는 기존의 ``os.path.exists(path) 함수와 다릅니다. (Beni Cherniavsky 기여)

  • os 모듈의 기반이 되는 posix 모듈에 새로운 getsid() 함수가 추가되었습니다. (J. Raynor 기여)

  • poplib 모듈이 이제 SSL을 통한 POP를 지원합니다. (Hector Urtubia 기여)

  • profile 모듈을 사용하여 C 확장 함수를 프로파일링할 수 있습니다. (Nick Bastin 기여)

  • random 모듈에 N 비트 길이의 긴 정수를 반환하는 getrandbits(N) 이라는 새 메서드가 추가되었습니다. 기존의 randrange() 메서드는 이제 적절한 경우에 getrandbits() 를 사용하여 임의로 큰 무작위 숫자를 생성하는 효율성이 향상되었습니다. (Raymond Hetikker 기여)

  • re 모듈이 수용하는 정규 표현식 언어에 (?(group)A|B) 와 같이 쓰이는 간단한 조건부 표현이 추가되었습니다. group 은 숫자 그룹 ID이거나 이전에 (?P<group>...) 로 정의된 그룹 이름입니다. 지정된 그룹이 일치하면 정규식 패턴 A 를 문자열에 대조하고, 일치하지 않으면 패턴 B 를 사용합니다. (Gustavo Niemeyer 기여)

  • Gustavo Niemeyer의 방대한 노력 덕분에 re 모듈이 더 이상 재귀적이지 않습니다. 재귀적 정규 표현식 엔진에서는 특정 패턴이 많은 양의 C 스택 공간을 소모하여 스택 오버플로가 발생할 수 있었습니다. 예를 들어, (a|b)+ 라는 식에 30,000바이트의 `a 문자열을 대조하면 문자당 하나의 스택 프레임이 소비되었습니다. Python 2.3은 스택 오버플로를 확인하고 RuntimeError 예외를 발생시키려 시도했지만, 일부 패턴이 이 검사를 우회할 수 있었고 운이 나쁘면 Python이 세그폴트(segfault)가 발생할 수 있었습니다. Python 2.4의 정규 표현식 엔진은 이제 이 패턴을 문제없이 처리합니다.

  • signal 모듈이 이제 signal.signal() 함수의 매개변수에 대해 더 엄격한 오류 검사를 수행합니다. 예를 들어, SIGKILL 시그널에 핸들러를 설정할 수 없습니다. 이전 파이썬 버전에서는 이를 묵인했지만, 2.4 버전부터는 RuntimeError 예외가 발생합니다.

  • socket 모듈에 두 개의 새 함수가 추가되었습니다. socketpair() 는 연결된 소켓 쌍을 반환하며, getservbyport(port) 는 주어진 포트 번호에 대한 서비스 이름을 조회합니다. (Dave Cole 및 Barry Warsaw 기여)

  • sys.exitfunc() 함수가 더 이상 권장되지 않습니다(deprecated). 코드는 여러 종료 함수를 호출하는 것을 올바르게 처리하는 기존의 atexit 모듈을 사용해야 합니다. 결국 sys.exitfunc() 은 오직 atexit 에 의해서만 액세스되는 순수 내부 인터페이스가 될 것입니다.

  • tarfile 모듈이 이제 기본적으로 GNU 형식의 tar 파일을 생성합니다. (Lars Gustäbel 기여)

  • threading 모듈은 이제 스레드 로컬 데이터를 지원하는 세련되게 단순한 방법을 제공합니다. 이 모듈에는 속성 값이 서로 다른 스레드에 국한된 local 클래스가 포함되어 있습니다.

    import threading
    
    data = threading.local()
    data.number = 42
    data.url = ('www.python.org', 80)
    

    다른 스레드는 numberurl 어트리뷰트에 대해 자신만의 값을 할당하고 가져올 수 있습니다. local 을 서브클래스화하여 어트리뷰스를 초기화하거나 메서드를 추가할 수 있습니다. (Jim Fulton 제공)

  • timeit 모듈은 이제 타이밍 루프 중에 주기적인 가비지 컬렉션을 자동으로 비활성화합니다. 이 변경으로 연속된 측정 결과의 비교가 더 용이해집니다. (Raymond Hettinger 기여)

  • weakref 모듈은 이제 Python 함수, 클래스 인스턴스, 세트(set), 프로즌셋(frozenset), 데크(deque), 배열(array), 파일, 소켓 및 정규 표현식 패턴 객체를 포함한 더 다양한 종류의 객체를 지원합니다. (Raymond Hetitter 기여)

  • xmlrpclib 모듈은 이제 단일 HTTP 작업에서 여러 개의 XML-RPC 호출을 전송하기 위한 멀티 콜(multi-call) 확장을 지원합니다. (Brian Quinlan 기여)

  • mpz, rotor, 및 xreadlines 모듈이 제거되었습니다.

cookielib

cookielib 라이브러리는 클라이언트 측의 HTTP 쿠키 처리를 지원하며, 이는 Cookie 모듈의 서버 측 쿠키 지원과 대응됩니다. 쿠키는 쿠키 자(cookie jars)에 저장되며, 이 라이브러리는 웹 서버가 제공하는 쿠키를 쿠키 자에 투명하게 저장하고 서버에 연결할 때 쿠키 자에서 쿠키를 가져옵니다. 웹 브라우저와 마찬가지로 정책 객체가 쿠키 수락 여부를 제어합니다.

세션 간에 쿠키를 저장하기 위해 두 가지 종류의 쿠키 자 구현이 제공됩니다. 하나는 애플리케이션이 Mozilla 또는 Lynx 쿠키 파일을 사용할 수 있도록 Netscape 형식으로 쿠키를 저장하는 것이고, 다른 하나는 Perl libwww 라이브러리와 동일한 형식으로 쿠키를 저장하는 것입니다.

urllib2cookielib 와 상호작용하도록 변경되었습니다: HTTPCookieProcessor 은 URL에 액세스할 때 사용되는 쿠키 저장을 관리합니다.

이 모듈은 John J. Lee에 의해 기여되었습니다.

doctest

doctest 모듈은 Edward Loper와 Tim Peters의 도움으로 대폭적인 리팩토링을 거쳤습니다. 테스트는 여전히 doctest.testmod() 를 실행하는 것만큼 간단할 수 있지만, 리팩토링을 통해 다양한 방식으로 모듈의 동작을 사용자 정의할 수 있습니다.

새로운 DocTestFinder 클래스는 주어진 객체의 독스트링에서 테스트를 추출합니다.

def f (x, y):
    """
>>> f(2,2)
4
>>> f(3,2)
6
    """
    return x*y

finder = doctest.DocTestFinder()

# DocTest 인스턴스 목록 가져오기
tests = finder.find(f)

새로운 DocTestRunner 클래스는 개별 테스트를 실행하고 결과 요약을 생성할 수 있습니다.

runner = doctest.DocTestRunner()
for t in tests:
    tried, failed = runner.run(t)

runner.summarize(verbose=1)

위의 예제는 다음과 같은 출력을 생성합니다:

1 items passed all tests:
   2 tests in f
2 tests in 1 items.
2 passed and 0 failed.
Test passed.

DocTestRunner 은 기대 출력과 실제 출력을 비교하기 위해 OutputChecker 클래스의 인스턴스를 사용합니다. 이 클래스는 동작을 사용자 정의하는 여러 플래그를 받으며, 고급 사용자는 OutputChecker 의 완전히 새로운 서브클래스를 작성할 수도 있습니다.

기본 출력 검사기는 여러 유용한 기능을 제공합니다. 예를 들어, doctest.ELLIPSIS 옵션 플래그를 사용하면 기대 출력 내의 생략 부호(...)가 임의의 부분 문자열과 일치하게 되어, 사소한 차이가 있는 출력도 쉽게 수용할 수 있습니다:

def o (n):
    """>>> o(1)
<__main__.C instance at 0x...>
>>>
"""

또 다른 특수 문자열인 <BLANKLINE> 은 빈 줄과 일치합니다:

def p (n):
    """>>> p(1)
<BLANKLINE>
>>>
"""

새로운 기능 중 하나는 doctest.REPORT_UDIFF (unified diffs), doctest.REPORT_CDIFF (context diffs) 또는 doctest.REPORT_NDIFF (delta-style) 옵션 플래그를 지정하여 출력을 diff 스타일로 표시하는 것입니다. 예를 들어:

def g (n):
    """>>> g(4)
here
is
a
lengthy
>>>"""
    L = 'here is a rather lengthy list of words'.split()
    for word in L[:n]:
        print word

doctest.REPORT_UDIFF 를 지정하고 위 함수의 테스트를 실행하면 다음과 같은 출력이 생성됩니다:

**********************************************************************
File "t.py", line 15, in g
Failed example:
    g(4)
Differences (unified diff with -expected +actual):
    @@ -2,3 +2,3 @@
     is
     a
    -lengthy
    +rather
**********************************************************************

빌드 및 C API 변경사항

Python 빌드 프로세스와 C API에 적용된 변경 사항 중 일부는 다음과 같습니다.

  • 확장 함수에서 흔히 사용되는 반환 값을 위한 세 가지 새로운 편의 매크로인 Py_RETURN_NONE, Py_RETURN_TRUE, 그리고 Py_RETURN_FALSE 가 추가되었습니다. (Brett Cannon 기여)

  • 또 다른 새로운 매크로인 Py_CLEARobj 의 참조 횟수를 줄이고 obj 를 null 포인터로 설정합니다. (Jim Fulton 기여)

  • 새로운 함수인 PyTuple_Pack(N, obj1, obj2, ..., objN) 은 가변 길이의 파이썬 객체 인자 목록으로부터 튜플을 생성합니다. (Raymond Hettinger 기여)

  • 새로운 함수인 PyDict_Contains(d, k) 는 검색 과정에서 발생하는 예외를 마스킹하지 않으면서도 빠른 딕셔너리 조회를 구현합니다. (Raymond Hetinger 기여)

  • Py_IS_NAN 매크로는 플로트 또는 더블 인자 X 가 NaN인 경우 1을 반환합니다. (Tim Peters 제공)

  • 새로운 PyEval_ThreadsInitialized() 함수를 사용하여 스레드 작업이 수행되었는지 확인함으로써 C 코드에서 불필요한 락킹을 방지할 수 있습니다. 이 함수가 false를 반환하면 락 작업이 필요하지 않습니다. (Nick Coghlan 기여)

  • 새로운 함수인 PyArg_VaParseTupleAndKeywords()PyArg_ParseTupleAndKeywords() 와 동일하지만, 여러 인자 대신 va_list 를 받습니다. (Greg Chapman 기여)

  • 새로운 메서드 플래그인 METH_COEXIST 은 슬롯에 정의된 함수가 동일한 이름을 가진 PyCFunction 과 공존할 수 있게 합니다. 이는 set.__contains__() 와 같은 메서드의 접근 시간을 절반으로 줄일 수 있습니다. (Raymond Hettinger 제공)

  • 이제 파이썬 코어를 개발하는 사람들을 돕기 위해 인터프리터 자체에 대한 추가 프로파일링 기능을 포함하여 파이썬을 빌드할 수 있습니다. configure 스크립트에 --enable-profiling`을 제공하면 :program:`gprof`로 인터프리터를 프로파일링할 있으며, :option:!–with-tsc` 스위치를 제공하면 Pentium의 Time-Stamp-Counter 레지스터를 사용하여 프로파일링할 수 있습니다. 참고로 --with-tsc 스위치는 명칭이 약간 부적절한데, 해당 기능은 PowerPC 플랫폼에서도 작동하지만 해당 프로세서 아키텍처에서는 해당 레지스터를 “TSC 레지스터”라고 부르지 않기 때문입니다. (Jeremy Hylton 기여)

  • tracebackobject 타입이 PyTracebackObject 로 이름이 변경되었습니다.

포트별 변경 사항

  • Windows 포트가 이제 버전 6뿐만 아니라 MSVC++ 7.1에서도 빌드됩니다. (Martin von Löwis 기여)

Python 2.4로 이식

이 섹션은 코드 변경이 필요할 수 있는 이전에 설명된 변경 사항을 나열합니다:

  • 왼쪽 시프트 및 너무 큰 16진수/8진수 상수가 더 이상 FutureWarning 을 발생시키지 않으며, 32 또는 64비트로 제한된 값 대신 long 정수를 반환합니다.

  • 정수 연산이 더 이상 OverflowWarning`을 발생시키지 않습니다. :exc:!OverflowWarning` 경고는 파이썬 2.5에서 사라질 예정입니다.

  • zip() 내장 함수와 itertools.izip() 은 인자 없이 호출될 경우 TypeError 예외를 발생시키는 대신 빈 리스트를 반환합니다.

  • datetime 모듈에서 제공하는 datedatetime 인스턴스를 더 이상 비교할 수 없습니다. 서로 다른 클래스의 두 인스턴스는 이제 항상 같지 않은 것으로 간주되며, 상대 비교(<, >)는 TypeError 를 발생시킵니다.

  • dircache.listdir() 이 이제 빈 리스트를 반환하는 대신 예외를 호출자에게 전달합니다.

  • LexicalHandler.startDTD 이 public 및 system ID를 잘못된 순서로 수신하던 문제가 수정되었습니다. 이전의 잘못된 순서에 의존하던 애플리케이션은 수정이 필요합니다.

  • fcntl.ioctl() 에서 mutate 인자가 생략되었고 관련이 있는 경우 이제 경고를 표시합니다.

  • tarfile 모듈이 이제 기본적으로 GNU 형식의 tar 파일을 생성합니다.

  • 모듈을 임포트하는 중에 오류가 발생해도 이제 sys.modules 에 부분적으로 초기화된 모듈 객체가 남지 않습니다.

  • None is now a constant; code that binds a new value to the name None is now a syntax error.

  • signal.signal() 함수는 이제 특정 부적절한 값에 대해 RuntimeError 예외를 발생시킵니다. 이전에는 이러한 오류가 무시되었습니다. 예를 들어, 더 이상 SIGKILL 시그널에 핸들러를 설정할 수 없습니다.

감사의 글

저자는 이 문서의 여러 초안에 대해 제안, 수정 및 도움을 준 다음 분들께 감사를 표합니다: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.

분실물 보관소