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 클래스를 서브클래스화하려는 경우 유용할 수 있습니다. 현재 이 모듈을 지원 중단할 계획은 없습니다.
더 보기
- 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'
템플릿 문자열을 작성할 때 닫는 괄호 뒤에 i 나 s 를 빠뜨리기 쉽습니다. 템플릿이 파이썬 모듈 내에 있다면 코드를 실행해 “Unsupported format character” ValueError 를 확인하고 문제를 해결하면 되므로 큰 문제가 되지 않습니다. 그러나 Mailman과 같이 숙련되지 않은 사용자가 템플릿 문자열이나 번역을 수정하는 애플리케이션을 생각해 보십시오. 이러한 사용자들에게 포맷 문자열의 구문을 설명하기는 복잡하며, 그들이 실수했을 때 유용한 피드백을 제공하기도 어렵습니다.
PEP 292는 치환을 나타내기 위해 $ 를 사용하는 Template 클래스를 string 모듈에 추가합니다:
>>> 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> 인자가 참인 경우, args 는 os.system() 과 동일하게 해석을 위해 셸로 전달되는 문자열일 수 있습니다.)
stdin, stdout, 그리고 stderr 은 서브 프로세스의 입력, 출력 및 에러 스트림을 지정합니다. 파일 객체나 파일 디스크립터를 제공할 수도 있고, subprocess.PIPE 상수를 사용하여 서브 프로세스와 부모 프로세스 사이에 파이프를 생성할 수도 있습니다.
생성자에는 다음과 같은 유용한 옵션들이 있습니다:
close_fds 는 서브 프로세스를 실행하기 전에 모든 파일 디스크립터를 닫도록 요청합니다.
cwd 는 서브 프로세스가 실행될 작업 디렉터리를 지정합니다 (기본값은 부모의 작업 디렉터리로 설정됩니다).
env 는 환경 변수를 정의하는 딕셔너리입니다.
preexec_fn 은 자식 프로세스가 시작되기 전에 호출되는 함수입니다.
universal_newlines 는 Python의 universal newlines 기능을 사용하여 자식의 입출력을 엽니다.
Popen 인스턴스를 생성한 후, 서브 프로세스가 종료될 때까지 중단하려면 wait() 메서드를 호출하고, 중단 없이 종료 여부를 확인하려면 poll`을 호출하며, 서브 프로세스의 표준 입력에 문자열 *data*를 보내려면 ``communicate(data)``를 호출할 수 있습니다. ``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.01은1 + 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 타입¶
Python 표준 라이브러리에 새로운 모듈인 decimal 이 추가되었습니다. 이 모듈은 Decimal 과 Context 라는 두 개의 클래스를 포함합니다. Decimal 인스턴스는 숫자를 표현하며, Context 인스턴스는 정밀도 및 기본 반올림 모드와 같은 다양한 설정을 묶어서 관리하는 데 사용됩니다.
Decimal 인스턴스는 일반적인 Python 정수나 FP 수와 마찬가지로 불변(immutable)입니다. 한 번 생성되면 해당 인스턴스가 나타내는 값을 변경할 수 없습니다. 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을 나타내는 FP 숫자가 정확히 1.1을 나타내는 십진수로 변환되어야 할까요, 아니면 도입된 모든 부정확성을 포함한 상태로 변환되어야 할까요? 결정은 이 문제를 회피하고 해당 변환을 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 숫자는 math 및 cmath 모듈과 함께 사용할 수 있지만, 연산이 수행되기 전에 즉시 부동 소수점 숫자로 변환되어 정밀도와 정확도가 손실될 가능성이 있음을 유의하십시오. 또한 결과로 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은 반올림 모드를 지정합니다.decimal모듈은 다양한 가능성에 대한 상수를 가지고 있습니다:ROUND_DOWN,ROUND_CEILING,ROUND_HALF_EVEN및 기타 여러 옵션들.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: 로케일 독립적인 부동 소수점/문자열 변환¶
The locale 모듈은 Python 소프트웨어가 특정 국가나 언어에 맞춰 로컬화된 다양한 변환 및 표시 관례를 선택할 수 있게 합니다. 그러나, Python 구현의 다양한 함수들이 숫자 로케일이 '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 Hetinger가 기여함.)문자열은 또한
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 Hettinger가 기여했습니다.)그 자리에 있는
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을 발생시키지 않습니다.OverflowWarning경고는 Python 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가 해결함.)Noneis now a constant; code that binds a new value to the nameNoneis now a syntax error. (Contributed by Raymond Hettinger.)
최적화들`¶
리스트 및 튜플 슬라이싱을 위한 내부 루프가 최적화되어 약 3분의 1 더 빠르게 실행됩니다. 딕셔너리를 위한 내부 루프도 최적화되어
keys(),values(),items(),iterkeys(),itervalues(), 및iteritems()의 성능이 향상되었습니다. (Raymond Hetlinger가 기여함.)리스트를 늘리고 줄이는 메커니즘이 속도와 공간 효율을 위해 최적화되었습니다. 리스트에서 요소 추가(Append) 및 제거(Pop)가 더 효율적인 코드 경로와 빈번하지 않은 하위 시스템
realloc()사용 덕분에 더 빠르게 작동합니다. 리스트 컴프리헨션 또한 혜택을 받습니다.list.extend()또한 최적화되어 기본 리스트를 확장하기 전에 인자를 임시 리스트로 변환하지 않습니다. (Raymond Hetlinger가 기여함.)list(),tuple(),map(),filter(), 그리고zip()이__len__()메서드를 제공하는 비시퀀스 인자(non-sequence arguments)에 대해 훨씬 더 빠르게 작동합니다. (Raymond Hettinger 기여)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과 같은 다른 Python 구현체에는 적용되지 않으므로 이를 신뢰해서는 안 됩니다. 많은 수의 문자열을 효율적으로 이어 붙이고자 할 때는 여전히 문자열의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.
UTF-8 및 UTF-16 코덱이 이제 부분적인 입력을 더 잘 처리합니다. 이전에는
StreamReader클래스가 더 많은 데이터를 읽으려고 시도하여 스트림에서 디코딩을 재개하는 것이 불가능했습니다. 이제read()메서드는 가능한 만큼의 데이터를 반환하며, 이후의 호출은 이전 단계에서 중단된 부분부터 디코딩을 재개합니다. (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
Queue및threading모듈을 포함한 여러 모듈이 성능 향상을 위해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 이전의 Python 버전에 대한 지원이 중단되었습니다. 패키지의 3.0 버전은email.FeedParser모듈에서 사용할 수 있는 MIME 메시지용 새로운 증분 파서(incremental parser)를 사용합니다. 이 새 파서는 메시지 전체를 메모리에 로드할 필요가 없으며, 메시지 형식이 잘못되었을 때 예외를 발생시키지 않고 대신 메시지의defect속성에 문제를 기록합니다. (Anthony Baxter, BarryZ Warsaw, Thomas Wouters 등이 개발)heapq모듈이 C로 전환되었습니다. 그 결과 속도가 10배 향상되어 대량의 데이터를 처리하는 데 적합해졌습니다. 또한, 이 모듈에는 전체 정렬의 비용 없이 데이터 세트에서 가장 큰 또는 작은 N개의 값을 찾기 위해 힙을 사용하는 두 가지 새로운 함수인nlargest()와nsmallest()가 추가되었습니다. (Raymond Hettinger 기여)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()는 이터레이터가 반환하는 값의 복사본을 유지해야 하며, 최악의 경우 모든 값을 유지해야 할 수도 있습니다. 따라서 긴 입력 스트림에서 선행(leading) 이터레이터가 후행(trailing) 이터레이터보다 훨씬 앞서 진행될 수 있는 경우에는 주의해서 사용해야 합니다. 데이터 간격이 크다면 대신list()를 사용하는 것이 좋습니다. 두 이터레이터가 서로 밀접하게 추적하는 경우,tee()가 이상적입니다. 가능한 활용 사례로는 북마크(bookmarking), 윈도잉(windowing), 또는 미리보기(lookahead) 이터레이터 등이 있습니다. (Raymond Hettinger 기여)locale모듈에 특정 인코딩을 지정하는bind_textdomain_codeset()및 선택한 인코딩으로 메시지를 반환하는l*gettext()함수군과 같은 여러 기능이 추가되었습니다. (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
rfc822module in some future Python release in favor of theemailpackage. To this end, theemail.Utils.formatdatefunction has been changed to make it usable as a replacement forrfc822.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 Hettinger 기여.)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시그널에 핸들러를 설정할 수 없습니다. 이전 Python 버전에서는 이를 조용히 수락했으나, 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)
다른 스레드는
number및url속성에 대해 자신만의 값을 할당하고 가져올 수 있습니다.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모듈이 제거되었습니다.
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_CLEAR은 obj 의 참조 횟수를 줄이고 obj 를 null 포인터로 설정합니다. (Jim Fulton 기여)새로운 함수인
PyTuple_Pack(N, obj1, obj2, ..., objN)은 가변 길이의 파이썬 객체 인자 목록으로부터 튜플을 생성합니다. (Raymond Hettinger 기여)새로운 함수인
PyDict_Contains(d, k)는 검색 과정에서 발생하는 예외를 마스킹하지 않으면서도 빠른 딕셔너리 조회를 구현합니다. (Raymond Hetinger 기여)Py_IS_NAN(X) 매크로는 float 또는 double 인자 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을 발생시키지 않습니다.OverflowWarning경고는 Python 2.5에서 사라집니다.zip()내장 함수와itertools.izip()이 인자 없이 호출될 때 이제TypeError예외를 발생시키는 대신 빈 리스트를 반환합니다.datetime모듈에서 제공하는date와datetime인스턴스를 더 이상 비교할 수 없습니다. 이제 서로 다른 클래스의 두 인스턴스는 항상 같지 않은 것으로 간주되며, 상대 비교(<,>) 시TypeError가 발생합니다.dircache.listdir()이 이제 빈 리스트를 반환하는 대신 예외를 호출자에게 전달합니다.LexicalHandler.startDTD()가 public 및 system ID를 잘못된 순서로 수신하던 문제가 수정되었습니다. 잘못된 순서에 의존하는 애플리케이션은 수정이 필요합니다.fcntl.ioctl()에서 mutate 인자가 생략되었고 관련이 있는 경우 이제 경고를 표시합니다.tarfile모듈이 이제 기본적으로 GNU 형식의 tar 파일을 생성합니다.모듈을 임포트하는 중에 오류가 발생해도 이제
sys.modules에 부분적으로 초기화된 모듈 객체가 남지 않습니다.Noneis now a constant; code that binds a new value to the nameNoneis now a syntax error.signals.signal()함수가 이제 특정 부적절한 값에 대해RuntimeError예외를 발생시킵니다. 이전에는 이러한 오류들이 무시되었습니다. 예를 들어, 더 이상SIGKILL시그널에 핸들러를 설정할 수 없습니다.
감사의 글¶
저자는 이 문서의 여러 초안에 대해 제안, 수정 및 도움을 준 다음 분들께 감사를 표합니다: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.