PEP 351 – 동결 프로토콜
- Author:
- Barry Warsaw <barry at python.org>
- Status:
- Rejected
- Type:
- Standards Track
- Created:
- 14-Apr-2005
- Python-Version:
- 2.5
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 변경 가능한 객체의 동결된 불변 복사본을 요청하기 위한 간단한 프로토콜을 설명합니다. 또한 이 프로토콜을 사용하여 협조하는 모든 객체의 불변 복사본을 제공하는 새로운 내장 함수를 정의합니다.
거부 공지
이 PEP는 거부되었습니다. 근거는 this thread on python-dev를 참조하십시오.
근거
딕셔너리와 세트 같은 내장 객체는 불변 객체만 키로 허용합니다. 즉, 리스트와 같은 변경 가능한 객체는 딕셔너리의 키로 사용할 수 없습니다. 그러나 Python 프로그래머는 리스트를 튜플로 변환할 수 있습니다. 두 객체는 유사하지만 후자는 불변이며 딕셔너리 키로 사용할 수 있습니다.
서드 파티 객체에도 유사한 변경 가능 객체와 불변 객체의 대응물이 있을 수 있으며, 이러한 객체를 변환하기 위한 표준 프로토콜이 있으면 유용할 것입니다.
sets.Set 객체는 sets.Set의 sets.Set들을 생성할 수 있도록 “불변으로 자동 변환하기 위한 프로토콜”을 노출합니다. PEP 218은 이 기능을 내장 세트에서 의도적으로 제외했습니다. 이 PEP는 이 기능이 여전히 유용하다고 주장하며 이를 지원하기 위한 표준 메커니즘을 제안합니다.
제안
freeze()라는 새로운 내장 함수를 추가할 것을 제안합니다.
freeze()에 불변 객체가 전달되면(해당 객체에 대한 hash()가 TypeError를 발생시키지 않는 것으로 판단), 그 객체가 직접 반환됩니다.
freeze()에 가변 객체가 전달되면(즉 해당 객체의 hash()가 TypeError를 발생시키면), freeze()는 그 객체의 __freeze__() 메서드를 호출하여 불변 복사본을 얻습니다. 객체에 __freeze__() 메서드가 없으면 TypeError가 발생합니다.
구현 예시
다음은 내장 함수 freeze()의 파이썬 구현입니다:
def freeze(obj):
try:
hash(obj)
return obj
except TypeError:
freezer = getattr(obj, '__freeze__', None)
if freezer:
return freezer()
raise TypeError('object is not freezable')
의도된 시맨틱을 보여주는 코드 예시는 다음과 같습니다:
class xset(set):
def __freeze__(self):
return frozenset(self)
class xlist(list):
def __freeze__(self):
return tuple(self)
class imdict(dict):
def __hash__(self):
return id(self)
def _immutable(self, *args, **kws):
raise TypeError('object is immutable')
__setitem__ = _immutable
__delitem__ = _immutable
clear = _immutable
update = _immutable
setdefault = _immutable
pop = _immutable
popitem = _immutable
class xdict(dict):
def __freeze__(self):
return imdict(self)
>>> s = set([1, 2, 3])
>>> {s: 4}
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: set objects are unhashable
>>> t = freeze(s)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/tmp/python-lWCjBK.py", line 9, in freeze
TypeError: object is not freezable
>>> t = xset(s)
>>> u = freeze(t)
>>> {u: 4}
{frozenset([1, 2, 3]): 4}
>>> x = 'hello'
>>> freeze(x) is x
True
>>> d = xdict(a=7, b=8, c=9)
>>> hash(d)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: dict objects are unhashable
>>> hash(freeze(d))
-1210776116
>>> {d: 4}
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: dict objects are unhashable
>>> {freeze(d): 4}
{{'a': 7, 'c': 9, 'b': 8}: 4}
참조 구현
패치 1335812는 이 기능의 C 구현을 제공합니다. 이 패치는 내장 함수 freeze()와 함께 리스트와 세트에 대한 __freeze__() 메서드 구현을 추가합니다. 현재 파이썬에서 딕셔너리는 쉽게 동결할 수 없으므로, dict.__freeze__()의 구현은 아직 제공되지 않습니다.
미해결 문제
- 동결된 객체를 해동하기 위한 유사한 프로토콜을 정의해야 합니까?
- 딕셔너리와 세트가 가변 키를 자동으로 동결해야 합니까?
sets.Set의__as_temporarily_immutable__()처럼 “임시 동결”(아마도__congeal__()이라는 메서드를 통해)을 지원해야 합니까?sets.Set과의 하위 호환성을 위해__as_immutable__()을 지원해야 합니까? 아니면__freeze__()를 그냥__as_immutable__()로 이름을 바꿔야 합니까?
Copyright
This document has been placed in the public domain.