PEP 3114 – 이터레이터.next()를 이터레이터.__next__()로 이름을 변경합니다.
- Author:
- Ka-Ping Yee <ping at zesty.ca>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 04-Mar-2007
- Python-Version:
- 3.0
- Post-History:
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
Python 2.x의 이터레이터 프로토콜은 두 메서드로 구성됩니다. 이터레이터를 생성하기 위해 이터러블 객체에서 호출되는 __iter__()와 시퀀스의 다음 항목을 생성하기 위해 이터레이터 객체에서 호출되는 next()입니다. 이터러블 객체를 순회하기 위해 for 루프를 사용하면 이 두 메서드가 모두 암묵적으로 호출됩니다. 이 PEP는 Python의 다른 모든 프로토콜과 일관되도록 next 메서드의 이름을 __next__로 변경할 것을 제안합니다. 이러한 프로토콜에서는 언어 수준 프로토콜의 일부로 메서드가 암묵적으로 호출됩니다. 또한 다른 프로토콜을 명시적으로 호출하는 방식과 일관되도록 __next__ 메서드를 호출하는 next라는 내장 함수를 도입할 것을 제안합니다.
이중 밑줄이 있는 이름
Python에서는 이름 앞뒤의 이중 밑줄을 사용하여 언어 자체에 속하는 이름을 구분합니다. 인터프리터가 암묵적으로 사용하거나 생성하는 속성과 메서드는 이 명명 규칙을 사용합니다. 예는 다음과 같습니다.
__file__- 인터프리터가 자동으로 생성하는 속성__dict__- 인터프리터에 특별한 의미를 갖는 속성__init__- 인터프리터가 암묵적으로 호출하는 메서드
이 규칙은 프로그래머가 명시적으로 정의한 __init__과 같은 메서드뿐만 아니라, 명시적으로 이름을 지정해야만 액세스할 수 있는 __file__과 같은 속성에도 적용되므로, 인터프리터가 사용하거나 생성하는 이름도 포함합니다.
(“프로토콜”이라고 불리는 모든 것이 이중 밑줄 이름을 가진 메서드로 구성되는 것은 아닙니다. 예를 들어 __contains__ 메서드에는 이중 밑줄이 있습니다. 언어 구문 x in y가 암묵적으로 __contains__를 호출하기 때문입니다. 그러나 read 메서드가 파일 프로토콜의 일부이더라도 이 메서드에는 이중 밑줄이 없습니다. x.read()를 암묵적으로 호출하는 언어 구문이 없기 때문입니다.)
이중 밑줄을 사용하면 Python 언어 정의의 일부인 이름을 위한 별도의 네임스페이스가 생성됩니다. 따라서 프로그래머는 언어에서 정의된 목적을 가진 이름과 자신도 모르게 충돌할 염려 없이 문자로 시작하는 변수, 속성 및 메서드를 자유롭게 생성할 수 있습니다. (예약 키워드와 충돌하는 것은 여전히 문제이지만, 적어도 이 경우에는 즉시 구문 오류가 발생합니다.)
이터레이터의 next 메서드 명명은 이 규칙의 예외입니다. next 메서드를 명시적으로 호출하는 코드가 전혀 없더라도 이러한 메서드의 존재로 인해 코드가 조용히 영향을 받을 수 있습니다. 따라서 이 PEP는 의미 변경 없이 이터레이터가 next 메서드 대신 __next__ 메서드를 가져야 한다고 제안합니다.
이중 밑줄 메서드와 내장 함수
Python 언어는 이중 밑줄 이름을 가진 메서드를 정의하여 구현하거나 사용자 지정할 수 있는 여러 프로토콜을 정의합니다. 각 경우에 프로토콜은 인터프리터에서 C 함수로 구현된 내부 메서드에 의해 제공됩니다. Python에서 정의된 객체의 경우 이 C 함수는 이중 밑줄 이름을 가진 Python 메서드를 암묵적으로 호출하여 사용자 지정을 지원합니다. (이 함수는 Python 메서드를 호출하는 것 외에도 약간의 추가 작업을 수행하는 경우가 많습니다.)
때로는 구문 구성을 통해 프로토콜이 호출됩니다.
x[y]–> internaltp_getitem–>x.__getitem__(y)x + y–> internalnb_add–>x.__add__(y)-x–> internalnb_negative–>x.__neg__()
때로는 구문 구성이 없지만 프로토콜을 명시적으로 호출할 수 있는 것이 여전히 유용합니다. 이러한 경우 Python은 이중 밑줄이 없는 동일한 이름의 내장 함수를 제공합니다.
len(x)–> internalsq_length–>x.__len__()hash(x)–> internaltp_hash–>x.__hash__()iter(x)–> internaltp_iter–>x.__iter__()
이 패턴에 따르면, next를 처리하는 자연스러운 방법은 정확히 같은 방식으로 동작하는 next 내장 함수를 추가하는 것입니다.
next(x)–> 내부tp_iternext–>x.__next__()
또한 getattr 및 iter 내장 함수의 방식에 따라 next 내장 함수가 선택적 두 번째 인자로 센티널 값을 받도록 제안합니다. 두 인자와 함께 호출되면 next 는 StopIteration 예외를 포착하고 예외를 전파하는 대신 센티널 값을 반환합니다. 이는 iter 와 next 사이에 훌륭한 이중성을 만듭니다.
iter(function, sentinel) <–> next(이터레이터, sentinel)
이전 제안
이 제안은 새로운 아이디어가 아닙니다. 여기서 제안하는 아이디어는 python-dev의 BDFL이 지지했으며 [1] 원래 이터레이터 PEP인 PEP 234 에도 언급되어 있습니다.:
(In retrospect, it might have been better to go for __next__()
and have a new built-in, next(it), which calls it.__next__().
But alas, it's too late; this has been deployed in Python 2.2
since December 2001.)
반대 의견
내장 함수를 더 추가하는 데에는 몇 가지 반대 의견이 있었습니다. 특히 Martin von Loewis는 [2] 다음과 같이 작성합니다.:
I dislike the introduction of more builtins unless they have a true
generality (i.e. are likely to be needed in many programs). For this
one, I think the normal usage of __next__ will be with a for loop, so
I don't think one would often need an explicit next() invocation.
It is also not true that most protocols are explicitly invoked through
builtin functions. Instead, most protocols are can be explicitly invoked
through methods in the operator module. So following tradition, it
should be operator.next.
...
As an alternative, I propose that object grows a .next() method,
which calls __next__ by default.
전환 계획
2to3 변환 도구 [3] 에 두 가지 추가 변환이 추가됩니다.
next라는 이름의 메서드 정의는__next__로 이름이 변경됩니다.next메서드를 명시적으로 호출하는 코드는next내장 함수를 호출하는 코드로 대체됩니다. 예를 들어x.next()는next(x)가 됩니다.
Collin Winter는 모듈 수준에서 next 에 바인딩된 이름이 존재하는지에 따라 두 번째 변환을 수행할지 자동으로 결정할 가능성 [4] 을 검토했으며, 그것이 “추하고 느릴” 것이라고 판단했습니다. 대신 변환 도구는 이러한 바인딩을 감지하면 경고를 출력합니다. Collin은 다음 조건에 대해 경고를 제안했습니다 [5].
next에 대한 모듈 수준 할당입니다.next라는 이름의 함수에 대한 모듈 수준 정의입니다.next라는 이름에 대한 모듈 수준 가져오기입니다.__builtin__.next에 대한 할당입니다.
승인
이 PEP는 2007년 3월 6일 Guido가 승인했습니다 [6].
구현
필요한 변경 사항이 포함된 패치(2to3 도구 제외)는 Georg Brandl이 작성했으며 리비전 54910으로 커밋되었습니다.
참고 자료
Copyright
This document has been placed in the public domain.