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

Python 개선 제안 한국어 번역

PEP 351 – 동결 프로토콜

Author:
Barry Warsaw <barry at python.org>
Status:
Rejected
Type:
Standards Track
Created:
14-Apr-2005
Python-Version:
2.5
Post-History:


Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 변경 가능한 객체의 동결된 불변 복사본을 요청하기 위한 간단한 프로토콜을 설명합니다. 또한 이 프로토콜을 사용하여 협조하는 모든 객체의 불변 복사본을 제공하는 새로운 내장 함수를 정의합니다.

거부 공지

이 PEP는 거부되었습니다. 근거는 this thread on python-dev를 참조하십시오.

근거

딕셔너리와 세트 같은 내장 객체는 불변 객체만 키로 허용합니다. 즉, 리스트와 같은 변경 가능한 객체는 딕셔너리의 키로 사용할 수 없습니다. 그러나 Python 프로그래머는 리스트를 튜플로 변환할 수 있습니다. 두 객체는 유사하지만 후자는 불변이며 딕셔너리 키로 사용할 수 있습니다.

서드 파티 객체에도 유사한 변경 가능 객체와 불변 객체의 대응물이 있을 수 있으며, 이러한 객체를 변환하기 위한 표준 프로토콜이 있으면 유용할 것입니다.

sets.Set 객체는 sets.Setsets.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__()로 이름을 바꿔야 합니까?