[Rejected] PEP 231 - findattr()

원문 링크: PEP 231 - findattr()

상태: Rejected 유형: Standards Track 작성일: 30-Nov-2000

PEP 231 – __findattr__()에 대한 번역 및 요약

상태: Rejected (거부됨) 작성자: Barry Warsaw 생성일: 2000년 11월 30일 Python 버전: 2.1

소개

PEP 231은 Python 인스턴스의 속성 조회(lookup) 및 수정 메커니즘을 확장하는 제안으로, 순수 Python만으로 다양한 흥미로운 프로그래밍 모델을 구현할 수 있도록 하는 것을 목표로 했습니다. 이 제안은 __findattr__()이라는 새로운 특수 메서드를 도입하여 기존 __getattr__()__setattr__()의 제한 사항을 해결하고자 했습니다.

배경

Python은 __getattr__()__setattr__()과 같은 특수 메서드를 통해 속성 접근을 사용자 정의할 수 있는 기능을 제공합니다. 그러나 이러한 메서드에는 특정 제한 사항이 있어, 엄격한 Java Bean과 유사한 인터페이스나 Zope 스타일의 Acquisition과 같은 특정 프로그래밍 기법을 순수 Python만으로는 구현하기 어려웠습니다. 예를 들어 Zope는 ExtensionClass라는 C 확장과 Python의 메타클래스 훅을 사용하여 이 문제를 해결했지만, 이는 C 확장을 필요로 하고 Python의 내부 메커니즘에 의존하며 이해하고 사용하기 어렵다는 단점이 있었습니다. 이 PEP는 “클래스/타입 이분법(class/type dichotomy)” 문제를 해결하는 것과는 별개로, 최소한의 수정으로 위와 같은 프로그래밍 구성을 가능하게 하는 80% 솔루션을 제공하고자 했습니다.

제안 내용

이 PEP는 다음과 같은 의미를 갖는 __findattr__()이라는 새로운 특수 메서드를 추가할 것을 제안했습니다.

  • 클래스에 __findattr__()이 정의되면, 모든 인스턴스 속성 해석 시 __getattr__()__setattr__() 대신 호출됩니다.
  • __findattr__()은 재귀적으로 호출되지 않습니다. 즉, 특정 인스턴스의 __findattr__()이 호출 스택에 있는 동안, 해당 인스턴스의 추가 속성 접근은 표준 __getattr__()__setattr__() 메서드를 사용합니다.
  • __findattr__()은 속성 접근(‘getting’) 및 속성 수정(‘setting’) 모두에 대해 호출됩니다. 속성 삭제(deletion)에 대해서는 호출되지 않습니다.
  • ‘getting’을 위해 호출될 때는 하나의 인자(self 제외)로 접근하려는 속성의 이름이 전달됩니다. ‘setting’을 위해 호출될 때는 세 번째 인자로 설정할 값이 전달됩니다.
  • __findattr__() 메서드는 __getattr__()__setattr__()과 동일한 캐싱(caching) 의미를 가집니다. 즉, 클래스 정의 시점에 클래스에 존재하면 사용되지만, 나중에 클래스에 추가되면 사용되지 않습니다.

기존 프로토콜과의 주요 차이점

__findattr__()의 의미론은 기존 __getattr__()__setattr__() 프로토콜과 다음과 같은 주요 차이점을 가집니다.

  • __getattr__()의 한계: __getattr__()은 속성이 인스턴스의 __dict__에 존재하면 호출되지 않습니다. 이는 효율성 때문이기도 하지만, __setattr__()이 인스턴스의 속성에 접근할 방법이 없어 재귀 호출을 방지하기 위함이었습니다.
  • __setattr__()의 한계: __setattr__()은 “self.name = foo”와 같은 “일반적인” 구문을 사용하여 인스턴스 속성을 설정할 수 없었습니다. 이렇게 하면 __setattr__()이 재귀적으로 호출되기 때문입니다.
  • __findattr__()의 동작: __findattr__()은 속성이 __dict__에 있든 없든 항상 호출됩니다. 그리고 인스턴스 객체 내부의 플래그(flag)가 __findattr__()의 재귀 호출을 방지합니다. 이를 통해 클래스는 모든 속성 접근에 대해 어떤 동작을 수행할 기회를 가질 수 있으며, ‘get’과 ‘set’ 모두에 대해 호출되므로 모든 속성 접근에 대해 유사한 정책을 쉽게 작성할 수 있습니다. 효율성 문제는 확장된 메커니즘이 사용될 때만 비용이 발생하므로 크게 문제되지 않습니다.

예시

이 제안은 Java Bean과 유사한 객체 인터페이스 구현을 허용하여, 꾸밈없는 속성 접근 및 수정이 함수형 인터페이스로 투명하게 매핑될 수 있도록 합니다. 또한, 순수 Python으로 암시적(implicit) 및 명시적(explicit) Acquisition을 구현하는 복잡한 예시와, C++와 유사한 접근 제어를 구현하는 예시도 제시되었습니다.

거부 (Rejection)

PEP 231은 최종적으로 거부되었습니다. 주된 거부 이유는 다음과 같습니다.

  • 재귀 방지 기능의 문제: 재귀 방지 기능에 심각한 문제가 있었습니다. 제안된 방식으로는 스레드 안전(thread-safe)하지 않았으며, 스레드 안전한 해결책은 다른 문제를 야기했습니다. __findattr__ 내부와 외부에서 모두 호출되어야 하는 코드를 작성하기 어렵게 만드는 등, 재귀 방지 기능의 유용성 자체가 명확하지 않았습니다. 반대로 재귀 방지 기능이 없으면 __findattr__이 자기 자신을 재귀적으로 호출하게 되어 구현하기 어려워집니다.
  • __getattr____setattr__의 충분성: 속성 ‘getting’과 ‘setting’ 모두에 대해 __findattr__을 지원하는 것이 얼마나 유용한지에 대한 의문이 있었습니다. __setattr__은 이미 모든 경우에 호출되고 있었습니다.
  • 대체 구현 가능성: 제안된 예시들은 인스턴스 변수를 자체 이름으로 저장하지 않도록 주의를 기울이면 기존 __getattr__을 사용하여 모두 구현할 수 있었습니다.

결론적으로, __findattr__()의 재귀 방지 메커니즘에 대한 적절한 해결책을 찾기 어려웠고, 기존 __getattr__()__setattr__()로도 제안된 대부분의 기능을 구현할 수 있다는 점 때문에 PEP 231은 거부되었습니다.

⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.

Comments