PEP 232 – 함수 속성
- Author:
- Barry Warsaw <barry at python.org>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 02-Dec-2000
- Python-Version:
- 2.1
- Post-History:
- 20-Feb-2001
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
소개
이 PEP는 함수와 메서드에 속성 딕셔너리를 추가하는 Python 확장을 설명합니다. 이 PEP는 이 기능의 상태와 소유권을 추적합니다. 이 PEP는 기능에 대한 설명을 담고 있으며, 이 기능을 지원하는 데 필요한 변경 사항을 개괄합니다. 이 PEP는 메일링 리스트 포럼에서 이루어진 논의를 요약하고, 적절한 경우 추가 정보를 얻을 수 있는 URL을 제공합니다. 이 파일의 CVS 리비전 이력에 확정적인 역사 기록이 담겨 있습니다.
배경
함수에는 이미 여러 속성이 있으며, 그중 일부는 쓰기가 가능합니다. 예를 들어 func.__doc__라고도 하는 func_doc이 그렇습니다. func_doc에는 흥미로운 특성이 있는데, 함수(및 메서드) 정의에 이 속성을 암묵적으로 설정하기 위한 특수 문법이 있다는 점입니다. 이 편리함은 거듭 활용되어 왔으며, 그 결과 독스트링에 부가적인 의미가 덧씌워졌습니다.
예를 들어 John Aycock은 독스트링을 사용해 파싱 규칙을 정의하는 시스템을 작성했습니다. [1] Zope의 ZPublisher ORB [2]는 독스트링을 사용해 공개 가능한 메서드, 즉 웹을 통해 호출할 수 있는 메서드임을 표시합니다.
이 접근 방식의 문제는 덧씌워진 의미들이 서로 충돌할 수 있다는 점입니다. 예를 들어 웹을 통해 공개되어서는 안 되는 Zope 메서드에 doctest 단위 테스트를 추가하려는 경우가 그렇습니다.
제안
이 제안은 함수 객체에 func_dict(일명 __dict__)라는 새 딕셔너리를 추가합니다. 이 딕셔너리는 일반적인 속성 설정 및 조회 문법을 사용하여 설정하고 조회할 수 있습니다.
메서드도 getter 문법을 얻게 되며, 현재 메서드는 내부 함수 객체의 딕셔너리를 통해 속성에 접근합니다. 바인드된 메서드나 언바운드 메서드에는 속성을 설정할 수 없으며, 기반 함수 객체에 명시적으로 설정하는 방법만 가능합니다. 이후 Python 버전에서 취할 수 있는 접근 방식에 대해서는 아래의 Future Directions 논의를 참조하십시오.
함수 객체의 __dict__도 설정할 수 있지만, 딕셔너리 객체로만 설정할 수 있습니다. 함수의 __dict__를 삭제하거나 구체적인 딕셔너리 객체가 아닌 다른 값으로 설정하면 TypeError가 발생합니다. 함수 속성이 한 번도 설정된 적이 없다면 함수의 __dict__는 비어 있습니다.
예시
다음은 이 기능으로 할 수 있는 일의 몇 가지 예입니다.
def a():
pass
a.publish = 1
a.unittest = '''...'''
if a.publish:
print a()
if hasattr(a, 'unittest'):
testframework.execute(a.unittest)
class C:
def a(self):
'just a docstring'
a.publish = 1
c = C()
if c.a.publish:
publish(c.a())
기타 용도
Paul Prescod는 python-dev thread에서 여러 가지 다른 용도를 열거했습니다.
향후 방향
다음은 고려할 만한 여러 향후 방향입니다. 이러한 아이디어를 채택하려면 이 PEP를 참조하는 새 PEP가 필요하며, 2.1 릴리스 이후의 Python 버전을 대상으로 해야 합니다.
- 이 PEP의 이전 버전에서는 언바운드 메서드에 대해 속성의 설정과 조회를 모두 허용했고, 바인드된 메서드에 대해서는 조회만 허용했습니다. 이 정책에서 여러 문제가 발견되었습니다.
메서드 속성이 기반 함수에 저장되었기 때문에, 이로 인해 예상치 못할 수 있는 여러 결과가 발생했습니다:
class C: def a(self): pass c1 = C() c2 = C() c1.a.publish = 1 # c2.a.publish would now be == 1 also!
c1에 바인딩된a를 변경하면c2에 바인딩된a도 함께 변경되었기 때문에, 바운드 메서드에 속성을 설정하는 것은 허용되지 않았습니다. 그러나 언바운드 메서드에 속성 설정을 허용하는 것조차도 모호한 점이 있습니다:class D(C): pass class E(C): pass D.a.publish = 1 # E.a.publish would now be == 1 also!
이러한 이유로, 현재 PEP는 바운드 메서드와 언바운드 메서드 어느 쪽에도 속성 설정을 허용하지 않지만, 양쪽 모두에서 속성을 가져오는 것은 허용합니다 – 두 경우 모두 내부 함수 객체에 있는 속성 값을 반환합니다.
향후 PEP에서는 특별한 명명 규칙을 사용하여 인스턴스나 클래스에 속성을 설정하는 방식으로 (바운드 또는 언바운드) 메서드 속성 설정을 구현하자고 제안할 수도 있습니다. 즉, 다음과 같습니다.:
class C: def a(self): pass C.a.publish = 1 C.__a_publish__ == 1 # true c = C() c.a.publish = 2 c.__a_publish__ == 2 # true d = C() d.__a_publish__ == 1 # true
이 경우 인스턴스에 대한 조회는 먼저 인스턴스의 딕셔너리를 살펴보고, 그다음 클래스의 딕셔너리를 조회하며, 마지막으로 함수 객체의 딕셔너리를 조회합니다.
- 현재 Python은 Python 함수(즉, 내장 함수가 아니라 Python으로 작성된 함수)에서만 함수 속성을 지원합니다. 그럴 만한 가치가 있다면, 내장 함수에 함수 속성을 추가하는 별도의 패치를 만들 수 있습니다.
__doc__은 현재 편리하게 설정할 수 있도록 문법적으로 지원되는 유일한 함수 속성입니다. 궁극적으로는 함수 속성을 쉽게 설정할 수 있도록 언어를 개선하는 것이 가치 있을 수도 있습니다. 다음은 PEP 검토자들이 제안한 몇 가지 문법입니다: [3]def a { 'publish' : 1, 'unittest': '''...''', } (args): # ... def a(args): """The usual docstring.""" {'publish' : 1, 'unittest': '''...''', # etc. } def a(args) having (publish = 1): # see reference [3] pass
BDFL은 현재 임의의 함수 속성을 설정하기 위한 이러한 특별한 문법 지원에 반대하고 있습니다. 문법에 관한 제안은 모두 새로운 PEP에서 제시되어야 합니다.
반대 의견
2000년 4월 python-dev 메일링 리스트에서 이 내용이 논의되었을 때, 여러 반대 의견이 제기되었습니다. 참고로, 해당 논의 스레드는 python-dev에서 시작합니다.
반대 측 인자는 다음 범주로 나뉘는 것으로 보입니다:
- 명확한 목적이 없음 (이것으로 무엇을 얻을 수 있는가?)
- 다른 방법이 있음 (예: 클래스 속성으로서의 매핑)
- 문법 지원이 포함되기 전까지는 쓸모없음
이러한 인자 중 일부에 대한 반론으로, 기본 Python 2.0에서도 사실 __doc__을 어떤 타입의 객체로든 설정할 수 있으므로 쓰기 가능한 함수 속성과 비슷한 것이 이미 가능하다는 점이 있습니다. 하지만 그 방식은 __doc__을 또 한 번 오용하는 것입니다.
또한 클래스 객체에 (함수 속성의 경우에는 함수의 모듈에) 매핑을 추가하는 것은 물론 가능하지만, 검사를 위해 속성 값을 추출하는 방법은 더 어렵고 덜 명확합니다.
마지막으로, __doc__ 문법 지원이 존재하는 것과 거의 같은 방식으로 문법 지원을 추가하는 것이 바람직할 수도 있습니다. 이는 함수 속성을 실제로 설정하고 가져오는 기능과는 별개로 검토할 수 있습니다.
참조 구현
이 PEP는 수락되었으며 구현이 Python 2.1에 통합되었습니다.
참고 문헌
Copyright
This document has been placed in the public domain.