Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

근거

Python의 인트로스펙션 기능은 오랫동안 중첩 클래스를 제대로 지원하지 못했습니다. 클래스 객체가 주어졌을 때, 그 클래스가 다른 클래스 안에서 정의되었는지 모듈 최상위 수준에서 정의되었는지 알 수 없으며, 전자라면 어느 클래스 안에서 정의되었는지도 알 수 없습니다. 중첩 클래스의 사용은 흔히 좋지 않은 스타일로 여겨지지만, 그렇다고 중첩 클래스가 이류(second class) 인트로스펙션 지원을 받아야 할 이유는 형편없는 말장난 말고는 없습니다.

Python 3는 이전에 언바운드 메서드(unbound method)라고 불리던 것을 없애 버림으로써 설상가상의 상황을 만듭니다. 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가 해결하는 문제 중 일부만 해결할 수 있으며, 그 대가도 더 큽니다(속성 하나를 추가하는 대신 객체 타입 하나와 간접 참조 단계 하나가 추가됩니다).

이름 선택

“정규화된 이름(qualified name)”은 이 추가 속성이 무엇인지를 짧은 구절로 가장 가깝게 나타내는 표현입니다. 이 이름은 (의도적으로) 모듈 이름을 포함하지 않으므로 “전체 이름(full name)”이나 “완전히 정규화된 이름(fully qualified name)”이 아닙니다. 이를 “경로(path)”라고 부르면 파일 시스템 경로 및 __file__ 속성과 혼동될 위험이 있습니다.

속성 이름에 대한 첫 제안은 __qname__이라고 부르는 것이었지만, (예를 들어 XML 명세 [2] 등에서 이러한 전문 용어가 이전에 쓰였다는 것을 모르는) 많은 사람이 이 이름을 모호하고 직관적이지 않다고 여겼습니다. 이 때문에 조금 덜 짧지만 더 명시적인 __qualname__이 최종적으로 선택되었습니다.

참고 문헌