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

Python 개선 제안 한국어 번역

PEP 351 – freeze 프로토콜

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.Set으로 이루어진 sets.Set을 만들 수 있습니다. PEP 218은 내장 집합에서 이 기능을 의도적으로 제외했습니다. 이 PEP는 이 기능이 여전히 유용하다고 주장하며, 이를 지원하는 표준 메커니즘을 제안합니다.

제안

freeze()라는 새 내장 함수를 추가할 것을 제안합니다.

freeze()에 불변 객체가 전달되면(해당 객체에 대한 hash()가 TypeError를 발생시키지 않는지로 판단합니다), 그 객체를 그대로 반환합니다.

freeze()에 가변 객체가 전달되면(즉, 해당 객체의 hash()가 TypeError를 발생시키면), freeze()는 그 객체의 __freeze__() 메서드를 호출해 불변 복사본을 얻습니다. 객체에 __freeze__() 메서드가 없으면 TypeError가 발생합니다.

샘플 구현

다음은 freeze() 내장 함수의 Python 구현입니다:

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__() 메서드 구현도 함께 추가합니다. 현재 Python에서는 딕셔너리를 동결하기가 쉽지 않으므로 dict.__freeze__() 구현은 아직 제공하지 않습니다.

미해결 문제

  • 동결된 객체를 해동하는 비슷한 프로토콜도 정의해야 합니까?
  • 딕셔너리와 집합이 가변 키를 자동으로 동결해야 합니까?
  • sets.Set의 __as_temporarily_immutable__()처럼 “임시 동결”(아마도 __congeal__()이라는 메서드로)을 지원해야 합니까?
  • sets.Set과의 하위 호환성을 위해 __as_immutable__()을 지원해야 합니까? 아니면 __freeze__()의 이름을 __as_immutable__()로 바꾸기만 하면 됩니까?