파이썬 2.3의 새로운 기능¶
- 저자:
A.M. Kuchling
이 기사는 Python 2.3의 새로운 기능에 대해 설명합니다. Python 2.3은 2003년 7월 29일에 배포되었습니다.
Python 2.3의 주요 내용은 2.2에서 추가된 몇 가지 기능들을 다듬고, 핵심 언어에 여러 작지만 유용한 개선 사항들을 추가하며, 표준 라이브러리를 확장하는 것입니다. 이전 버전에서 소개된 새로운 객체 모델은 18개월간의 버그 수정 작업과 스타일 클래스의 성능을 향상시킨 최적화 노력 덕분에 많은 이점을 얻었습니다. sum() 및 enumerate() 와 같은 몇 가지 새로운 내장 함수가 추가되었습니다. 또한, in 연산자는 이제 부분 문자열 검색에 사용될 수 있습니다 (예: "ab" in "abc" 는 True 를 반환합니다).
여러 새로운 라이브러리 기능에는 Boolean, set, heap, 그리고 날짜/시간 데이터형 등이 포함되며, ZIP 형식 아카이브의 모듈 가져오기 기능, 오랫동안 기다려 온 Python 카탈로그를 위한 메타데이터 지원, 업데이트된 IDLE 버전, 메시지 로깅, 텍스트 래핑, CSV 파일 구문 분석, 명령줄 옵션 처리, 그리고 BerkeleyDB 데이터베이스 사용을 위한 모듈 등이 있습니다… 새로운 및 향상된 모듈 목록은 방대합니다.
This article doesn’t attempt to provide a complete specification of the new features, but instead provides a convenient overview. For full details, you should refer to the documentation for Python 2.3, such as the Python Library Reference and the Python Reference Manual. If you want to understand the complete implementation and design rationale, refer to the PEP for a particular new feature.
PEP 218: 표준 집합 데이터 유형¶
새로운 sets 모듈은 집합 데이터 유형의 구현을 담고 있습니다. Set 클래스는 멤버를 추가하고 제거할 수 있는 가변 집합용입니다. 반면, ImmutableSet 클래스는 수정될 수 없는 집합용이므로, ImmutableSet 인스턴스를 딕셔너리 키로 사용할 수 있습니다. 집합은 딕셔너리 위에 구축되므로, 집합 내부의 요소들은 반드시 해시 가능해야 합니다.
다음은 간단한 예입니다:
>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>
The union and intersection of sets can be computed with the union() and
intersection() methods; an alternative notation uses the bitwise operators
& and |. Mutable sets also have in-place versions of these methods,
union_update() and intersection_update().
>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2 # 대체 표기법
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2 # 대체 표기법
Set([])
>>> S1.union_update(S2)
>>> S1
Set([1, 2, 3, 4, 5, 6])
두 집합의 대칭 차집합을 계산하는 것도 가능합니다. 이것은 합집합에 속하지만 교집합에는 포함되지 않는 모든 원소들의 집합입니다. 다른 방식으로는, 대칭 차집합이 정확히 한쪽에만 존재하는 모든 요소를 포함하고 있다는 것입니다. 마찬가지로 대체 표기법 (^)과 다소 보기 좋지 않은 이름의 제자리 버전인 :meth:`~set.symmetric_difference_update`가 존재합니다.
>>> S1 = sets.Set([1,2,3,4])
>>> S2 = sets.Set([3,4,5,6])
>>> S1.symmetric_difference(S2)
Set([1, 2, 5, 6])
>>> S1 ^ S2
Set([1, 2, 5, 6])
>>>
또한, 한 집합이 다른 집합의 부분집합 또는 상위집합인지 확인하기 위한 issubset() 및 issuperset() 메서드가 있습니다:
>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([2,3])
>>> S2.issubset(S1)
True
>>> S1.issubset(S2)
False
>>> S1.issuperset(S2)
True
>>>
더 보기
- PEP 218 - 내장 집합 객체 유형 추가
PEP 작성: Greg V. Wilson. 구현: Greg V. Wilson, Alex Martelli, GvR.
PEP 255: 간단한 제너레이터¶
파이썬 2.2에서 제너레이터는 선택적 기능으로 추가되었으며, from __future__ import generators 지시문을 통해 활성화해야 했습니다. 2.3 버전부터는 제너레이터가 특별히 활성화될 필요 없이 항상 기본적으로 존재하며, 이는 :keyword:`yield`가 항상 키워드임을 의미합니다. 이 섹션의 나머지는 “Python 2.2에서 새로운 기능” 문서에 있는 제너레이터 설명의 복사본이므로, Python 2.2가 출시되었을 때 읽으셨다면 이 섹션의 나머지 부분은 건너뛰셔도 좋습니다.
파이썬이나 C에서 함수 호출 방식에 대해 잘 알고 계실 것입니다. 함수를 호출하면 지역 변수가 생성되는 비공개 이름 공간(private namespace)이 생깁니다. 함수가 return 문에 도달하면 지역 변수들이 파괴되고, 결과 값은 호출자에게 반환됩니다. 같은 함수를 나중에 다시 호출하면 새로운 지역 변수 집합을 받게 됩니다. 하지만 만약 지역 변수가 함수를 빠져나갈 때 사라지지 않았다면 어떨까요? 중단했던 곳부터 나중에 함수를 재개할 수 있다면 좋을까요? 이것이 바로 제너레이터가 제공하는 기능입니다; 이들은 재개 가능한 함수로 생각할 수 있습니다.
다음은 제너레이터 함수의 가장 간단한 예입니다:
def generate_ints(N):
for i in range(N):
yield i
새로운 키워드인 yield`가 제너레이터를 위해 도입되었습니다. :keyword:!yield` 문을 포함하는 모든 함수는 제너레이터 함수이며, 이는 파이썬의 바이트코드 컴파일러에 의해 감지되어 특별하게 컴파일됩니다.
제너레이터 함수를 호출하면 단일 값을 반환하지 않습니다; 대신 이터레이터 프로토콜을 지원하는 제너레이터 객체를 반환합니다. yield 문이 실행되면, 제너레이터는 i``의 값(값)을 출력하는데 이는 :keyword:`return` 문과 유사합니다. :keyword:`!yield`와 :keyword:`!return` 문의 가장 큰 차이점은 :keyword:`!yield`에 도달하면 제너레이터의 실행 상태가 일시 중지되고 지역 변수가 보존된다는 것입니다. 제너레이터의 ``.next() 메서드가 다음에 호출되면, 함수는 yield 문 바로 다음부터 이어서 실행됩니다. (복잡한 이유로 인해, yield 문 자체는 try… finally 문의 try 블록 내부에서는 허용되지 않습니다; :keyword:`!yield`와 예외 간의 상호 작용에 대한 전체 설명은 :pep:`255`를 참조하십시오.)
다음은 generate_ints() 제너레이터 사용 예입니다:
>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
File "stdin", line 1, in ?
File "stdin", line 2, in generate_ints
StopIteration
여러분은 똑같이 for i in generate_ints(5) 또는 a,b,c = generate_ints(3) 라고 작성할 수 있습니다.
제너레이터 함수 내부에서, return 문은 값 없이 사용될 수 있으며, 값의 순서 끝을 알립니다; 그 이후로는 제너레이터가 더 이상 값을 반환할 수 없습니다. return 5 와 같이 값을 가지는 return 는 제너레이터 함수 내부에서 구문 오류입니다. 제너레이터 결과의 끝은 또한 StopIteration 을 수동으로 발생시키거나, 실행 흐름이 함수의 바닥으로 떨어지게 하여 나타낼 수도 있습니다.
직접 클래스를 작성하고 제너레이터의 모든 지역 변수를 인스턴스 변수로 저장하여 제너레이터의 효과를 수동으로 구현할 수 있습니다. 예를 들어, 정수 리스트를 반환하는 것은 self.count 를 0으로 설정하고 next() 메서드에서 self.count 를 증가시켜 반환함으로써 수행될 수 있습니다. 하지만, 다소 복잡한 제너레이터의 경우 해당 클래스를 작성하는 것이 훨씬 더 지저분할 것입니다. Lib/test_/test_generators.py 파일에는 더 흥미로운 여러 예제가 포함되어 있습니다. 이 중 가장 간단한 것은 제너레이터를 사용하여 트리를 중위 순회하는 것을 재귀적으로 구현합니다.
# 트리에서 리프 노드를 중위(in-order)로 생성하는 재귀적 제너레이터입니다.
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
`:file:`Lib/test/test_generators.py`의 다른 두 가지 예제는 N-여왕 문제($N$개의 여왕을 $N times N$ 체스판에 배치하여 어떤 여왕도 서로 위협하지 않게 하는 문제)와 기사의 여행(기사가 $N times N$ 체스판의 모든 칸을 두 번 방문하지 않고 지나가는 경로를 찾는 문제)의 해답을 제공합니다.
제너레이터의 아이디어는 다른 프로그래밍 언어들, 특히 Icon(https://www2.cs.arizona.edu/icon/)에서 왔으며, 이곳에서는 제너레이터의 개념이 핵심입니다. Icon에서는 모든 표현식과 함수 호출이 제너레이터처럼 동작합니다. https://www2.cs.arizona.edu/icon/docs/ipd266.htm에 있는 “Icon 프로그래밍 언어 개요” 예제는 이게 어떻게 생겼는지 감을 잡게 해줍니다:
sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)
Icon에서는 find() 함수가 하위 문자열 “or”를 찾는 인덱스를 반환합니다: 3, 23, 33. The if 문에서 i 는 처음에 값 3을 할당받지만, 3은 5보다 작기 때문에 비교에 실패하고 Icon은 두 번째 값으로 23을 다시 시도합니다. 23은 5보다 크므로 이번에는 비교가 성공하고 코드는 화면에 값 23이 출력됩니다.
Python은 제너레이터 개념을 핵심으로 채택하는 데 있어서 Icon만큼 나아가진 못했습니다. 제너레이터는 핵심 Python 언어의 일부로 간주되지만, 학습하거나 사용해야 하는 것은 의무 사항이 아니며, 만약 해결하지 못하는 문제가 있다면 무시해도 좋습니다. Icon과 비교했을 때 Python 인터페이스의 독특한 기능 중 하나는 제너레이터의 상태가 다른 함수로 전달되거나 데이터 구조에 저장될 수 있는 구체적인 객체(반복자)로 표현된다는 것입니다.
더 보기
- PEP 255 - 단순 제너레이터
작성자: Neil Schemenauer, Tim Peters, Magnus Lie Hetland. 구현은 주로 Neil Schemenauer와 Tim Peters가 담당했으며, Python Labs 크루의 다른 수정 사항들이 추가되었습니다.
PEP 263: 소스 코드 인코딩¶
Python 소스 파일은 이제 다른 문자 집합 인코딩으로 선언될 수 있습니다. 인코딩은 소스 파일의 첫 번째 또는 두 번째 줄에 특별히 포맷된 주석을 포함하여 선언됩니다. 예를 들어, UTF-8 파일은 다음과 같이 선언할 수 있습니다:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
이러한 인코딩 선언이 없으면 기본 인코딩으로 7비트 ASCII가 사용됩니다. 인코딩 선언 없이 문자열 리터럴에 8비트 문자를 포함하는 모듈을 실행하거나 임포트하면 Python 2.3에서는 :exc:`DeprecationWarning`가 발생하고, 2.4 버전에서는 구문 오류가 발생합니다.
인코딩 선언은 유니코드 문자열 리터럴에만 영향을 미치며, 이들은 지정된 인코딩을 사용하여 유니코드로 변환됩니다. Python 식별자는 여전히 ASCII 문자로 제한되므로, 일반적인 영숫자 문자 외의 문자를 사용하는 변수 이름은 가질 수 없습니다.
더 보기
- PEP 263 - 파이썬 소스 코드 인코딩 정의
작성자: Marc-André Lemburg와 Martin von Löwis; 구현: Suzuki Hisao 및 Martin von Löwis.
PEP 273: ZIP 아카이브에서 모듈 임포트¶
새로운 zipimport 모듈은 ZIP 형식 아카이브에서 모듈을 임포트하는 지원 기능을 추가합니다. 이 모듈을 명시적으로 임포트할 필요는 없으며, ZIP 아카이브의 파일 이름이 sys.path 에 추가되면 자동으로 임포트됩니다. 예를 들면 다음과 같습니다:
amk@nyman:~/src/python$ unzip -l /tmp/example.zip
Archive: /tmp/example.zip
Length Date Time Name
-------- ---- ---- ----
8467 11-26-02 22:30 jwzthreading.py
-------- -------
8467 1 file
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip') # .zip 파일을 path 앞에 추가합니다
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'
>>>
sys.path 에 있는 항목은 이제 ZIP 아카이브의 파일 이름일 수 있습니다. ZIP 아카이브는 모든 종류의 파일을 포함할 수 있지만, *.py, *.pyc, 또는 *.pyo 으로 이름 붙여진 파일만 임포트할 수 있습니다. 만약 아카이브에 오직 *.py 파일만 포함되어 있다면, Python은 해당 *.pyc 파일을 추가하여 아카이브를 수정하려고 시도하지 않습니다. 즉, ZIP 아카이브에 *.pyc 파일이 포함되어 있지 않으면 임포트 속도가 다소 느릴 수 있습니다.
아카이브 내의 특정 경로를 지정하여 하위 디렉터리에서만 임포트하도록 할 수도 있습니다. 예를 들어, 경로 /tmp/example.zip/lib/`는 아카이브 내의 :file:`lib/ 하위 디렉터리에서만 임포트합니다.
PEP 277: Windows NT용 유니코드 파일 이름 지원¶
Windows NT, 2000 및 XP에서는 시스템이 파일 이름을 유니코드 문자열로 저장합니다. 전통적으로 Python은 파일 이름을 바이트 문자열로 나타냈는데, 이는 일부 파일 이름에 대한 접근을 불가능하게 만들어 부적절합니다.
Python은 이제 파일 이름을 기대하는 모든 함수들(특히 open() 내장 함수)에서 임의의 유니코드 문자열 사용을 허용합니다. os.listdir`에 유니코드 문자열이 전달되면, Python은 현재 유니코드 문자열 목록을 반환합니다. 또한, 새로운 함수인 :func:()!os.getcwdu`는 현재 디렉터리를 유니코드 문자열로 반환합니다.
바이트 문자열은 여전히 파일 이름으로 작동하며, Windows에서 Python은 이를 mbcs 인코딩을 사용하여 투명하게 유니코드로 변환합니다.
다른 시스템에서도 파일 이름으로 유니코드 문자열을 허용하지만, 시스템에 전달하기 전에 바이트 문자열로 변환하며, 이로 인해 :exc:`UnicodeError`가 발생할 수 있습니다. 애플리케이션은 :const:`os.path.supports_unicode_filenames`를 확인하여 임의의 유니코드 문자열이 파일 이름으로 지원되는지 테스트할 수 있습니다.
MacOS 환경에서는 이제 :func:`os.listdir`가 유니코드 파일 이름을 반환할 수 있습니다.
더 보기
- PEP 277 - Windows NT용 유니코드 파일 이름 지원
Neil Hodgson이 작성하고, Neil Hodgson, Martin von Löwis 및 Mark Hammond가 구현했습니다.
PEP 278: 유니버설 줄 넘김 지원¶
현재 사용되는 세 가지 주요 운영체제는 Microsoft Windows, Apple의 Macintosh OS, 그리고 다양한 Unix 파생판입니다. 크로스 플랫폼 작업에서 발생하는 사소한 성가심은 이 세 플랫폼 모두 텍스트 파일의 줄 끝을 표시하는 데 다른 문자를 사용하는 것입니다. 유닉스는 라인 피드(ASCII 문자 10)를 사용하고, MacOS는 캐리지 리턴(ASCII 문자 13)을 사용하며, Windows는 캐리지 리턴과 뉴라인이 결합된 두 문자열 시퀀스를 사용합니다.
Python의 파일 객체는 이제 Python이 실행되는 플랫폼에 따르는 종식 줄 표현 방식 외의 다른 방식을 지원할 수 있습니다. 모드 'U' 또는 'rU' 로 파일을 열면, universal newlines 모드로 읽기 전용으로 파일을 엽니다. 세 가지 모두의 줄바꿈 규칙은 read() 및 readline() 과 같은 다양한 파일 메서드가 반환하는 문자열에서 '\n' 으로 변환됩니다.
유니버설 줄 넘김 지원은 모듈을 임포트할 때와 execfile() 함수로 파일을 실행할 때도 사용됩니다. 이는 Python 모듈이 줄 끝을 변환할 필요 없이 세 운영체제 간에 공유될 수 있음을 의미합니다.
이 기능은 Python의 configure 스크립트를 실행할 때 --without-universal-newlines 옵션을 지정함으로써 컴파일 시 비활성화할 수 있습니다.
더 보기
- PEP 278 - 유니버설 줄 넘김 지원
Jack Jansen이 작성하고 구현했습니다.
PEP 279: enumerate()¶
새로운 내장 함수인 enumerate`는 특정 반복문을 좀 더 명확하게 만들어 줄 것입니다. ``enumerate(thing)``은 *thing*이 이터레이터 또는 시퀀스 중 하나일 때, `(0, thing[0])(), (1, thing[1]), (2, thing[2]) 및 그 외와 같은 값을 반환하는 이터레이터를 반환합니다.
리스트의 모든 요소를 변경하기 위한 일반적인 관용구는 다음과 같습니다:
for i in range(len(L)):
item = L[i]
# ... compute some result based on item ...
L[i] = result
:func:`enumerate`를 사용하면 다음과 같이 다시 작성할 수 있습니다:
for i, item in enumerate(L):
# ... compute some result based on item ...
L[i] = result
더 보기
- PEP 279 - 내장 함수 enumerate()
Raymond D. Hettinger가 작성하고 구현했습니다.
PEP 282: 로깅 패키지¶
:mod:`logging`을 위한 표준 로깅 패키지가 Python 2.3에 추가되었습니다. 이 패키지는 강력하고 유연한 메커니즘을 제공하여 로그 출력을 생성하며, 이는 다양한 방식으로 필터링되고 처리될 수 있습니다. 표준 형식으로 작성된 구성 파일을 사용하여 프로그램의 로깅 동작을 제어할 수 있습니다. Python에는 표준 오류나 파일 또는 소켓에 로그 레코드를 기록하거나, 시스템 로그로 보내거나, 심지어 특정 주소로 이메일로 전송하는 핸들러가 포함되어 있으며, 물론 자신만의 핸들러 클래스를 작성하는 것도 가능합니다.
Logger 는 주요 클래스입니다. 대부분의 애플리케이션 코드는 하나 이상의 Logger 객체를 다루게 되며, 각각은 애플리케이션의 특정 하위 시스템에서 사용됩니다. 각 Logger 는 이름으로 식별되며, 이 이름들은 . 를 구성 요소 구분자로 사용하여 계층 구조로 정리됩니다. 예를 들어, server, server.auth 및 server.network 라는 이름을 가진 Logger 인스턴스를 가질 수 있습니다. 후자의 두 인스턴스는 계층 구조에서 server 아래에 위치합니다. 이는 server 의 상세 수준을 높이거나 server 메시지를 다른 핸들러로 직접 전송할 경우, 이 변경 사항이 server.auth 와 server.network 에 기록된 레코드에도 적용된다는 의미입니다. 모든 다른 로거들의 부모인 최상위 Logger 도 있습니다.
간단한 사용의 경우, logging 패키지는 항상 루트 로그(root log)를 사용하는 몇 가지 편리한 함수를 포함하고 있습니다:
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
다음의 출력을 만듭니다:
WARNING:root:경고: 설정 파일 server.conf를 찾을 수 없습니다<br>ERROR:root:오류가 발생했습니다<br>CRITICAL:root:심각한 오류 -- 종료합니다
기본 구성에서는 정보 및 디버깅 메시지가 억제되며 출력은 표준 오류로 전송됩니다. 루트 로거에서 setLevel() 메서드를 호출하여 정보 및 디버깅 메시지 표시를 활성화할 수 있습니다.
warning() 호출의 문자열 포매팅 연산자 사용에 주목하십시오; 모든 로깅 메시지 함수는 (msg, arg1, arg2, ...) 인수를 받으며 msg % (arg1, arg2, ...) 로부터 결과 문자열을 기록합니다.
최근 트레이스백을 기록하는 exception() 함수도 있습니다. 다른 함수들도 키워드 인자 exc_info 를 True로 지정하면 마찬가지로 트레이스백을 기록합니다:
def f():
try: 1/0
except: logging.exception('Problem recorded')
f()
다음의 출력을 만듭니다:
ERROR:root:Problem recorded
Traceback (most recent call last):
File "t.py", line 6, in f
1/0
ZeroDivisionError: integer division or modulo by zero
좀 더 고급 프로그램은 루트 로거가 아닌 로거를 사용하게 됩니다. getLogger(name) 함수는 특정 로그를 가져오는 데 사용되며, 아직 존재하지 않으면 생성합니다. getLogger(None) 는 루트 로거를 반환합니다:
log = logging.getLogger('server')
...
log.info('Listening on port %i', port)
...
log.critical('Disk full')
...
로그 레코드는 일반적으로 계층 구조의 위로 전파되므로, server.auth 에 기록된 메시지는 server 와 root 에서도 볼 수 있지만, Logger 는 이 속성인 propagate 를 False 로 설정하여 이를 방지할 수 있습니다.
logging 패키지에서 사용자 정의할 수 있는 더 많은 클래스를 제공합니다. Logger 인스턴스가 메시지를 기록하도록 지시받으면, 이 인스턴스는 여러 개의 서로 다른 Handler 인스턴스로 전송되는 LogRecord 인스턴스를 생성합니다. 로거와 핸들러는 또한 첨부된 필터 목록을 가질 수 있으며, 각 필터는 LogRecord 인스턴스는 Formatter 클래스에 의해 텍스트로 변환됩니다. 이러한 모든 클래스는 사용자가 특별히 작성한 클래스로 교체될 수 있습니다.
이러한 모든 기능들을 통해 logging 패키지는 가장 복잡한 애플리케이션에게도 충분한 유연성을 제공해야 합니다. 이는 기능에 대한 불완전한 개요일 뿐이므로, 자세한 내용은 패키지 레퍼런스 문서를 참조하십시오. :pep:`282`를 읽는 것도 도움이 될 것입니다.
더 보기
- PEP 282 - 로깅 시스템
작성자는 Vinay Sajip과 Trent Mick이며, 구현자는 Vinay Sajip입니다.
PEP 285: 부울 타입¶
부울 타입은 Python 2.3에 추가되었습니다. __builtin__ 모듈에는 새 상수인 True`와 :const:`False`가 두 개 추가되었습니다. (:const:`True`와 :const:`False 상수는 Python 2.2.1 버전의 내장 기능에 추가되었지만, 2.2.1 버전은 단순히 정수 값 1과 0으로 설정되어 있으며 별도의 타입이 아닙니다.)
이 새 타입에 대한 타입 객체는 bool 이며, 생성자는 모든 Python 값을 받아와서 True 또는 :const:`False`로 변환합니다.
>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True
표준 라이브러리의 대부분의 모듈과 내장 함수들이 부울을 반환하도록 변경되었습니다.
>>> obj = []
>>> hasattr(obj, 'append')
True
>>> isinstance(obj, list)
True
>>> isinstance(obj, tuple)
False
Python에서 부울이 추가된 주된 목표는 코드를 더 명확하게 만드는 것이었습니다. 예를 들어, 함수를 읽다가 return 1 문을 만나면, 이 `1`이 부울 진리값인지, 인덱스 값인지, 아니면 다른 수량을 곱하는 계수인지 궁금할 수 있습니다. 그러나 만약 해당 문이 `return True`라면, 반환 값의 의미가 매우 분명합니다.
Python에서 부울 타입은 엄격한 타입 검사를 위해 추가되지 않았습니다. Pascal과 같은 매우 엄격한 언어에서도 여전히 부울에 대해 산술 연산을 수행하는 것을 방지할 것이며, if 문에서의 표현식이 항상 부울 결과를 평가하도록 요구할 것입니다. Python은 그렇게 엄격하지 않으며, PEP 285 에서 명시했듯이 그럴 일도 없을 것입니다. 이것은 여전히 목록이나 튜플 또는 임의 객체로 평가되는 표현식을 if 문에 사용할 수 있다는 의미입니다. 부울 타입은 int 클래스의 서브클래스이므로, 부울을 사용한 산술 연산도 작동합니다.
>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75
True`와 :const:`False`를 문장으로 요약하자면: 이들은 정수 값 1과 0을 표기하는 대체적인 방식이며, 유일한 차이점은 :func:`str`과 :func:`repr`가 각각 `’True’`` 및 'False' 문자열을 반환한다는 것입니다.
더 보기
- PEP 285 - bool 타입 추가
GvR이 작성하고 구현했습니다.
PEP 293: 코드 처리 오류 콜백¶
유니코드 문자열을 바이트 문자열로 인코딩할 때, 인코딩할 수 없는 문자를 만날 수 있습니다. 지금까지 Python은 이 오류 처리를 “strict”( UnicodeError 발생), “ignore”(문자 무시), 또는 “replace”(출력 문자열에 물음표 사용)로 지정할 수 있도록 허용했으며, “strict”이 기본 동작입니다. XML 문자 참조나 HTML 개체 참조를 변환된 문자열에 삽입하는 등 대체 처리 방식을 지정하는 것이 바람직할 수 있습니다.
Python은 이제 다양한 처리 전략을 추가하기 위한 유연한 프레임워크를 갖추게 되었습니다. 새 에러 핸들러는 :func:`codecs.register_error`로 추가할 수 있으며, 코덱은 :func:`codecs.lookup_error`로 해당 에러 핸들러에 접근할 수 있습니다. C로 작성된 코덱을 위해 동등한 C API도 추가되었습니다. 이 에러 핸들러는 변환 중인 문자열, 오류가 감지된 문자열 내 위치 및 대상 인코딩과 같은 필요한 상태 정보를 얻습니다. 그러면 핸들러는 예외를 발생시키거나 대체 문자열을 반환할 수 있습니다.
이 프레임워크를 사용하여 두 개의 추가 에러 핸들러가 구현되었습니다: “backslashreplace”는 Python 백슬래시 인용 문법을 사용하여 인코딩할 수 없는 문자를 나타내고, “xmlcharrefreplace”는 XML 문자 참조를 방출합니다.
더 보기
- PEP 293 - 코드 처리 오류 콜백
Walter Dörwald가 작성하고 구현했습니다.
PEP 301: Distutils의 패키지 인덱스 및 메타데이터¶
오래 요청되었던 Python 카탈로그 지원이 2.3에서 처음으로 등장합니다.
카탈로그의 핵심은 새로운 Distutils register 명령어입니다. python setup.py register 를 실행하면 이름, 버전, 유지 관리자, 설명 등 패키지를 설명하는 메타데이터를 수집하여 중앙 카탈로그 서버로 전송합니다. 결과로 생성되는 카탈로그는 https://pypi.org에서 확인할 수 있습니다.
카탈로그를 좀 더 유용하게 만들기 위해, Distutils setup() 함수에 새로운 선택적 classifiers 키워드 인수가 추가되었습니다. 소프트웨어를 분류하는 데 도움이 되는 Trove <http://catb.org/~esr/trove/> 형식의 문자열 목록을 제공할 수 있습니다.
클래스파이어가 포함된 예시 :file:`setup.py`를 보여드리며, 이는 Distutils의 이전 버전과 호환되도록 작성되었습니다:
from distutils import core
kw = {'name': "Quixote",
'version': "0.5.1",
'description': "A highly Pythonic Web application framework",
# ...
}
if (hasattr(core, 'setup_keywords') and
'classifiers' in core.setup_keywords):
kw['classifiers'] = \
['Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Environment :: No Input/Output (Daemon)',
'Intended Audience :: Developers'],
core.setup(**kw)
전체 분류 목록은 python setup.py register --list-classifiers 를 실행하여 얻을 수 있습니다.
더 보기
- PEP 301 - Distutils용 패키지 인덱스와 메타데이터
Richard Jones가 작성하고 구현했습니다.
PEP 302: 새로운 임포트 훅¶
:mod:!ihooks` 모듈이 Python 1.3에 도입된 이래로 사용자 정의 임포트 훅을 작성하는 것이 가능했지만, 아무도 만족하지 못했습니다. 새로운 임포트 훅을 작성하기가 어렵고 복잡합니다. imputil 및 iu 모듈과 같은 여러 대안이 제안되었지만, 어느 것도 큰 수용도를 얻지 못했고, C 코드에서 쉽게 사용할 수 있는 것도 없었습니다.
PEP 302 는 선행 버전, 특히 Gordon McMillan의 iu 모듈로부터 아이디어를 가져왔습니다. sys 모듈에 세 가지 새로운 항목이 추가됩니다:
sys.path_hooks는 호출 가능한 객체의 목록입니다. 대부분은 클래스일 것입니다. 각 호출 가능 객체는 경로를 포함하는 문자열을 받아 이 경로에서 임포트를 처리할 임포터 객체를 반환하거나, 해당 경로를 처리할 수 없는 경우ImportError예외를 발생시킵니다.sys.path_importer_cache는 각 경로의 임포터 객체를 캐싱합니다. 따라서sys.path_hooks는 각 경로에 대해 한 번만 순회하면 됩니다.sys.meta_path는sys.path가 확인되기 전에 순회될 임포터 객체의 목록입니다. 이 목록은 초기에는 비어 있지만, 사용자 코드는 여기에 객체를 추가할 수 있습니다. 이 목록에 추가된 객체에 의해 추가적인 내장 및 프로즌 모듈을 임포트할 수 있습니다.
임포터 객체는 단일 메서드인 find_module(fullname, path=None) 를 가지고 있어야 합니다. fullname 은 string 또는 distutils.core 와 같은 모듈이나 패키지 이름입니다. find_module() 은 단일 메서드인 load_module(fullname) 을 가진 로더 객체를 반환해야 하며, 이 메서드는 해당 모듈 객체를 생성하고 반환합니다.
Python의 새로운 임포트 로직에 대한 의사 코드는 따라서 다음과 같은 형태를 <0xEB><0x9D><0xB1>니다 (약간 단순화되었습니다. 자세한 내용은 PEP 302 참고):
for mp in sys.meta_path:
loader = mp(fullname)
if loader is not None:
<module> = loader.load_module(fullname)
for path in sys.path:
for hook in sys.path_hooks:
try:
importer = hook(path)
except ImportError:
# ImportError이므로 다른 경로 훅을 시도합니다.
pass
else:
loader = importer.find_module(fullname)
<module> = loader.load_module(fullname)
# 찾지 못함!
raise ImportError
더 보기
- PEP 302 - 새로운 임포트 훅
Just van Rossum과 Paul Moore가 작성했으며 Just van Rossum이 구현했습니다.
PEP 305: 쉼표로 구분된 파일¶
쉼표로 구분된 파일은 데이터베이스와 스프레드시트에서 데이터를 내보낼 때 자주 사용되는 형식입니다. Python 2.3는 쉼표로 구분된 파일을 위한 파서를 추가합니다.
쉼표로 구분된 형식은 언뜻 보기에는 속임수로 단순합니다:
Costs,150,200,3.95
줄을 읽고 line.split(',') 를 호출하는 것은 무엇보다 간단할 수 있을까요? 그러나 쉼표를 포함할 수 있는 문자열 데이터를 넣으면 일이 더 복잡해집니다:
"Costs",150,200,3.95,"세금, 배송 및 잡다한 항목 포함"
거대하고 못생긴 정규 표현식으로 이 데이터를 파싱할 수 있지만, 새로운 csv 패키지를 사용하는 것이 훨씬 간단합니다:
import csv
input = open('datafile', 'rb')
reader = csv.reader(input)
for line in reader:
print line
reader() 함수는 다양한 옵션을 받습니다. 필드 구분자는 쉼표로 제한되지 않으며 아무 문자든 변경할 수 있고, 따옴표 및 줄 바꿈 문자도 마찬가지입니다.
다양한 쉼표 구분 파일 방언을 정의하고 등록할 수 있습니다. 현재 Microsoft Excel에서 사용되는 두 가지 방언이 있습니다. 별도의 csv.writer 클래스는 연속된 튜플이나 리스트로부터 쉼표로 구분된 파일을 생성하며, 구분자를 포함하는 문자열에 따옴표를 붙입니다.
더 보기
- PEP 305 - CSV 파일 API
Kevin Altis, Dave Cole, Andrew McNamara, Skip Montanaro, Cliff Wells가 작성하고 구현했습니다.
PEP 307: Pickle 개선 사항¶
pickle 및 cPickle 모듈은 2.3 개발 주기 동안 주목을 받았습니다. 2.2에서는 새로운 스타일의 클래스가 어려움 없이 피클링될 수 있었지만, 매우 간결하게 피클링되지는 않았습니다. :pep:`307`은 새로운 스타일의 클래스가 클래식 클래스의 것보다 세 배나 긴 문자열이 되는 사소한 예시를 인용합니다.
해결책은 새로운 피클 프로토콜을 발명하는 것이었습니다. pickle.dumps() 함수는 오랫동안 텍스트 또는 바이너리 플래그를 지원해 왔습니다. 버전 2.3에서는 이 플래그가 불리언(Boolean)에서 정수형으로 재정의되었습니다: 0은 이전의 텍스트 모드 피클 형식이고, 1은 이전 바이너리 형식이며, 이제 2는 새로운 2.3 전용 형식입니다. 또한, 새로운 상수인 :const:`pickle.HIGHEST_PROTOCOL`를 사용하여 사용 가능한 가장 최신 프로토콜을 선택할 수 있습니다.
언피클링은 더 이상 안전한 작업으로 간주되지 않습니다. 2.2의 pickle`은 unsafe 클래스가 언피클되는 것을 막기 위한 후크(hook)를 제공했습니다 (구체적으로, :attr:!__safe_for_unpickling__` 속성). 하지만 이 코드는 어느 경우에도 감사(audited)되지 않았으며, 따라서 2.3에서 모두 제거되었습니다. 모든 버전의 Python에서 신뢰할 수 없는 데이터를 언피클해서는 안 됩니다.
신규 스타일 클래스의 피클링 오버헤드를 줄이기 위해, 세 가지 특수 메서드인 __getstate__(), __setstate__(), 및 :meth:`~object.__getnewargs__`를 사용하여 간편화된 피클링 사용자 정의 인터페이스가 추가되었습니다. 이러한 메서드의 전체 의미론은 :pep:`307`을 참조하십시오.
피클 데이터를 더욱 압축하는 방법으로, 이제 피클링된 클래스를 식별하기 위해 긴 문자열 대신 정수 코드를 사용할 수 있습니다. Python 소프트웨어 재단은 표준화된 코드 목록을 유지할 것이며, 사적인 사용을 위한 코드 범위도 존재합니다. 현재는 지정된 코드가 없습니다.
더 보기
- PEP 307 - 피클 프로토콜 확장
Guido van Rossum와 Tim Peters에 의해 작성 및 구현됨.
확장 슬라이스¶
Python 1.4부터, 슬라이싱 구문은 선택적인 세 번째 “스텝(step)” 또는 “스트라이드(stride)” 인자를 지원합니다. 예를 들어, 다음 모두는 유효한 Python 구문입니다: L[1:10:2], L[:-1:1], L[::-1]. 이는 세 번째 인자를 광범위하게 사용하는 Numerical Python 개발자들의 요청에 따라 추가되었습니다. 하지만 Python의 기본 리스트, 튜플 및 문자열 시퀀스 타입은 이 기능을 한 번도 지원하지 않아, 사용하려고 하면 :exc:`TypeError`를 발생시켰습니다. Michael Hudson가 이 결함을 수정하는 패치를 기여했습니다.
예를 들어, 이제 짝수 인덱스를 가진 리스트 요소들을 쉽게 추출할 수 있습니다:
>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]
음수 값 역시 같은 리스트의 역순 복사본을 만드는 데 사용됩니다:
>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
이것은 튜플, 배열 및 문자열에도 적용됩니다:
>>> s='abcd'
>>> s[::2]
'ac'
>>> s[::-1]
'dcba'
만약 리스트나 배열과 같은 변경 가능한 시퀀스가 있다면 확장 슬라이스에 대입하거나 삭제할 수 있지만, 확장 슬라이스와 일반 슬라이스 간에는 몇 가지 차이점이 있습니다. 일반 슬라이스에 대한 할당은 시퀀스의 길이를 변경하는 데 사용될 수 있습니다:
>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]
확장 슬라이스는 그렇게 유연하지 않습니다. 확장 슬라이스에 값을 대입할 때, 해당 문장의 오른쪽의 리스트는 대체되는 슬라이스와 동일한 수의 항목을 포함해야 합니다:
>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2
삭제는 더 간단합니다:
>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]
이제 내장 시퀀스의 __getitem__() 메서드에 슬라이스 객체를 전달할 수도 있습니다:
>>> range(10).__getitem__(slice(0, 5, 2))
[0, 2, 4]
또는 서브스크립트에서 슬라이스 객체를 직접 사용할 수 있습니다:
>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]
확장 슬라이싱을 지원하는 시퀀스를 구현하는 것을 간단하게 하기 위해, slice 객체는 이제 indices(length)`라는 메서드를 가지고 있습니다. 이 메서드는 시퀀스의 길이를 받아 `:func:range`에 직접 전달할 수 있는 `(start, stop, step) 튜플을 반환합니다. :meth:`!indices`는 누락된 인덱스 및 범위를 벗어난 인덱스를 일반 슬라이스와 일관되게 처리합니다 (그리고 이 무해한 구문은 혼란스러운 세부 사항들을 숨기고 있습니다!). 이 메서드는 다음과 같은 방식으로 사용하도록 의도되었습니다:
class FakeSeq:
...
def calc_item(self, i):
...
def __getitem__(self, item):
if isinstance(item, slice):
indices = item.indices(len(self))
return FakeSeq([self.calc_item(i) for i in range(*indices)])
else:
return self.calc_item(i)
이 예제에서 여러분은 또한 내장 slice 객체가 이제 슬라이스 타입의 형 객체이며 더 이상 함수가 아님을 알 수 있습니다. 이는 레벨 2.2의 int, str 등도 동일한 변경을 겪었던 것과 일관됩니다.
이외의 언어 변경 사항¶
여기에 Python 2.3이 코어 Python 언어에 적용하는 모든 변경 사항을 안내합니다.
yield문은 이제 항상 키워드가 되었으며, 이 문서의 PEP 255: 간단한 제너레이터 섹션에 설명되어 있습니다.이 문서의 PEP 279: enumerate() 섹션에서 설명된 대로 새로운 내장 함수 :func:`enumerate`가 추가되었습니다.
본 문서의 PEP 285: 부울 타입 섹션에 설명된 대로 두 가지 새로운 상수,
True`와 :const:`False`가 내장 :class:`bool타입과 함께 추가되었습니다.Python의
int()타입 생성자는 문자열이나 부동 소수점 숫자가 정수에 담기에는 너무 클 때 더 이상OverflowError\를 발생시키는 대신 긴 정수(long integer)를 반환합니다. 이는isinstance(int(expression), int)가 거짓이라는 역설적인 결과를 초래할 수 있지만, 실제로는 문제가 없을 가능성이 높아 보입니다.내장 타입이 이제 이 문서의 확장 슬라이스\ 섹션에 설명된 확장 슬라이싱 구문을 지원합니다.
새로운 내장 함수,
sum(iterable, start=0)가 이터러블 객체 내의 숫자 항목들을 합산하고 그 합계를 반환합니다.sum()는 숫자를만 허용하므로 문자열을 연결하는 데 사용할 수 없습니다. (Alex Martelli 기여)list.insert(pos, value)는 이전에는 pos 가 음수일 때 리스트 맨 앞에 value 를 삽입하는 데 사용되었습니다. 이제 이 동작은 슬라이스 인덱싱과 일관되도록 변경되어, pos 가 -1인 경우 해당 값은 마지막 요소 앞에 삽입되며, 그 외의 경우도 마찬가지입니다.리스트 내에서 value 를 검색하고 그 인덱스를 반환하는
list.index(value)에 이제 선택적 인자 start 와 stop 이 추가되어, 검색 범위를 리스트의 일부로 제한할 수 있습니다.딕셔너리가 새로운 메소드,
pop(key[, *default*]),를 갖고 이제 이 메소드는 key 에 해당하는 값을 반환하고 해당 키/값 쌍을 딕셔너리에서 제거합니다. 요청된 키가 딕셔너리에 없으면, 지정되었을 경우 default 가 반환되고 그렇지 않으면KeyError\가 발생합니다.>>> d = {1:2} >>> d {1: 2} >>> d.pop(4) Traceback (most recent call last): File "stdin", line 1, in ? KeyError: 4 >>> d.pop(1) 2 >>> d.pop(1) Traceback (most recent call last): File "stdin", line 1, in ? KeyError: 'pop(): dictionary is empty' >>> d {} >>>
또한, 제공된 이터레이터 iterable 에서 가져온 키를 사용하고 모든 값을 value 로 설정하는 딕셔너리를 생성하는 새로운 클래스 메소드,
dict.fromkeys(iterable, value),가 있습니다. 기본값은None입니다.(Raymond Hettinger 기여 패치)
또한,
dict()생성자는 작은 딕셔너리 생성을 간소화하기 위해 키워드 인자를 받습니다:>>> dict(red=1, blue=2, green=3, black=4) {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
(Just van Rossum 기여)
assert문은 더 이상__debug__플래그를 확인하지 않으므로,__debug__에 할당하여 어설션을 비활성화할 수 없습니다.-O스위치로 Python을 실행해도 어설션을 실행하지 않는 코드는 계속 생성됩니다.대부분의 타입 객체는 이제 호출 가능하므로, 이를 사용하여 함수, 클래스 및 모듈과 같은 새 객체를 만들 수 있습니다. (이는
new모듈이 향후 Python 버전에서 폐기될 수 있음을 의미하는데, 왜냐하면 이제types모듈에 있는 타입 객체를 사용할 수 있기 때문입니다.) 예를 들어, 다음 코드를 사용하여 새 모듈 객체를 만들 수 있습니다:>>> import types >>> m = types.ModuleType('abc','docstring') >>> m <module 'abc' (built-in)> >>> m.__doc__ 'docstring'
A new warning,
PendingDeprecationWarningwas added to indicate features which are in the process of being deprecated. The warning will not be printed by default. To check for use of features that will be deprecated in the future, supply-Walways::PendingDeprecationWarning::on the command line or usewarnings.filterwarnings().문자열 기반 예외(예:
raise "Error occurred")의 폐기 과정이 시작되었습니다. 문자열을 발생시키면 이제 :exc:`PendingDeprecationWarning`가 트리거됩니다.변수 이름으로
None를 사용하는 것은 이제SyntaxWarning경고를 발생시킵니다. 향후 버전의 Python에서는,None이 최종적으로 키워드가 될 수도 있습니다.Python 2.1에서 도입된 파일 객체의
xreadlines()메소드는 파일이 이제 자체 이터레이터처럼 작동하기 때문에 더 이상 필요하지 않습니다.xreadlines`는 원래 파일의 모든 라인을 반복하는 더 빠른 방법으로 도입되었지만, 이제 단순히 ``for line in file_obj``를 작성할 수 있습니다. 파일 객체는 또한 파일에 사용되는 인코딩을 제공하는 새 읽기 전용 :attr:()!encoding` 속성을 가지고 있으며, 파일에 쓰이는 유니코드 문자열은 주어진 인코딩을 사용하여 자동으로 바이트로 변환됩니다.신규 스타일 클래스에서 사용되는 메서드 결정 순서가 변경되었습니다. 매우 복잡한 상속 계층 구조를 가진 경우에만 차이점을 눈치챌 수 있습니다. 클래식 클래스는 이 변경 사항의 영향을 받지 않습니다. Python 2.2는 원래 클래스의 조상들을 위상 정렬로 사용했지만, 2.3부터는 논문 “A Monotonic Superclass Linearization for Dylan” <https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.3910>에 설명된 C3 알고리즘을 사용합니다. 이 변경의 동기를 이해하려면, Michele Simionato이 작성한 글 :ref:`python_2.3_mro`를 읽거나, https://mail.python.org/pipermail/python-dev/2002-October/029035.html 메시지부터 시작하는 python-dev 스레드를 읽으세요. Samuele Pedroni가 문제점을 처음 지적했으며 C3 알고리즘을 코딩하여 수정 사항도 구현했습니다.
Python은 N개의 바이트 코드를 실행한 후 스레드 간 전환을 통해 멀티스레드 프로그램을 실행합니다. 기본값인 N이 10에서 100 바이트 코드로 증가하여, 전환 오버헤드가 줄어듦으로써 싱글 스레드 애플리케이션의 속도가 향상되었습니다. 일부 멀티스레드 애플리케이션은 응답 시간이 느릴 수 있지만,
sys.setcheckinterval(N)을 사용하여 제한을 더 낮은 숫자로 설정하여 쉽게 수정할 수 있습니다. 이 제한은 새로운sys.getcheckinterval()함수로 검색할 수 있습니다.사소하지만 파급력이 큰 변화는 Python에 포함된 모듈에 의해 정의된 확장 유형 이름이 이제 해당 모듈과 타입 이름 앞에
'.'를 포함한다는 점입니다. 예를 들어, Python 2.2에서 소켓을 생성하고 그__class__를 출력하면 다음과 같은 출력을 얻게 될 것입니다:>>> s = socket.socket() >>> s.__class__ <type 'socket'>
2.3 버전에서는 다음과 같이 얻게 됩니다:
>>> s.__class__ <type '_socket.socket'>
이전 버전과 새로운 스타일 클래스 간의 알려진 비호환성 중 하나가 제거되었습니다: 이제 신규 스타일 클래스의
__name__및__bases__어트리뷰트에 값을 할당할 수 있습니다. 인스턴스의__class__어트리뷰트에 할당하는 것과 관련된 사항과 유사하게, :attr:`!__bases__`에 무엇을 할당할 수 있는지에 일부 제한 사항이 있습니다.
문자열 변경 사항¶
in연산자는 이제 문자열에 대해 다르게 작동합니다. 이전에는 X 와 Y 가 문자열일 때X in Y를 평가하면 X 는 단일 문자만 될 수 있었습니다. 이 점이 변경되었습니다. X 는 어느 길이의 문자열이 될 수 있으며, X 가 Y 의 부분 문자열인 경우X in Y는True를 반환합니다. 만약 X 가 빈 문자열이라면 결과는 항상True입니다:>>> 'ab' in 'abcd' True >>> 'ad' in 'abcd' False >>> '' in 'abcd' True
이것이 부분 문자열이 어디서 시작하는지 알려주지 않는다는 점에 유의하십시오. 해당 정보가 필요하다면
find()문자열 메서드를 사용하세요.strip(),lstrip(), 및rstrip()문자열 메서드는 이제 제거할 문자를 지정하는 선택적 인수를 가집니다. 기본값은 여전히 모든 공백 문자 제거입니다:>>> ' abc '.strip() 'abc' >>> '><><abc<><><>'.strip('<>') 'abc' >>> '><><abc<><><>\n'.strip('<>') 'abc<><><>\n' >>> u'\u4000\u4001abc\u4000'.strip(u'\u4000') u'\u4001abc' >>>
(Simon Brunning이 제안하고 Walter Dörwald가 구현했습니다.)
startswith()및endswith()문자열 메서드는 이제 start*와 *end 매개변수에 음수를 허용합니다.또 다른 새로운 문자열 메서드는
string모듈의 원래 함수인``%`()연산자가 여전히 :meth:`~str.zfill`보다 더 유연하고 강력하다는 점에 유의하십시오:>>> '45'.zfill(4) '0045' >>> '12345'.zfill(4) '12345' >>> 'goofy'.zfill(6) '0goofy'
(Walter Dörwald 기여.)
새로운 타입 객체,
basestring`이 추가되었습니다. 8비트 문자열과 유니코드 문자열 둘 다 이 타입으로부터 상속받으므로, ``isinstance(obj, basestring)``는 두 종류의 문자열 모두에 대해 :const:`True`를 반환할 것입니다. 완전히 추상적인 타입이기 때문에 :class:!basestring` 인스턴스를 생성할 수 없습니다.인턴 된 문자열은 더 이상 불멸이 아니며, 내부 인턴 문자열 딕셔너리로부터 유일한 참조가 있을 때 이제 일반적인 방식으로 가비지 수집됩니다. (Oren Tirosh 구현.)
최적화들`¶
신규 스타일 클래스 인스턴스의 생성 속도가 훨씬 빨라졌습니다. 이제는 클래식 클래스보다 빠릅니다!
리스트 객체의
sort()메서드가 Tim Peters에 의해 광범위하게 재작성되었으며, 구현이 훨씬 빨라졌습니다.큰 정수 곱셈은 이제 카라츠바 곱셈을 구현함으로써 훨씬 빨라졌습니다. 이것은 초등학교 방식의 곱셈 알고리즘이 요구하는 O (n)²보다 더 잘 확장되는 알고리즘입니다. (Christopher A. Craig가 원본 패치를 했으며, Tim Peters에 의해 대폭 수정되었습니다.)
SET_LINENOopcode는 사라졌습니다. 이는 컴파일러의 특성에 따라 약간의 속도 향상을 제공할 수 있습니다. 더 자세한 설명은 섹션 :ref:`23section-other`를 참조하십시오. (Michael Hudson이 제거함.)xrange()객체는 이제 자체 이터레이터를 가지게 되어,for i in xrange(n)가for i in range(n)보다 약간 더 빨라졌습니다. (Raymond Hettinger 패치.)성능 개선을 위해 다양한 핫스팟에 여러 작은 재배치가 이루어졌습니다. 예를 들어, 함수 인라인화나 일부 코드 제거와 같습니다. (주로 GvR이 구현했지만, 많은 사람들이 단일 변경 사항을 기여했습니다.)
2.3 최적화의 전반적인 결과는 Python 2.3가 Python 2.2보다 pystone 벤치마크를 약 25% 더 빠르게 실행한다는 것입니다.
새롭고, 개선되고, 사용 중단된 모듈¶
예상대로 Python 표준 라이브러리에 여러 가지 향상 및 버그 수정 사항들이 적용되었습니다. 여기에는 모듈 이름에 따라 알파벳순으로 정렬된 가장 주목할 만한 변경 사항들의 일부 목록이 있습니다. 더 완전한 변경 목록은 소스 트리 내의 :file:`Misc/NEWS` 파일을 참조하거나 모든 세부 정보를 보려면 CVS 로그를 확인하십시오.
array모듈은 이제'u'형식 문자를 사용하여 유니코드 문자 배열을 지원합니다. 또한, 배열은 다른 배열의 내용을 추가하기 위해 추가 := 인자 할당 연산자를 사용하는 것과, 배열을 반복하기 위해 == 할당 연산자를 사용하는 것도 지원하게 되었습니다. (Jason Orendorff가 기여함.)bsddb모듈은 버크리DB 라이브러리의 트랜잭션 기능을 위한 보다 완전한 인터페이스를 제공하는 PyBSDDB 버전 4.1.6으로 교체되었습니다.이 모듈의 이전 버전은
bsddb185`로 이름이 변경되었으며 더 이상 자동으로 빌드되지 않습니다. 활성화하려면 :file:`Modules/Setup`을 수정해야 합니다. 새로운 :mod:!bsddb` 패키지는 구버전 모듈과 호환되도록 의도되었으므로, 비호환성을 발견하면 버그를 제출하시기 바랍니다. Python 2.3으로 업그레이드할 때, 새 인터프리터가 기반이 되는 BerkeleyDB 라이브러리의 새 버전으로 컴파일된 경우, 데이터베이스 파일을 새로운 버전으로 변환해야 할 가능성이 매우 높습니다. 이 작업은 배포판의 :file:`Tools/scripts` 디렉토리에서 찾을 수 있는 새로운 스크립트인 :file:`db2pickle.py` 및 :file:`pickle2db.py`를 사용하면 비교적 쉽게 수행할 수 있습니다. 이미 PyBSDDB 패키지를 사용하고 이를bsddb3`로 가져오는 경우, ``import`구문을 수정하여 :mod:`!bsddb`로 가져와야 합니다.새로운
bz2모듈은 bz2 데이터 압축 라이브러리에 대한 인터페이스입니다. bz2 압축 데이터는 일반적으로 해당zlib-압축 데이터보다 작습니다. (Gustavo Niemeyer가 기여함.)새로운
datetime모듈에 표준 날짜/시간 유형 세트가 추가되었습니다. 더 자세한 내용은 다음 섹션을 참조하십시오.Distutils
Extension클래스는 이제 확장 기능이 의존하는 추가 소스 파일 목록을 지정하기 위해 depends 라는 추가 생성자 인자를 지원합니다. 이를 통해 종속성 파일 중 하나라도 수정되면 Distutils가 모듈을 다시 컴파일하도록 할 수 있습니다. 예를 들어,sampmodule.c가 헤더 파일sample.h를 포함하는 경우 다음과 같이Extension객체를 생성할 수 있습니다:ext = Extension("samp", sources=["sampmodule.c"], depends=["sample.h"])
:file:`sample.h`을 수정하면 모듈이 다시 컴파일되게 됩니다. (Jeremy Hylton가 기여함.)
Distutils의 기타 사소한 변경 사항: 이제
CC,CFLAGS,CPP,LDFLAGS, 및CPPFLAGS환경 변수를 확인하여 Python 구성 설정을 재정의하며 사용합니다 (Robert Weber 기여).이전에는
doctest모듈이 공개 메서드와 함수만 대상으로 테스트 케이스를 검색했지만, 이제는 비공개 요소도 검사합니다.DocTestSuite()함수는 일련의doctest테스트로부터unittest.TestSuite객체를 생성합니다.새로운
gc.get_referents(object)함수는 object 가 참조하는 모든 객체의 목록을 반환합니다.getopt모듈에 기존getopt()함수와 동일한 인수를 지원하지만 GNU 스타일 스캐닝 모드를 사용하는 새로운 함수인 :func:`~getopt.gnu_getopt`이 추가되었습니다. 기존의 :func:`~getopt.getopt`은 비옵션 인자가 발견되면 옵션 처리를 중지하지만, GNU 스타일 모드에서는 처리가 계속되므로 옵션과 인자를 혼합할 수 있습니다. 예를 들어:>>> getopt.getopt(['-f', 'filename', 'output', '-v'], 'f:v') ([('-f', 'filename')], ['output', '-v']) >>> getopt.gnu_getopt(['-f', 'filename', 'output', '-v'], 'f:v') ([('-f', 'filename'), ('-v', '')], ['output'])
(Peter Åstrand 기여.)
grp,pwd, 및resource모듈은 이제 향상된 튜플을 반환합니다:>>> import grp >>> g = grp.getgrnam('amk') >>> g.gr_name, g.gr_gid ('amk', 500)
gzip모듈은 이제 2 GiB를 초과하는 파일도 처리할 수 있습니다.새로운
heapq모듈에는 힙 큐 알고리즘의 구현이 포함되어 있습니다. 힙은 k*인 모든 인덱스에 대해 ``heap[k] <= heap[2*k+1]`` 및 ``heap[k] <= heap[2*k+2]``를 유지하여 항목을 부분적으로 정렬된 순서로 보관하는 배열과 유사한 자료 구조입니다. 이를 통해 가장 작은 항목을 빠르게 제거할 수 있으며, 힙 속성을 유지하면서 새 항목을 삽입하는 것은 *O*(log *n) 시간이 소요됩니다. (우선순위 큐 자료 구조에 대한 더 많은 정보는 https://xlinux.nist.gov/dads//HTML/priorityque.html를 참조하십시오.)heapq모듈은 다른 변경 가능한 Python 시퀀스 타입 위에 힙 속성을 유지하면서 항목을 추가하고 제거하기 위해heappop()함수를 제공합니다. 여기 Python 리스트를 사용하는 예제가 있습니다:>>> import heapq >>> heap = [] >>> for item in [3, 7, 5, 11, 1]: ... heapq.heappush(heap, item) ... >>> heap [1, 3, 5, 11, 7] >>> heapq.heappop(heap) 1 >>> heapq.heappop(heap) 3 >>> heap [5, 7, 11]
(Kevin O’Connor 기여.)
IDLE 통합 개발 환경은 IDLEfork 프로젝트(https://idlefork.sourceforge.net)의 코드를 사용하여 업데이트되었습니다. 가장 주목할 만한 특징은 이제 개발 중인 코드가 서브프로세스에서 실행된다는 점이며, 이는 수동
reload()작업이 더 이상 필요하지 않음을 의미합니다. IDLE의 핵심 코드는idlelib패키지로 표준 라이브러리에 통합되었습니다.imaplib모듈은 이제 SSL을 통한 IMAP을 지원합니다. (Piers Lauder 및 Tino Lange 기여.)itertools는 ML 및 Haskell 언어에서 제공되는 다양한 함수에서 영감을 받은, 이터레이터와 함께 사용하기에 유용한 여러 함수를 포함하고 있습니다. 예를 들어,itertools.ifilter(predicate, iterator)는 함수predicate()가True를 반환하는 이터레이터의 모든 요소를 반환하며,itertools.repeat(obj, N)은obj를 N 번 반환합니다. 모듈에는 다른 여러 함수들이 있으며, 자세한 내용은 패키지 참조 문서를 참조하십시오. (Raymond Hettinger 기여.)math모듈의 두 가지 새로운 함수인degrees(rads)및radians(degs)``는 라디안과 도를 상호 변환합니다. :func:`math.sin` 및 :func:`math.cos`와 같은 :mod:`math` 모듈의 다른 함수들은 항상 라디안으로 측정된 입력 값을 필요로 했습니다. 또한, 옵션 *base* 인수가 :func:`math.log`에 추가되어 ``e``와 ``10이외의 기수를 갖는 로그를 계산하기가 더 쉬워졌습니다. (Raymond Hettinger 기여.)os모듈을 기반으로 하는posix모듈에 여러 새로운 POSIX 함수들 (getpgid(),killpg(),lchown(),loadavg(),major(),makedev(),minor(), 및mknod())이 추가되었습니다. (Gustavo Niemeyer, Geert Jansen, Denis S. Otkidach 기여.)os모듈에서*stat()계열의 함수는 이제 타임스탬프에 초 단위의 분수까지 보고할 수 있습니다. 이러한 시간 스탬프는 :func:`time.time`이 반환하는 값과 유사하게 float으로 표현됩니다.테스트 중에 일부 애플리케이션은 타임스탬프가 float일 경우 작동이 중단되는 것이 발견되었습니다. 호환성을 위해
2에서 처음 도입된 기능)를 사용할 때도 타임스탬프는 여전히 정수로 표현되지만, float 반환 값을 활성화하려면 :func:!os.stat_float_times`를 호출해야 합니다:>>> os.stat("/tmp").st_mtime 1034791200 >>> os.stat_float_times(True) >>> os.stat("/tmp").st_mtime 1034791200.6335014
Python 2.4에서는 기본값이 항상 float을 반환하도록 변경됩니다.
애플리케이션 개발자는 모든 라이브러리가 부동소수점 타임스탬프를 접했을 때 제대로 작동하는 경우 또는 튜플 API를 사용하는 경우에만 이 기능을 활성화해야 합니다. 사용되는 경우, 개별 사용 사례 단위가 아닌 애플리케이션 수준에서 활성화되어야 합니다.
optparse모듈에는 옵션 값을 특정 Python 타입으로 변환할 수 있고 사용법 메시지를 자동으로 생성하는 새로운 명령줄 인수 파서가 포함되어 있습니다. 더 자세한 내용은 다음 섹션을 참조하십시오.오래되고 문서화되지 않은
linuxaudiodev모듈은 사용 중단되었으며, :mod:`!ossaudiodev`라는 새 버전이 추가되었습니다. 이 모듈 이름은 OSS 사운드 드라이버가 리눅스 외의 플랫폼에서도 사용될 수 있기 때문에 변경되었고, 인터페이스도 여러 방식으로 정리되고 최신화되었습니다. (Greg Ward와 Nicholas FitzRoy-Dale 기여.)새로운
platform모듈에는 실행 중인 플랫폼의 다양한 속성을 확인하려는 여러 함수가 포함되어 있습니다. 아키텍처, CPU 타입, Windows OS 버전 및 심지어 리눅스 배포판 버전 등을 가져오는 함수들이 있습니다. (Marc-André Lemburg 기여.)The parser objects provided by the
pyexpatmodule can now optionally buffer character data, resulting in fewer calls to your character data handler and therefore faster performance. Setting the parser object’sbuffer_textattribute toTruewill enable buffering.random모듈에sample(population, k)함수가 추가되었습니다. population 은 모집단의 요소를 포함하는 시퀀스 또는xrange객체이며,sample()은 선택된 요소를 교체하지 않고 모집단에서 k 개의 요소를 선택합니다. k 는len(population)까지의 어떤 값이든 될 수 있습니다. 예시:>>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn'] >>> random.sample(days, 3) # 3개 요소 선택 ['St', 'Sn', 'Th'] >>> random.sample(days, 7) # 7개 요소 선택 ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn'] >>> random.sample(days, 7) # 다시 7개 요소 선택 ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th'] >>> random.sample(days, 8) # 8개는 선택할 수 없음 Traceback (most recent call last): File "<stdin>", line 1, in ? File "random.py", line 414, in sample raise ValueError, "sample larger than population" ValueError: sample larger than population >>> random.sample(xrange(1,10000,2), 10) # 10000 미만의 홀수 10개 선택 [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
random모듈은 이제 C로 구현된 새로운 알고리즘인 Mersenne Twister를 사용합니다. 이전 알고리즘보다 빠르고 더 광범위하게 연구되었습니다.(모든 변경 사항은 Raymond Hettinger 기여.)
readline모듈에는 또한 새로운 많은 함수들이 추가되었습니다:get_history_item(),get_current_history_length(), 및redisplay():rexec및Bastion모듈은 사용 중단됨으로 선언되었으며, 이들을 가져오려고 시도하면RuntimeError`가 발생합니다. New-style 클래스는 :mod:!rexec`이 제공하는 제한된 실행 환경에서 벗어날 수 있는 새로운 방법을 제공하며, 아무도 이를 수정하거나 시간을 들여 바꿀 관심이 없습니다. :mod:`!rexec`을 사용하는 애플리케이션이 있다면 다른 것을 사용하도록 다시 작성하십시오.(Python 2.2 또는 2.1에 머무르는 것은 해당 버전의
rexec모듈에 알려진 버그가 있기 때문에 애플리케이션을 더 안전하게 만들지 않습니다. 반복합니다: 만약 :mod:`!rexec`를 사용하고 있다면, 즉시 사용하는 것을 중단하십시오.)rotor모듈은 암호화에 사용되는 알고리즘이 안전하지 않다고 여겨져 더 이상 사용되지 않습니다. 암호화가 필요하면 별도로 사용할 수 있는 여러 AES Python 모듈 중 하나를 사용하십시오.shutil모듈에 파일이나 디렉터리를 새 위치로 재귀적으로 옮기는 move(src, dest) 함수가 추가되었습니다.더 발전된 POSIX 시그널 처리에 대한 지원이 :mod:`signal`에 추가되었으나, 플랫폼 전반에서 안정적으로 작동하는 것이 불가능함이 입증되어 다시 제거되었습니다.
socket모듈은 이제 시간제한(timeout)을 지원합니다.settimeout(t)메서드를 소켓 객체에 호출하여 t 초의 시간제한을 설정할 수 있습니다. 이후 t 초보다 오래 걸리는 모든 소켓 작업은 중단되고socket.timeout예외를 발생시킵니다.원래의 시간제한 구현은 Tim O’Malley가 개발했습니다. Michael Gilfix는 이를 Python
socket모듈에 통합했고, 긴 검토 과정을 거쳤습니다. 코드가 체크인된 후 Guido van Rossum이 일부 부분을 재작성했습니다. (이는 협업적인 개발 과정의 좋은 예입니다.)Windows에서
socket모듈은 이제 Secure Sockets Layer (SSL) 지원을 포함합니다.C
PYTHON_API_VERSION매크로의 값은 이제sys.api_version으로 Python 레벨에 노출됩니다. 현재 예외는 새로운sys.exc_clear()함수를 호출하여 지울 수 있습니다.tarfile모듈은 tar 형식의 아카이브 파일에서 읽고 쓰는 것을 허용합니다. (Lars Gustäbel 기여.)새로운
textwrap모듈에는 텍스트 단락을 포함하는 문자열을 래핑하기 위한 함수들이 들어 있습니다. wrap(text, width) 함수는 주어진 문자열을 최대 선택된 너비의 줄로 분할하여 리스트를 반환합니다. fill(text, width) 함수는 주어진 문자열을 최대 선택된 너비가 넘지 않도록 재형식화한 단일 문자열을 반환합니다. (짐작하시는 대로, :func:`~textwrap.fill`은 :func:`~textwrap.wrap`을 기반으로 구축되었습니다. 예를 들어:>>> import textwrap >>> paragraph = "Not a whit, we defy augury: ... more text ..." >>> textwrap.wrap(paragraph, 60) ["Not a whit, we defy augury: there's a special providence in", "the fall of a sparrow. If it be now, 'tis not to come; if it", ...] >>> print textwrap.fill(paragraph, 35) Not a whit, we defy augury: there's a special providence in the fall of a sparrow. If it be now, 'tis not to come; if it be not to come, it will be now; if it be not now, yet it will come: the readiness is all. >>>
이 모듈에는 텍스트 래핑 전략을 실제로 구현하는
TextWrapper클래스도 포함되어 있습니다.TextWrapper클래스와wrap()및fill()함수는 서식을 미세 조정하기 위해 여러 추가 키워드 인수를 지원합니다. (Greg Ward 기여.) 자세한 내용은 모듈 문서를 참조하십시오.thread및threading모듈에는 스레드가 지원되지 않는 플랫폼의 경우thread모듈 인터페이스에 아무것도 하지 않는 구현을 제공하는 보조 모듈인dummy_thread`와 :mod:!dummy_threading`가 있습니다. 의도는 다음 코드를 맨 위에 배치함으로써 스레드 인식 모듈(스레드를 실행에 의존하지 않는)의 복잡성을 단순화하는 것입니다:try: import threading as _threading except ImportError: import dummy_threading as _threading
이 예제에서는
_threading`을 사용하여 해당 모듈이 반드시 실제 :mod:`threading모듈은 아님을 명확히 했습니다. 코드는 스레드가 지원되든 안되든 상관없이_threading`의 함수를 호출하고 클래스를 사용할 수 있어, :keyword:`if문을 피하게 하고 코드를 조금 더 명확하게 만듭니다. 이 모듈이 마법처럼 스레드 없이 멀티스레드 코드를 실행하지는 않습니다. 다른 스레드가 반환되기를 기다리거나 무언가를 하기 위해 대기하는 코드는 계속 멈춰 있게 됩니다.time모듈의strptime()함수는 플랫폼 C 라이브러리의strptime()구현을 사용하고, 다른 플랫폼에서 때때로 이상한 버그를 가지고 있기 때문에 오랫동안 골칫거리였습니다. Brett Cannon이 순수 Python으로 작성된 이식 가능한 구현을 기여하여 모든 플랫폼에서 동일하게 작동해야 합니다.새로운
timeit모듈은 파이썬 코드 스니펫이 실행되는 데 걸리는 시간을 측정하는 데 도움을 줍니다.timeit.py파일은 명령줄에서 직접 실행할 수 있으며, 모듈의Timer클래스를 임포트하여 바로 사용할 수도 있습니다. 여기는 8비트 문자열을 유니코드로 변환하는 것이 빈 유니코드 문자열을 추가하는 것과unicode()함수를 사용하는 것 중 어느 것이 더 빠른지 알아내는 짧은 예제입니다:import timeit timer1 = timeit.Timer('unicode("abc")') timer2 = timeit.Timer('"abc" + u""') # 세 번의 반복 실행 print timer1.repeat(repeat=3, number=100000) print timer2.repeat(repeat=3, number=100000) # 제 노트북에서 출력되는 값: # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869] # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
Tix모듈은 Tix 패키지의 현재 버전에 대한 다양한 버그 수정 및 업데이트를 받았습니다.Tkinter모듈은 이제 스레드가 활성화된 버전의 Tcl에서 작동합니다. Tcl의 스레딩 모델은 위젯이 생성된 스레드에서만 접근되어야 함을 요구하며, 다른 스레드로부터의 액세스는 Tcl 패닉을 유발할 수 있습니다. 특정 Tcl 인터페이스의 경우,Tkinter`는 이제 위젯에 다른 스레드에서 접근될 때 명령을 중계(marshalling)하고 올바른 스레드로 전달한 다음 결과를 기다림으로써 이를 자동으로 방지합니다. 다른 인터페이스는 자동으로 처리할 수 없지만, :mod:!Tkinter`는 이러한 액세스 시 예외를 발생시켜 적어도 문제에 대해 알 수 있도록 합니다. 자세한 설명은 여기(https://mail.python.org/pipermail/python-dev/2002-December/031107.html)를 참조하십시오. (Martin von Löwis가 구현하였습니다.)_tkinter`를 통해 Tcl 메서드를 호출할 때 더 이상 문자열만 반환하지 않습니다. 대신, Tcl이 다른 객체를 반환하는 경우, 해당 객체는 파이썬 동등물이 있는 경우 파이썬 동등물로 변환되거나, 파이썬 동등물이 없는 경우 :class:!_tkinter.Tcl_Obj` 객체로 감싸집니다. 이 동작은tkapp객체의wantobjects()메서드를 통해 제어할 수 있습니다.Tkinter모듈을 통해 :mod:`!_tkinter`를 사용할 때(대부분의 Tkinter 애플리케이션이 그렇듯이) 이 기능은 항상 활성화됩니다. Tkinter는 가능한 경우 문자열 결과를 파이썬 타입으로 항상 변환하기 때문에, 호환성 문제는 발생하지 않아야 합니다.호환성 문제가 발견된 경우, 첫 번째
tkapp객체를 생성하기 전에Tkinter모듈의wantobjects변수를 False로 설정하여 이전 동작을 복원할 수 있습니다.import Tkinter Tkinter.wantobjects = 0
이 변경으로 인해 발생한 모든 장애는 버그로 보고해야 합니다.
UserDict모듈에는 최소 매핑 인터페이스를 이미 가진 클래스의 모든 딕셔너리 메서드를 정의하는 새로운DictMixin클래스가 있습니다. 이는 shelve 모듈의 클래스와 같이 딕셔너리를 대체해야 하는 클래스를 작성하는 것을 크게 단순화합니다.혼합(mix-in)을 슈퍼클래스로 추가하면, 해당 클래스가
__getitem__(),__setitem__(),__delitem__(), 및 :meth:`!keys`를 정의하는 한 항상 전체 딕셔너리 인터페이스를 제공합니다. 예시:>>> import UserDict >>> class SeqDict(UserDict.DictMixin): ... """리스트로 구현된 딕셔너리 비슷한 객체입니다.""" ... def __init__(self): ... self.keylist = [] ... self.valuelist = [] ... def __getitem__(self, key): ... try: ... i = self.keylist.index(key) ... except ValueError: ... raise KeyError ... return self.valuelist[i] ... def __setitem__(self, key, value): ... try: ... i = self.keylist.index(key) ... self.valuelist[i] = value ... except ValueError: ... self.keylist.append(key) ... self.valuelist.append(value) ... def __delitem__(self, key): ... try: ... i = self.keylist.index(key) ... except ValueError: ... raise KeyError ... self.keylist.pop(i) ... self.valuelist.pop(i) ... def keys(self): ... return list(self.keylist) ... >>> s = SeqDict() >>> dir(s) # 다른 딕셔너리 메서드가 구현되었는지 확인합니다 ['__cmp__', '__contains__', '__delitem__', '__doc__', '__getitem__', '__init__', '__iter__', '__len__', '__module__', '__repr__', '__setitem__', 'clear', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keylist', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'valuelist', 'values']
(Raymond Hettinger 작성.)
xml.dom.minidom`의 DOM 구현을 사용하면 이제 :meth:`~xml.dom.minidom.Node.toxml및toprettyxml()메서드에 선택적 인코딩 인수를 제공하여 특정 인코딩으로 XML 출력을 생성할 수 있습니다.xmlrpclib모듈은 이제 Python의None과 같은 nil 데이터 값을 처리하기 위한 XML-RPC 확장을 지원합니다. Nil 값은 항상 XML-RPC 응답을 비마셜링할 때 지원됩니다.None을 포함하는 요청을 생성하려면,Marshaller인스턴스를 만들 때 allow_none 매개변수에 true 값을 공급해야 합니다.새로운
DocXMLRPCServer모듈은 자체 설명형의 XML-RPC 서버를 작성할 수 있게 합니다. 데모 모드(프로그램으로)로 실행하여 동작을 확인해 보세요. 웹 브라우저에서 RPC 서버를 가리키면 pydoc 스타일의 문서가 생성되고, xmlrpclib에서 서버를 가리키면 실제 메서드를 호출할 수 있습니다. (Brian Quinlan 기여.)국제화된 도메인 이름(RFC 3454, 3490, 3491 및 3492)에 대한 지원이 추가되었습니다. “idna” 인코딩을 사용하여 유니코드 도메인 이름과 해당 이름의 ASCII 호환 인코딩(ACE) 간 변환할 수 있습니다.
>{}>{}> u"www.Alliancefrançaise.nu".encode("idna") 'www.xn--alliancefranaise-npb.nu'
socket모듈도 유니코드 호스트 이름을 ACE 버전으로 투명하게 변환하여 C 라이브러리에 전달하도록 확장되었습니다.httplib및ftplib`와 같이 호스트 이름과 관련된 모듈은 또한 유니코드 호스트 이름을 지원합니다. 또한, :mod:!httplib`는 도메인 이름의 ACE 버전을 사용하여 HTTPHost헤더도 전송합니다.urllib`은 URL의 ``path`부분이 ASCII만인 경우 비 ASCII 호스트 이름을 가진 유니코드 URL을 지원합니다.이 변경 사항을 구현하기 위해,
stringprep모듈,mkstringprep도구, 그리고punycode인코딩이 추가되었습니다.
날짜/시간 유형¶
타임스탬프를 표현하기에 적합한 날짜 및 시간 유형이 datetime 모듈로 추가되었습니다. 이 유형들은 다양한 달력을 지원하거나 많은 고급 기능을 제공하지 않으며, 시간을 나타내는 기본적인 부분에 중점을 두었습니다.
세 가지 주요 유형은 다음과 같습니다: 일, 월, 년을 나타내는 date, 시간, 분, 초로 구성된 time, 그리고 datetime. 또한 두 시점 간의 차이를 나타내는 timedelta 클래스가 있으며, 시간대 논리는 추상 클래스인 :class:`~datetime.tzinfo`를 상속받은 클래스에 의해 구현됩니다.
time 인스턴스를 적절한 생성자에 키워드 인수를 공급하는 방식(예: datetime.date(year=1972, month=10, day=15))이나 여러 클래스 메서드 중 하나를 사용하여 생성할 수 있습니다. 예를 들어, today() 클래스 메서드는 현재 로컬 날짜를 반환합니다.
생성된 후에는 날짜/시간 클래스의 인스턴트는 모두 불변입니다. 객체에서 형식화된 문자열을 생성하는 데 사용할 수 있는 몇 가지 메서드가 있습니다.
>>> import datetime as dt
>>> now = dt.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime() # date, datetime에서만 사용 가능
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'
replace() 메서드는 date 또는 datetime 인스턴스의 하나 이상의 필드를 수정하여 새 인스턴스를 반환할 수 있게 합니다.
>>> d = dt.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(year=2001, hour=12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>
인스턴스는 비교, 해싱 및 문자열로 변환될 수 있습니다 (결과는 datetime() 인스턴스는 서로 빼거나 timedelta 인스턴스에 더할 수 있습니다. 가장 큰 누락 기능은 문자열을 파싱하여 date 또는 :class:`~datetime.datetime`으로 되돌리는 표준 라이브러리 지원이 없다는 것입니다.
자세한 내용은 모듈의 참조 문서를 참조하십시오. (Tim Peters 기여.)
optparse 모듈¶
getopt 모듈은 명령줄 인수의 간단한 구문 분석을 제공합니다. 새로 추가된 optparse 모듈(원래 이름은 Optik)은 유닉스 규칙을 따르는 더 정교한 명령줄 구문 분석을 제공하며, :option:`!–help`에 대한 출력을 자동으로 생성하고 다양한 옵션에 대해 다른 동작을 수행할 수 있습니다.
:class:`~optparse.OptionParser`의 인스턴스를 생성하여 프로그램의 옵션이 무엇인지 알려주는 것부터 시작합니다:
import sys
from optparse import OptionParser
op = OptionParser()
op.add_option('-i', '--input',
action='store', type='string', dest='input',
help='set input filename')
op.add_option('-l', '--length',
action='store', type='int', dest='length',
help='set maximum length of output')
명령줄 구문 분석은 parse_args() 메서드를 호출하여 수행합니다:
options, args = op.parse_args(sys.argv[1:])
print options
print args
이는 모든 옵션 값을 포함하는 객체와 나머지 인자 문자열 리스트를 반환합니다.
다양한 인자로 스크립트를 호출하면 예상대로 동작합니다. 길이 인수는 자동으로 정수로 변환된다는 점에 유의하세요.
$ ./python opt.py -i data arg1
<Values at 0x400cad4c: {'input': 'data', 'length': None}>
['arg1']
$ ./python opt.py --input=data --length=4
<Values at 0x400cad2c: {'input': 'data', 'length': 4}>
[]
$
도움말 메시지가 자동으로 생성됩니다:
$ ./python opt.py --help
usage: opt.py [options]
options:
-h, --help show this help message and exit
-iINPUT, --input=INPUT
set input filename
-lLENGTH, --length=LENGTH
set maximum length of output
$
더 자세한 내용은 모듈 문서를 참조하십시오.
Optik은 Greg Ward가 작성했으며 Getopt SIG의 독자들의 도움을 받았습니다.
Pymalloc: 전문 객체 할당자¶
Vladimir Marangozov가 작성한 특수 객체 할당자인 Pymalloc은 Python 2.1에 추가된 기능입니다. Pymalloc은 시스템 malloc() 보다 빠르고, 파이썬 프로그램의 일반적인 할당 패턴에 대해 메모리 오버헤드가 적도록 설계되었습니다. 이 할당자는 C의 malloc() 함수를 사용하여 큰 메모리 풀을 가져온 다음, 이 풀들로부터 더 작은 메모리 요청을 충족합니다.
2.1 및 2.2 버전에서는 pymalloc이 실험적인 기능이었으며 기본 활성화되어 있지 않았습니다. configure 스크립트에 옵션인 --with-pymalloc`을 제공하여 명시적으로 활성화해야 했습니다. 2.3 버전부터는 pymalloc이 추가 개선 사항들을 거쳐 이제 기본으로 활성화됩니다. 비활성화하려면 :option:!–without-pymalloc`을 공급해야 합니다.
이 변경은 Python으로 작성된 코드에는 투명합니다. 그러나 pymalloc은 C 확장에서 버그를 노출할 수 있습니다. C 확장 모듈의 저자는 런타임에 일부 잘못된 코드가 코어 덤프를 유발할 수 있으므로, pymalloc을 활성화하여 자신들의 코드를 테스트해야 합니다.
문제를 일으키는 매우 흔한 에러가 하나 있습니다. Python의 C API에는 이전에 단순히 C 라이브러리의 malloc() 및 :c:func:`free`에 대한 별칭이었던 여러 메모리 할당 함수들이 있어, 실수로 일치하지 않는 함수를 호출해도 오류가 눈에 띄지 않았습니다. 객체 할당자가 활성화되면, 이 함수들은 더 이상 :c:func:`malloc`과 :c:func:`free`의 별칭이 아니므로, 메모리를 해제하기 위해 잘못된 함수를 호출하면 코어 덤프(core dump)가 발생할 수 있습니다. 예를 들어, 메모리가 :c:func:`PyObject_Malloc`을 사용하여 할당되었다면, :c:func:`free`가 아닌 :c:func:`PyObject_Free`를使用하여 해제해야 합니다. 일부 필수 모듈이 이 문제에 휘말려 수정되어야 했으며, 의심할 여지 없이 동일한 문제가 있는 서드파티 모듈이 더 많이 있을 것입니다.
이번 변경의 일환으로, 메모리를 할당하기 위한 혼란스러운 여러 인터페이스가 두 가지 API 계열로 통합되었습니다. 한 계열로 할당된 메모리는 다른 계열의 함수로 조작해서는 안 됩니다. 메모리 청크를 할당하는 가족과 Python 객체를 전문적으로 할당하는 또 다른 함수 가족이 있습니다.
구별되지 않은 메모리 청크를 할당하고 해제하려면 “로우 메모리” 계열인
PyMem_Malloc(),PyMem_Realloc(), 및 :c:func:`PyMem_Free`를 사용하십시오.“객체 메모리” 계열은 위에 설명된 pymalloc 기능에 대한 인터페이스이며, “작은” 할당이 많이 발생한다는 데 치우쳐 있습니다:
PyObject_Malloc(),PyObject_Realloc(), 및PyObject_Free().Python 객체를 할당하고 해제하려면 “객체” 계열인
PyObject_New,PyObject_NewVar, 및 :c:func:`PyObject_Del`을 사용하십시오.
Tim Peters의 많은 작업 덕분에, 2.3 버전의 pymalloc은 확장 모듈과 인터프리터 자체 모두에서 메모리 오버라이트 및 이중 해제를 감지하는 디버깅 기능도 제공합니다. 이 지원을 활성화하려면 --with-pydebug 옵션을 사용하여 Python 인터프리터를 디버깅 버전을 컴파일하십시오.
확장 작성자를 돕기 위해, Python 확장 모듈이 1.5.2 이후 버전의 모든 파이썬을 대상으로 컴파일하면서 2.3 인터페이스를 메모리 할당에 사용할 수 있도록 소스 배포판과 함께 Misc/pymemcompat.h 헤더 파일이 배포됩니다. 이 파일을 파이썬 소스에서 복사하여 확장 모듈의 소스와 함께 번들링해야 합니다.
더 보기
- https://hg.python.org/cpython/file/default/Objects/obmalloc.c
pymalloc 구현의 전체 세부 정보는 파이썬 소스 코드 내
Objects/obmalloc.c파일 상단의 주석을 참조하십시오. 위의 링크는 python.org SVN 브라우저 내의 해당 파일을 가리킵니다.
빌드 및 C API 변경사항¶
파이썬의 빌드 프로세스와 C API에 대한 변경 사항은 다음과 같습니다:
가비지 컬렉션에서 사용되는 순환 감지 구현은 안정적임이 입증되어 이제 필수 항목이 되었습니다. 파이썬을 이것 없이 컴파일할 수 없으며, configure`의 :option:!–with-cycle-gc` 스위치는 제거되었습니다.
파이썬은 이제 실행 시 configure 스크립트에
--enable-shared`를 제공하여 선택적으로 공유 라이브러리(:file:`libpython2.3.so)로 빌드할 수 있습니다. (Ondrej Palkovsky가 기여함.)DL_EXPORT및DL_IMPORT매크로는 이제 사용되지 않습니다. 파이썬 확장 모듈의 초기화 함수는 새 매크로PyMODINIT_FUNC를 사용하여 선언해야 하며, 파이썬 코어는 일반적으로PyAPI_FUNC및PyAPI_DATA매크로를 사용합니다.configure 스크립트에 :option:`!–without-doc-strings`를 제공하여 내장 함수 및 모듈에 대해 docstring 없이 인터프리터를 컴파일할 수 있습니다. 이로 인해 파이썬 실행 파일의 크기가 약 10% 작아지지만, 파이썬의 내장 기능을 위한 도움말을 얻을 수 없게 됩니다. (Gustavo Niemeyer가 기여함.)
PyArg_NoArgs()매크로는 이제 사용되지 않으며, 이를 사용하는 코드는 변경해야 합니다. Python 2.2 이상에서는 메서드 정의 테이블이METH_NOARGS플래그를 지정하여 인수가 없음을 알릴 수 있으며, 그러면 인수 확인을 제거할 수 있습니다. 2.2 이전 버전과의 호환성이 중요하다면, 코드 대신PyArg_ParseTuple(args, "")를 사용할 수 있지만, 이는METH_NOARGS를 사용하는 것보다 느립니다.PyArg_ParseTuple()는 다양한 크기의 부호 없는 정수에 대해 새로운 형식 문자(format characters)를 받아들입니다. unsigned char 용B, unsigned short int 용H, unsigned int 용I, 그리고 unsigned long long 용K가 있습니다.새 함수인
PyObject_DelItemString(mapping, char *key)가PyObject_DelItem(mapping, PyString_New(key))의 짧은 형태로 추가되었습니다.파일 객체가 이제 내부 문자열 버퍼를 다르게 관리하며, 필요할 때 지수 함수적으로 크기를 증가시킵니다. 이로 인해 :file:`Lib/test/test_bufio.py`의 벤치마크 테스트가 상당히 빨라졌습니다 (한 측정에 따르면 57초에서 1.7초로).
메서드의
PyMethodDef구조체에서METH_CLASS또는METH_STATIC플래그를 설정함으로써 C 확장 유형에 대해 클래스 및 정적 메서드를 정의하는 것이 가능해졌습니다.파이썬은 이제 Expat XML 파서의 소스 코드 사본을 포함하여 시스템 버전이나 로컬 설치된 Expat에 대한 의존성을 제거했습니다.
확장 모듈에서 타입 객체를 동적으로 할당하는 경우,
__module__및__name__속성과 관련된 규칙의 변경 사항을 인지해야 합니다. 요약하자면, 타입의 딕셔너리에'__module__'키를 포함하도록 보장해야 하며, 이제 모듈 이름을 최종 마침표까지의 타입 이름 부분으로 지정하는 것이 원하는 효과를 내지 못할 것입니다. 더 자세한 내용은 API 레퍼런스 문서를 참조하거나 소스를 확인하십시오.
플랫폼별 변경 사항¶
EMX 런타임 환경을 사용한 IBM의 OS/2 포트로의 지원이 메인 Python 소스 트리에 통합되었습니다. EMX는 OS/2 시스템 API를 위한 POSIX 에뮬레이션 계층입니다. EMX 런타임이 노출하는 모든 POSIX와 유사한 기능을 지원하려고 시도하며, 대부분 성공합니다. 다만 :func:`!fork`와 :func:`fcntl`은 기반의 에뮬레이션 계층 제한으로 인해 제약적입니다. 표준 OS/2 포트 역시 IBM Visual Age 컴파일러를 사용하며, EMX 포트를 CVS에 통합하는 과정에서 대소문자를 구분하는 가져오기 의미론(import semantics)에 대한 지원을 받게 되었습니다. (Andrew MacIntyre 기여.)
MacOS에서는 하위 호환성을 개선하기 위해 대부분의 툴박스 모듈들이 약하게 링크되었습니다. 이는 현재 OS 버전에서 단일 루틴이 누락되어도 모듈 로딩에 실패하지 않음을 의미합니다. 대신, 해당 누락된 루틴을 호출하면 예외가 발생합니다. (Jack Jansen 기여.)
Python 배포판의 Misc/RPM/ 디렉토리에 있는 RPM 스펙 파일들이 2.3 버전을 위해 업데이트되었습니다. (Sean Reifschneider 기여.)
Python에서 지원하는 다른 새로운 플랫폼에는 AtheOS (http://www.atheos.cx/), GNU/Hurd, OpenVMS가 포함됩니다.
기타 변경 사항 및 수정 사항¶
평소와 같이 소스 트리를 여기저기 거쳐 수많은 기타 개선 사항과 버그 수정이 있었습니다. CVS 변경 로그를 검색해 보면, Python 2.2에서 2.3 사이에는 523개의 패치가 적용되었고 514개의 버그가 수정된 것을 찾을 수 있습니다. 두 수치 모두 과소평가일 가능성이 높습니다.
눈에 띄는 몇 가지 변경 사항은 다음과 같습니다:
만약
PYTHONINSPECT환경 변수가 설정되어 있으면, Python 인터프리터는 Python 프로그램 실행 후 대화형 프롬프트에 진입합니다. 이는 마치 Python을-i옵션으로 호출한 것과 같습니다. 이 환경 변수는 Python 인터프리터를 실행하기 전에 설정하거나, Python 프로그램의 실행 과정에서 의해 설정될 수 있습니다.regrtest.py스크립트는 이제 “마*지* 않*는*” 모든 리소스를 허용하는 방법을 제공합니다.-u옵션에 전달된 리소스 이름은 하이픈('-')을 앞에 붙여 이 리소스를 제거한다는 의미로 사용할 수 있습니다. 예를 들어, ‘-uall,-bsddb’ 옵션을 사용하여 `bsddb`를 제외한 모든 리소스 사용을 활성화할 수 있습니다.문서 작성을 위해 사용되는 도구들이 이제 Unix뿐만 아니라 Cygwin에서도 작동합니다.
SET_LINENO opcode가 제거되었습니다. 예전에는 이 opcode가 트레이스백에서 줄 번호를 생성하고 t race 함수 (:mod:`pdb`의 경우와 같이, 예를 들어)를 지원하는 데 필요했습니다. Python 1.5부터는 트레이스백의 줄 번호가 “python -O”으로 작동하는 다른 메커니즘을 사용하여 계산됩니다. Python 2.3에서 Michael Hudson은 t race 함수 호출 시점을 결정하기 위해 유사한 스킴을 구현하여, `SET_LINENO`의 필요성을 완전히 없<0xEC><0x95><0xB4>습니다.
Python이
-O없이 실행될 때 약간 속도가 향상되는 것 외에는 Python 코드에서 발생하는 어떤 결과적인 차이를 감지하기는 어려울 것입니다.프레임 객체의
f_lineno필드에 접근하는 C 확장 모듈은 대신PyCode_Addr2Line(f_->f_code, f_->f_lasti)를 호출해야 합니다. 이는 이전 버전의 Python에서 “python -O”으로 실행할 때 원하는 대로 작동하도록 추가 효과를 갖습니다.새롭고 편리한 기능은 t race 함수가 이제 프레임 객체의
f_lineno속성에 대입하여 다음에 실행될 줄을 변경할 수 있다는 것입니다. 이 새로운 기능을 활용하여pdb디버거에jump명령이 추가되었습니다. (Richie Hindle 구현.)
Python 2.3으로 포팅하기¶
이 섹션은 코드 변경이 필요할 수 있는 이전에 설명된 변경 사항 목록을 담고 있습니다:
:keyword:`yield`는 이제 항상 키워드입니다. 코드를 작성할 때 변수 이름으로 사용된다면, 다른 이름을 선택해야 합니다.
문자열 X 및 Y 에 대해,
X in Y는 이제 X 가 한 글자보다 길 경우 작동합니다.int()타입 생성자는 더 이상 :exc:`OverflowError`를 발생시키지 않고, 문자열이나 부동 소수점 숫자가 정수에 맞지 않아 너무 큰 경우 길*은* 정수를 반환합니다.유니코드 문자열에 8비트 문자가 포함된 경우, 파일의 인코딩(UTF-8, Latin-1 또는 기타)을 명시적으로 선언해야 합니다. 이 내용은 PEP 263: 소스 코드 인코딩 섹션에서 자세한 정보를 확인하십시오.
_tkinter`를 통해 Tcl 메서드를 호출하면 더 이상 문자열만 반환하지 않습니다. 대신, Tcl이 다른 객체를 반환하는 경우, 만약 해당 객체의 Python 이식이 존재하는 경우 그 객체가 변환되거나, Python 이식이 존재하지 않으면 :class:!_tkinter.Tcl_Obj` 객체로 래핑됩니다.0xffffffff와 같은 큰 팔진수 및 16진수 리터럴은 이제FutureWarning를 발생시킵니다. 현재는 32비트 숫자로 저장되어 음수 값이 되지만, Python 2.4에서는 양의 롱 정수가 됩니다.이 경고를 해결하는 몇 가지 방법이 있습니다. 정말로 양수를 필요로 한다면, 리터럴 끝에
L을 추가하기만 하면 됩니다. 낮은 비트가 설정된 32비트 정수를 얻으려고 시도했고 이전에~(1 << 31)과 같은 표현식을 사용했다면, 모든 비트를 설정한 다음 원하는 상위 비트를 지우는 것이 가장 명확할 수 있습니다. 예를 들어, 최상위 비트(비트 31)만 제거하려면0xffffffffL &~(1L<<31)을 작성할 수 있습니다.더 이상
__debug__에 할당하여 어설션(assertions) 사용을 비활성화할 수 없습니다.Distutils
setup()함수는 이제 depends 와 같은 다양한 새 키워드 인자를 얻었습니다. Distutils의 이전 버전은 알 수 없는 키워드가 전달되면 중단됩니다. 해결책은setup.py에서 새로운get_distutil_options()함수의 존재를 확인하고, 해당 기능을 지원하는 버전의 Distutils를 사용하는 경우에만 새로운 키워드를 사용하는 것입니다:from distutils import core kw = {'sources': 'foo.c', ...} if hasattr(core, 'get_distutil_options'): kw['depends'] = ['foo.h'] ext = Extension(**kw)
변수 이름으로
None을 사용하면 이제SyntaxWarning경고가 발생합니다.Python에 포함된 모듈이 정의한 타입의 이름에는 이제 모듈명과 타입 이름 앞의
'.'가 포함됩니다.
감사의 말¶
필자는 이 글의 다양한 초안을 제안하고 수정하며 도움을 준 다음 사람들에게 감사드립니다: Jeff Bauer, Simon Brunning, Brett Cannon, Michael Chermside, Andrew Dalke, Scott David Daniels, Fred L. Drake, Jr., David Fraser, Kelly Gerber, Raymond Hettinger, Michael Hudson, Chris Lambert, Detlef Lannert, Martin von Löwis, Andrew MacIntyre, Lalo Martins, Chad Netzer, Gustavo Niemeyer, Neal Norwitz, Hans Nowak, Chris Reedy, Francesco Ricciardi, Vinay Sajip, Neil Schemenauer, Roman Suzi, Jason Tishler, Just van Rossum.