PEP 3155 – 클래스와 함수의 정규화된 이름
- Author:
- Antoine Pitrou <solipsis at pitrou.net>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 29-Oct-2011
- Python-Version:
- 3.3
- Post-History:
- Resolution:
- Python-Dev message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
근거
Python의 인트로스펙션 기능은 오랫동안 중첩 클래스에 대한 지원이 부족했습니다. 클래스 객체가 주어졌을 때, 해당 객체가 다른 클래스 내부에 정의되었는지 모듈 최상위 수준에 정의되었는지 알 수 없으며, 전자의 경우에는 어느 클래스에 정의되었는지도 알 수 없습니다. 중첩 클래스의 사용은 흔히 좋지 않은 스타일로 간주되지만, 중첩 클래스에 2류 인트로스펙션 지원만 제공해야 할 유일한 이유는 형편없는 말장난 때문입니다.
Python 3은 이전에 바인딩되지 않은 메서드라고 불리던 것을 제거하여 엎친 데 덮친 격으로 만들었습니다. Python 2에서는 다음 정의가 주어졌을 때:
class C:
def f():
pass
C.f 객체에서 해당 객체를 정의한 클래스로 거슬러 올라갈 수 있습니다.:
>>> C.f.im_class
<class '__main__.C'>
Python 3에서는 이러한 가능성이 사라졌습니다.:
>>> C.f.im_class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'im_class'
>>> dir(C.f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__',
'__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__get__', '__getattribute__',
'__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__',
'__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__']
이로 인해 사용자가 이용할 수 있는 인트로스펙션 기능이 다시 제한됩니다. 소프트웨어를 Python 3으로 포팅할 때 실제 문제가 발생할 수 있으며, 예를 들어 메서드 객체의 인트로스펙션 문제가 여러 차례 제기된 Twisted Core가 있습니다. 피클링 지원도 제한됩니다 [1].
제안
이 PEP에서는 함수와 클래스에 __qualname__속성을 추가할 것을 제안합니다. 최상위 함수와 클래스의 경우 __qualname__속성은 __name__속성과 같습니다. 중첩 클래스, 메서드 및 중첩 함수의 경우 __qualname__속성은 모듈 최상위 수준에서 해당 객체로 이어지는 점으로 구분된 경로를 포함합니다. 함수의 로컬 네임스페이스는 해당 점으로 구분된 경로에서 <locals>라는 이름의 구성 요소로 표현됩니다.
함수와 클래스의 repr() 및 str()은 __name__대신 __qualname__을 사용하도록 수정됩니다.
중첩 클래스 예제
>>> class C:
... def f(): pass
... class D:
... def g(): pass
...
>>> C.__qualname__
'C'
>>> C.f.__qualname__
'C.f'
>>> C.D.__qualname__
'C.D'
>>> C.D.g.__qualname__
'C.D.g'
중첩 함수 예제
>>> def f():
... def g(): pass
... return g
...
>>> f.__qualname__
'f'
>>> f().__qualname__
'f.<locals>.g'
제한 사항
중첩 함수와 함수 내부에 정의된 클래스의 경우, 함수의 네임스페이스를 외부에서 사용할 수 없으므로 점으로 구분된 경로를 프로그래밍 방식으로 따라갈 수 없습니다. 그래도 단순한 __name__보다 사람에게는 더 유용합니다.
__name__속성과 마찬가지로 __qualname__속성은 정적으로 계산되며 재바인딩을 자동으로 따르지 않습니다.
논의
모듈 이름 제외
__name__과 마찬가지로 __qualname__에는 모듈 이름이 포함되지 않습니다. 따라서 모듈 별칭 지정 및 재바인딩과 독립적이며, 컴파일 시간에 계산할 수도 있습니다.
바인딩되지 않은 메서드의 부활
바인딩되지 않은 메서드를 부활시키면 이 PEP가 해결하는 문제의 일부만 더 높은 비용으로 해결할 수 있습니다. 즉, 추가 속성 하나가 아니라 추가 객체 유형과 추가 간접 참조가 필요합니다.
이름 지정 선택
“정규화된 이름”은 추가 속성이 무엇에 관한 것인지를 짧은 표현으로 나타내는 가장 적절한 근사입니다. 이는 “전체 이름”이나 “완전 정규화된 이름”이 아닙니다. (의도적으로) 모듈 이름을 포함하지 않기 때문입니다. 이를 “경로”라고 부르면 파일 시스템 경로 및 __file__ 속성과 혼동될 위험이 있습니다.
속성 이름에 대한 최초의 제안은 이를 __qname__이라고 부르는 것이었지만, (예를 들어 XML 사양 [2]에서 이러한 용어가 이전에 사용된 것을 알지 못하는) 많은 사람이 이를 모호하고 쉽게 이해할 수 없다고 여겼으며, 이것이 최종적으로 조금 덜 짧지만 더 명시적인 __qualname__이 선택된 이유입니다.
참고 문헌
Copyright
This document has been placed in the public domain.