PEP 3135 – 새로운 super
- Author:
- Calvin Spealman <ironfroggy at gmail.com>, Tim Delaney <timothy.c.delaney at gmail.com>, Lie Ryan <lie.1296 at gmail.com>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 28-Apr-2007
- Python-Version:
- 3.0
- Post-History:
- 28-Apr-2007, 29-Apr-2007, 29-Apr-2007, 14-May-2007, 12-Mar-2009
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
번호에 관한 참고
이 PEP는 원래 PEP 367로 시작했습니다. 이제 Python 3000을 대상으로 하므로 3xxx 번호대로 옮겨졌습니다.
초록
이 PEP는 super 타입 사용을 위한 문법 설탕을 제안합니다. 이를 사용하면 메서드가 정의된 클래스와 그 메서드가 현재 작용하고 있는 인스턴스(클래스 메서드의 경우 클래스 객체)에 바인딩되는 super 타입 인스턴스가 자동으로 생성됩니다.
제안하는 새로운 super 사용법의 전제는 다음과 같습니다:
super().foo(1, 2)
이는 기존의 다음 코드를 대체합니다:
super(Foo, self).foo(1, 2)
근거
현재 super를 사용하려면 super가 기준으로 삼아야 하는 클래스와 인스턴스를 모두 명시적으로 전달해야 하므로 DRY(Don’t Repeat Yourself) 원칙을 어기게 됩니다. 이 때문에 클래스 이름을 바꾸기가 어려우며, 많은 사람이 이를 흠으로 여기곤 합니다.
명세
명세 절에서는 서로 비슷하고 밀접하게 관련된 개념을 구별하기 위해 몇 가지 특별한 용어를 사용합니다. “super 클래스”는 “super”라는 이름의 실제 내장 클래스를 가리킵니다. “super 인스턴스”는 단순히 super 클래스의 인스턴스로, 다른 클래스와 연관되며 경우에 따라 그 클래스의 인스턴스와도 연관됩니다.
새로운 super 의미 체계는 Python 3.0에서만 사용할 수 있습니다.
기존의 super 사용법 대신, 클래스 객체를 명시적으로 전달하지 않고도 MRO(메서드 결정 순서)상의 다음 클래스를 호출할 수 있습니다(명시적으로 전달하는 방식도 계속 지원됩니다). 모든 함수에는 __class__라는 이름의 셀이 생기며, 이 셀에는 그 함수가 정의된 클래스 객체가 들어 있습니다.
새로운 문법:
super()
다음과 동등합니다:
super(__class__, <firstarg>)
여기서 __class__는 메서드가 정의된 클래스이고, <firstarg>는 메서드의 첫 번째 매개변수입니다(보통 인스턴스 메서드에서는 self, 클래스 메서드에서는 cls입니다). 클래스 본문 밖에서 정의된 함수에서는 __class__가 정의되지 않으므로 런타임에 SystemError가 발생합니다.
super는 예약어가 아니지만, 파서는 메서드 정의 안에서 super가 사용된 것을 인식하고, 이를 발견한 경우에만 __class__ 셀을 전달합니다. 따라서 super의 전역 별칭을 인자 없이 호출하면 반드시 동작한다는 보장은 없습니다.
해결된 문제
사용할 클래스 객체 결정하기
클래스 객체는 __class__라는 이름의 셀에서 가져옵니다.
super가 실제로 키워드가 되어야 합니까?
아닙니다. super가 키워드가 될 필요는 없습니다.
__call__ 속성과 함께 사용되는 super
super 인스턴스를 고전적인 방식으로 생성하는 것이 문제가 될 수 있다는 의견이 있었습니다. 이를 호출하면 __call__ 속성을 조회하게 되고, 그 결과 MRO상의 다음 클래스에 대해 자동 super 조회를 시도할 것이라는 이유였습니다. 그러나 객체를 호출할 때는 객체의 타입에서 직접 __call__ 메서드만 조회하므로 이 우려는 사실이 아닌 것으로 밝혀졌습니다. 다음 예제는 이것이 실제로 어떻게 동작하는지 보여 줍니다.
class A(object):
def __call__(self):
return '__call__'
def __getattribute__(self, attr):
if attr == '__call__':
return lambda: '__getattribute__'
a = A()
assert a() == '__call__'
assert a.__call__() == '__getattribute__'
어쨌든 super(<class>, <instance>)를 사용하는 기존 방식의 호출은 여전히 같은 의미로 지원되므로, 이 문제는 완전히 사라집니다.
대안 제안
변경하지 않음
모든 것을 지금 그대로 유지하는 쪽은 언제나 매력적이지만, 사람들은 한동안 super 호출 방식의 변경을 요구해 왔으며, 앞서 모두 언급했듯이 그럴 만한 이유가 있습니다.
- 클래스 이름으로부터의 분리(그 이름이 더 이상 올바른 클래스에 바인딩되어 있지 않을 수도 있습니다!)
- 더 단순해 보이고 더 깔끔한 super 호출이 더 낫습니다
super 타입의 동적 속성
이 제안은 super 타입에 동적 속성 조회를 추가하며, 이 조회는 적절한 클래스 매개변수와 인스턴스 매개변수를 자동으로 결정합니다. 각 super 속성 조회는 이러한 매개변수를 식별하고 인스턴스에 대해 super 조회를 수행합니다. 이는 현재의 super 구현이 클래스와 인스턴스에 대해 super 인스턴스를 명시적으로 호출하여 수행하는 방식과 같습니다.
이 제안은 sys._getframe()에 의존하는데, 이는 프로토타입 구현 외에는 적합하지 않습니다.
self.__super__.foo(*args)
__super__ 속성은 이 PEP의 여러 곳에서 언급되며, super를 직접 사용하는 대신 이 속성을 명시적으로 사용하는 완전한 해결책의 후보가 될 수 있습니다. 그러나 이중 밑줄 이름은 보통 내부 세부 사항이며, 일상적인 코드에는 드러나지 않도록 하려는 것입니다.
super(self, *args) 또는 __super__(self, *args)
이 해결책은 타입 지정 문제만 해결할 뿐, 이름이 다른 super 메서드는 처리하지 못하며, 인스턴스의 이름을 명시적으로 드러냅니다. 필요한 경우에 다른 메서드 이름에 대해 적용할 수 없으므로 유연성이 떨어집니다. 이 방식이 실패하는 사용 사례 중 하나는 베이스 클래스에 팩토리 클래스 메서드가 하나 있고 서브클래스에 팩토리 클래스 메서드가 두 개 있으며, 그 두 메서드 모두 베이스 클래스의 메서드에 대해 올바르게 super 호출을 해야 하는 경우입니다.
super.foo(self, *args)
이 변형은 올바른 인스턴스를 찾는 문제를 실제로 없애 주며, 대안 중 하나라도 주목받게 된다면 저는 이것이 되기를 바랍니다.
super(*p, **kw)
super(*p, **kw)를 직접 호출하면 현재 실행 중인 메서드와 같은 이름의 메서드를 super 객체에서 호출하는 것과 동등하게 하자는 제안이 있었습니다. 즉, 다음 두 메서드는 동등합니다:
def f(self, *p, **kw):
super.f(*p, **kw)
def f(self, *p, **kw):
super(*p, **kw)
이에 대해서는 찬반 의견이 모두 강하지만, 구현과 스타일 측면의 우려는 분명합니다. Guido는 KISS(Keep It Simple Stupid) 원칙에 따라 이것을 이 PEP에서 제외해야 한다고 제안했습니다.
역사
- 29-Apr-2007
- 제목을 “키워드로서의 Super”에서 “새로운 Super”로 변경했습니다.
- 문구의 상당 부분을 수정하고, 혼동하기 쉬운 부분을 명확히 하기 위해 용어 섹션을 추가했습니다.
- 참조 구현 섹션과 이력 섹션을 추가했습니다.
- 06-May-2007
- python-3000 및 python-dev 메일링 리스트에서의 논의를 반영하여 Tim Delaney가 수정했습니다.
- 12-Mar-2009
- 현재 구현 상태를 반영하여 수정했습니다.
참고 문헌
[1] Fixing super anyone? (https://mail.python.org/pipermail/python-3000/2007-April/006667.html)
[2] PEP 3130: 현재 정의 중인 모듈/클래스/함수에 대한 접근 (this) (https://mail.python.org/pipermail/python-ideas/2007-April/000542.html)
Copyright
This document has been placed in the public domain.