Python 3.1의 새로운 기능¶
- 저자:
Raymond Hettinger
이 기사에서는 Python 3.0과 비교하여 Python 3.1의 새로운 기능에 관해 설명합니다. Python 3.1은 2009년 6월 27일에 배포되었습니다.
PEP 372: 순서가 유지되는 딕셔너리(Ordered Dictionaries)¶
정규 Python 딕셔너리는 키/값 쌍을 임의의 순서로 반복합니다. 세월이 흐르면서 여러 저자들이 키가 원래 삽입된 순서를 기억하는 대체 구현을 작성해 왔습니다. 이러한 구현의 경험을 바탕으로 새로운 collections.OrderedDict 클래스가 도입되었습니다.
OrderedDict API는 기본 딕셔너리와 실질적으로 동일하지만, 키가 처음 삽입된 시간에 따라 보장된 순서로 키와 값을 반복합니다. 새 항목이 기존 항목을 덮어쓰는 경우, 원래 삽입 위치는 변경되지 않습니다. 항목을 삭제했다가 다시 삽입하면 끝으로 이동합니다.
표준 라이브러리는 이제 여러 모듈에서 순서가 지정된 딕셔너리 사용을 지원합니다. configparser 모듈은 기본적으로 이를 사용합니다. 이를 통해 설정 파일을 원래 순서대로 읽고, 수정하고, 다시 쓸 수 있습니다. collections.namedtuple() 의 _asdict() 메서드는 이제 기본 튜플 인덱스와 동일한 순서로 값이 나타나는 순서가 지정된 딕셔너리를 반환합니다. json 모듈은 디코더에 의해 OrderedDict가 빌드될 수 있도록 object_pairs_hook 으로 구축되고 있습니다. 지원은 또한 PyYAML <https://pyyaml.org/> 와 같은 외부 도구에도 추가되었습니다.
더 보기
- PEP 372 - Ordered Dictionaries
PEP는 Armin Ronacher가 작성하고 Raymond Hettinger가 구현했습니다. 구현은 Raymond Hettinger가 담당했습니다.
순서가 지정된 딕셔너리는 삽입 순서를 기억하기 때문에, 정렬과 결합하여 정렬된 딕셔너리를 만들 수 있습니다:
>>> # 일반적인 정렬되지 않은 딕셔너리
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # 키로 정렬된 딕셔너리
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # 값으로 정렬된 딕셔너리
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # 키 문자열 길이를 기준으로 정렬된 딕셔너리
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
새로운 정렬된 딕셔너리는 항목이 삭제될 때 정렬 순서를 유지합니다. 그러나 새 키가 추가될 때, 키는 끝에 추가되며 정렬은 유지되지 않습니다.
PEP 378: 천 단위 구분 기호 포매터¶
내장 format() 함수와 str.format() 메서드는 이제 천 단위 구분자로 숫자를 포맷하는 간단하고 지역화되지 않은 방법을 포함하는 미니 언어를 사용합니다. 이는 프로그램의 출력을 인간화하는 방법을 제공하여 전문적인 외관과 가독성을 향상시킵니다:
>>> format(1234567, ',d')
'1,234,567'
>>> format(1234567.89, ',.2f')
'1,234,567.89'
>>> format(12345.6 + 8901234.12j, ',f')
'12,345.600000+8,901,234.120000j'
>>> format(Decimal('1234567.89'), ',f')
'1,234,567.89'
지원되는 타입은 int, float, complex, 그리고 :class:`decimal.Decimal`입니다.
점, 공백, 아포스트로피 또는 밑줄과 같은 대체 구분자를 지정하는 방법에 대한 논의가 진행 중입니다. 지역화에 민감한 애플리케이션은 이미 천 단위 구분자에 대한 일부 지원을 갖춘 기존 n 포맷 지정자를 사용해야 합니다.
더 보기
- PEP 378 - 천 단위 구분자용 포맷 지정자
PEP는 Raymond Hettinger가 작성하고 Eric Smith와 Mark Dickinson가 구현했습니다.
다른 언어 변경 사항들¶
핵심 파이썬 언어에 일부 작은 변경 사항들이 있습니다.
__main__.py파일을 포함하는 디렉터리 및 zip 아카이브는 이제 인터프리터에 이름을 전달하여 직접 실행할 수 있습니다. 디렉터리/zipfile은 sys.path의 첫 번째 항목으로 자동 삽입됩니다. (Andy Chu가 제안하고 초기 패치했으며; Phillip J. Eby와 Nick Coghlan이 수정했습니다; bpo-1739468).int()타입은 인수를 이진수로 나타내는 데 필요한 비트 수를 반환하는bit_length메서드를 얻었습니다:>>> n = 37 >>> bin(37) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(Fredrik Johansson, Victor Stinner, Raymond Hettinger, Mark Dickinson가 기여했으며; bpo-3439.)
format()문자열의 필드는 이제 자동으로 번호가 매겨질 수 있습니다:>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
이전에는 문자열에
'Sir {0} of {1}'와 같은 번호가 매겨진 필드가 필요했습니다.(Eric Smith가 기여했으며; bpo-5237.)
string.maketrans()함수는 더 이상 사용되지 않으며, 새로운 정적 메서드인bytes.maketrans`와 :meth:`bytearray.maketrans`로 대체되었습니다. 이 변경 사항은 :mod:`string()모듈에서 어떤 타입이 지원되었는지와 관련된 혼란을 해결합니다. 이제str,bytes, 그리고 :class:`bytearray`는 각각 적절한 타입의 중간 번역 테이블을 가진 자체 maketrans 및 translate 메서드를 가집니다.(Georg Brandl 기여; bpo-5675.)
with문의 구문이 이제 단일 구문에서 여러 컨텍스트 관리자를 허용합니다:>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '<critical>' in line: ... outfile.write(line)
새로운 구문과 함께
contextlib.nested()함수는 더 이상 필요하지 않으며 이제 사용 중지되었습니다.(Georg Brandl 및 Mattias Brändström 기여; appspot issue 53094.)
round(x, n)은 이제 x 가 정수일 경우 정수를 반환합니다. 이전에는 float을 반환했었습니다:>>> round(1123, -2) 1100
(Mark Dickinson 기여; bpo-4707.)
Python은 이제 값의 변화를 일으키지 않는 가장 짧은 부동 소수점 표현을 찾는 데 David Gay의 알고리즘을 사용합니다. 이는 이진 부동 소수점 숫자를 둘러싼 일부 혼란을 완화하는 데 도움이 될 것입니다.
이러한 중요성은 이진 부동 소수점에서 정확한 동등한 값이 없는
1.1과 같은 숫자로 쉽게 확인할 수 있습니다. 정확한 동등한 값이 없기 때문에,float('1.1')과 같은 표현식은 가장 가까운 표현 가능한 값으로 평가되며, 이는 16진수로는0x1.199999999999ap+0또는 십진수로는1.100000000000000088817841970012523233890533447265625입니다. 이 가장 가까운 값이 이후 부동 소수점 계산에서 계속 사용됩니다.새롭게 바뀐 것은 숫자가 표시되는 방식입니다. 이전에는 Python이 간단한 접근 방식을 사용했습니다.
repr(1.1)의 값은format(1.1, '.17g')로 계산되어'1.1000000000000001'로 평가되었습니다. 17자리를 사용하는 이점은 IEEE-754 보장을 이용해eval(repr(1.1))이 원래 값으로 정확히 왕복할 것이라고 보장하는 것이었습니다. 단점은 많은 사람들이 출력값이 혼란스럽다고 느꼈다는 것입니다 (이진 부동 소수점 표현의 고유한 한계를 파이썬 자체의 문제로 오해함).repr(1.1)을 위한 새로운 알고리즘은 더 똑똑하며'1.1'을 반환합니다. 효과적으로, 이 알고리즘은 모든 동등한 문자열 표현(동일한 기본 float 값을 가지고 저장되는 문자열)을 검색하고 가장 짧은 표현을 반환합니다.새로운 알고리즘은 가능할 때 더 깔끔한 표현을 내세우는 경향이 있지만, 근본적인 값 자체는 변경하지 않습니다. 따라서 표현은 다르게 암시할 수 있음에도 불구하고
1.1 + 2.2 != 3.3인 경우는 여전히 존재합니다.새로운 알고리즘은 기본 부동 소수점 구현의 특정 기능에 의존합니다. 필요한 기능이 발견되지 않으면 이전 알고리즘이 계속 사용됩니다. 또한, 텍스트 피클 프로토콜은 이전 알고리즘을 사용하여 플랫폼 간 이식성을 보장합니다.
(Eric Smith 및 Mark Dickinson 기여; bpo-1580.)
새롭고, 개선되고, 사용 중단된 모듈¶
시퀀스 또는 이터러블의 고유 항목을 편리하게 계산할 수 있도록
collections.Counter클래스가 추가되었습니다:>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
(Raymond Hettinger 기여; bpo-1696199.)
Tk 테마 위젯 세트에 접근하기 위한 새로운 모듈인 :mod:`tkinter.ttk`가 추가되었습니다. ttk의 기본 아이디어는 위젯 동작을 구현하는 코드와 모양을 구현하는 코드를 가능한 한 분리하는 것입니다.
(Guilherme Polo 기여; bpo-2983.)
gzip.GzipFile및bz2.BZ2File클래스가 이제 컨텍스트 관리 프로토콜을 지원합니다:>>> # 파일 작성 후 자동으로 닫기 >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
(Antoine Pitrou가 기여했습니다.)
decimal모듈은 이제 이진 :class:`float`으로부터 십진 객체를 생성하는 메서드를 지원합니다. 변환은 정확하지만 때로는 놀라울 수 있습니다:>>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625')
긴 십진 결과는 1.1 에 대해 저장된 실제 이진 분수를 보여줍니다. 이 분수는 1.1 이 이진수로 정확하게 표현될 수 없기 때문에 많은 자릿수를 가집니다.
(Raymond Hettinger 및 Mark Dickinson 기여.)
itertools모듈에 두 개의 새로운 함수가 추가되었습니다.itertools.combinations_with_replacement()함수는 순열과 카티션 곱을 포함하여 조합을 생성하는 네 가지 함수 중 하나입니다.itertools.compress()함수는 APL에서 유래한 같은 이름을 모방합니다. 또한, 기존의itertools.count()함수에는 이제 선택적 step 인자가 추가되었으며,fractions.Fraction및 :class:`decimal.Decimal`을 포함한 모든 유형의 카운팅 시퀀스를 허용할 수 있습니다.:>>> [p+q for p,q in combinations_with_replacement('LOVE', 2)] ['LL', 'LO', 'LV', 'LE', 'OO', 'OV', 'OE', 'VV', 'VE', 'EE'] >>> list(compress(data=range(10), selectors=[0,0,1,1,0,1,0,1,0,0])) [2, 3, 5, 7] >>> c = count(start=Fraction(1,2), step=Fraction(1,6)) >>> [next(c), next(c), next(c), next(c)] [Fraction(1, 2), Fraction(2, 3), Fraction(5, 6), Fraction(1, 1)]
(Raymond Hettinger 작성.)
:func:`collections.namedtuple`는 이제 rename 키워드 인자를 지원합니다. 이를 통해 유효하지 않은 필드 이름이 _0, _1 등과 같은 위치 이름으로 자동 변환될 수 있습니다. 필드 이름이 CSV 헤더, SQL 필드 목록 또는 사용자 입력과 같은 외부 소스에 의해 생성되는 경우 유용합니다.:
>>> query = input() SELECT region, dept, count(*) FROM main GROUPBY region, dept >>> cursor.execute(query) >>> query_fields = [desc[0] for desc in cursor.description] >>> UserQuery = namedtuple('UserQuery', query_fields, rename=True) >>> pprint.pprint([UserQuery(*row) for row in cursor]) [UserQuery(region='South', dept='Shipping', _2=185), UserQuery(region='North', dept='Accounting', _2=37), UserQuery(region='West', dept='Sales', _2=419)]
(Raymond Hettinger가 기여했습니다; bpo-1818)
re.sub(),re.subn()및re.split()함수는 이제 flags 매개변수를 받습니다.(Gregory Smith가 기여했습니다.)
logging모듈은 이제 로깅을 사용하지 않지만 로깅을 사용하는 라이브러리 코드를 호출하는 애플리케이션을 위한 간단한logging.NullHandler클래스를 구현합니다. null 핸들러를 설정하면 “No handlers could be found for logger foo”::와 같은 불필요한 경고를 억제할 수 있습니다.>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(Vinay Sajip가 기여했습니다; bpo-4384)
runpy모듈은-m명령줄 전환을 지원하는 버전에서 이제 패키지 이름을 제공할 때 __main__ 서브모듈을 찾아 실행함으로써 패키지 실행을 지원합니다.(Andi Vajda가 기여했습니다; bpo-4195)
pdb모듈은 이제zipimport(또는 다른 호환되는 PEP 302 로더)를 통해 로드된 소스 코드를 접근하고 표시할 수 있습니다.(Alexander Belopolsky가 기여했습니다; bpo-4201)
functools.partial객체는 이제 피클링할 수 있습니다.
(Antoine Pitrou와 Jesse Noller가 제안했으며, Jack Diederich가 구현했습니다; bpo-5228)
help(‘@’)`가 대화형 환경에서 예상대로 작동하도록 심볼에 대한 :mod:`pydoc 도움말 주제를 추가합니다.
(David Laban이 기여했습니다; bpo-4739)
unittest모듈은 이제 개별 테스트나 테스트 클래스를 건너뛰는 기능을 지원합니다. 또한, 테스트가 깨져서 실패하는 것이 알려져 있지만, TestResult에서 실패로 계산되어서는 안 되는 “예상된 실패”로 테스트에 표시하는 기능도 지원합니다.:class TestGizmo(unittest.TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_gizmo_on_windows(self): ... @unittest.expectedFailure def test_gimzo_without_required_library(self): ...
또한, 예외에 대한 테스트는
with문을 사용하는 컨텍스트 관리자와 함께 작동하도록 빌드되었습니다.:def test_division_by_zero(self): with self.assertRaises(ZeroDivisionError): x / 0
또한,
assertSetEqual(),assertDictEqual(),assertDictContainsSubset(),assertListEqual(),assertTupleEqual(),assertSequenceEqual(),assertRaisesRegexp(),assertIsNone(), 및 :meth:`~unittest.TestCase.assertIsNotNone`을 포함하여 여러 새로운 단언 메서드가 추가되었습니다.(Benjamin Peterson과 Antoine Pitrou가 기여했습니다.)
io모듈은seek()메서드를 위해 세 가지 새로운 상수(SEEK_SET,SEEK_CUR, 및SEEK_END)를 가지고 있습니다.sys.version_info튜플은 이제 이름 지정 튜플입니다.:>>> sys.version_info sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)
(Ross Light가 기여했습니다; bpo-4285)
nntplib및imaplib모듈은 이제 IPv6을 지원합니다.pickle모듈은 프로토콜 2 또는 그 이하로 사용될 때 Python 2.x와의 상호 운용성을 개선하도록 조정되었습니다. 표준 라이브러리의 재구성은 많은 객체의 형식적 참조를 변경했습니다. 예를 들어, Python 2의__builtin__.set은 Python 3에서는builtins.set이라고 불립니다. 이 변경은 파이썬의 여러 버전 간에 데이터를 공유하려는 노력을 혼란스럽게 했습니다. 그러나 이제 프로토콜 2 또는 그 이하가 선택되면, 피클러는 로딩과 덤핑 모두에 대해 자동으로 이전의 Python 2 이름을 사용합니다. 이 재매핑은 기본적으로 켜져 있지만 fix_imports 옵션으로 끌 수 있습니다.:>>> s = {1, 2, 3} >>> pickle.dumps(s, protocol=0) b'c__builtin__\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.' >>> pickle.dumps(s, protocol=0, fix_imports=False) b'cbuiltins\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.'
Python 3.1에서 생성된 protocol 2 피클의 경우, Python 3.0에서는 읽을 수 없다는 불행하지만 피할 수 없는 부작용이 있습니다. 데이터 마이그레이션 시 Python 3.x 구현 간에는 Python 2.x와 호환성을 유지하려고 시도하지 않는 최신 피클 프로토콜인 protocol 3를 사용해야 합니다.
(Antoine Pitrou와 Alexandre Vassalotti가 기여했습니다, bpo-6137.)
새 모듈인
importlib`가 추가되었습니다. 이 모듈은 :keyword:`import구문과 그 대응 함수인__import__()함수에 대한 완전하고, 이식성이 높으며, 순수 Python 참조 구현을 제공합니다. 이는 import 중에 발생하는 작업을 문서화하고 정의하는 데 있어 상당한 진전을 나타냅니다.(Brett Cannon 기여).
최적화들`¶
주요 성능 향상이 추가되었습니다:
새 I/O 라이브러리( PEP 3116 에서 정의됨)는 대부분 Python으로 작성되었으나, Python 3.0에서 까다로운 병목 현상을 일으키는 것으로 빠르게 판명되었습니다. Python 3.1에서는 I/O 라이브러리가 C로 완전히 재작성되었으며, 작업에 따라 2배에서 20배까지 더 빠릅니다. 순수 Python 버전은 여전히
_pyio모듈을 통해 실험 목적으로 사용할 수 있습니다.(Amaury Forgeot d’Arc와 Antoine Pitrou가 기여했습니다.)
추적할 수 없는 객체만을 포함하는 튜플과 딕셔너리가 가비지 컬렉터에 의해 추적되지 않도록 하는 휴리스틱이 추가되었습니다. 이는 컬렉션의 크기를 줄여, 데이터 형식의 사용에 따라 장시간 실행되는 프로그램의 가비지 컬렉션 오버헤드를 감소시킬 수 있습니다.
(Antoine Pitrou가 기여했습니다, bpo-4688.)
지원하는 컴파일러(주로: gcc, SunPro, icc)에서
--with-computed-gotos라는 구성 옵션을 활성화하면, 바이트코드를 평가하는 루프는 새로운 디스패치 메커니즘으로 컴파일되며, 시스템, 컴파일러 및 벤치마크에 따라 최대 20%의 속도 향상을 제공합니다.(Antoine Pitrou가 여러 참여자들과 함께 기여했습니다, bpo-4753).
UTF-8, UTF-16 및 LATIN-1의 디코딩 속도가 이제 2배에서 4배까지 빨라졌습니다.
(Antoine Pitrou와 Amaury Forgeot d’Arc가 기여했습니다, bpo-4868.)
json모듈에 성능을 대폭 향상시키는 C 확장 기능이 추가되었습니다. 또한, API가 수정되어 json이 :class:`str`와만 작동하고 :class:`bytes`와는 작동하지 않게 되었습니다. 이 변경으로 모듈이 유니코드의 관점에서 정의된 `JSON specification <https://json.org/>`_와 가깝게 일치하게 되었습니다.(Bob Ippolito가 기여했으며 Antoine Pitrou와 Benjamin Peterson에 의해 Py3.1로 변환되었습니다; bpo-4136.)
Unpickling 시 이제 피클된 객체의 속성 이름을 내부 저장소에 보관(intern)합니다. 이는 메모리를 절약하고 피클 파일을 더 작게 만들 수 있도록 합니다.
(Jake McGuire와 Antoine Pitrou가 기여했습니다; bpo-5084.)
IDLE¶
IDLE의 파일 메뉴에서 이제 소스 파일의 끝 공백을 제거하는 옵션을 제공합니다.
(Roger D. Serwy가 기여했습니다; bpo-5150.)
빌드 및 C API 변경사항¶
파이썬의 빌드 프로세스와 C API에 대한 변경 사항은 다음과 같습니다:
정수형은 이제 내부적으로 base
2**15또는 base2**30에 저장됩니다. 베이스는 빌드 시점에 결정됩니다. 이전에는 항상 base2**15에 저장되었습니다. base2**30을 사용하면 64비트 기계에서 상당한 성능 향상을 얻을 수 있지만, 32비트 기계에서의 벤치마크 결과는 혼재되어 왔습니다. 따라서 기본값은 64비트 기계에서 base2**30을, 32비트 기계에서 base2**15를 사용하도록 되어 있으며, Unix에서는 이 기본값을 재정의할 수 있는 새로운 구성 옵션--enable-big-digits가 있습니다.이 변경은 성능 개선 외에는 최종 사용자에게 보이지 않아야 하지만, 한 가지 예외가 있습니다. 테스트 및 디버깅 목적으로 내부 형식에 대한 정보를 제공하는 새로운 :data:`sys.int_info`가 존재하며, 여기에는 숫자의 비트 수와 각 자릿수를 저장하는 데 사용되는 C 타입의 바이트 크기가 포함됩니다:
>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(마크 디킨슨 기여; bpo-4258.)
PyLong_AsUnsignedLongLong()함수는 이제 음수 pylong 을TypeError대신OverflowError를 발생시켜 처리합니다.(Mark Dickinson와 Lisandro Dalcrin이 기여했습니다; bpo-5175.)
폐기된
PyNumber_Int(). 대신 :c:func:`PyNumber_Long`을 사용하십시오.(Mark Dickinson 기고; bpo-4910.)
PyOS_ascii_strtod()및 :c:func:`!PyOS_ascii_atof`가 폐지되었으며, 새 함수 :c:func:`PyOS_string_to_double`로 대체되었습니다.(Mark Dickinson 기고; bpo-5914.)
PyCObjectAPI를 대체하는 :c:type:`PyCapsule`가 추가되었습니다. 주요 차이점은 새 타입이 타입 안전성 정보를 전달하기 위한 잘 정의된 인터페이스를 가지고 있으며, 소멸자를 호출하는 시그니처가 덜 복잡하다는 것입니다. 이전 타입은 문제가 있는 API를 가지고 있어 이제 폐지되었습니다.(Larry Hastings 기고; bpo-5630.)
파이썬 3.1로 이식하기¶
본 섹션은 코드 변경이 필요할 수 있는 이전에 설명한 변경 사항과 기타 버그 수정 사항을 나열합니다:
새 부동소수점 문자열 표현은 기존 doctest를 깨뜨릴 수 있습니다. 예를 들면:
def e(): '''자연로그의 밑을 계산합니다. >>> e() 2.7182818284590451 ''' return sum(1/math.factorial(x) for x in reversed(range(30))) doctest.testmod() ********************************************************************** 실패한 예제: e() 기대값: 2.7182818284590451 얻은 값: 2.718281828459045 **********************************************************************
pickle 모듈에서 프로토콜 2 이하에 대한 자동 이름 재매핑 기능은 Python 3.1의 pickle 파일을 Python 3.0에서 읽을 수 없게 만들 수 있습니다. 한 가지 해결책은 프로토콜 3을 사용하는 것입니다. 또 다른 해결책은 fix_imports 옵션을
False로 설정하는 것입니다. 더 자세한 내용은 위 논의를 참조하십시오.