From 9c2d269ad4fddf000f60e1db7795e95382fa93d0 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sun, 23 Oct 2005 22:39:17 +0000 Subject: [PATCH] PEP 351, the freeze protocol. --- pep-0000.txt | 2 + pep-0351.txt | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 pep-0351.txt diff --git a/pep-0000.txt b/pep-0000.txt index 500b4e9a3..0a07dd4bf 100644 --- a/pep-0000.txt +++ b/pep-0000.txt @@ -106,6 +106,7 @@ Index by Category P 347 Migrating the Python CVS to Subversion von Löwis S 349 Allow str() to return unicode strings Schemenauer I 350 Codetags Elliott + S 351 The freeze protocol Warsaw S 754 IEEE 754 Floating Point Special Values Warnes Finished PEPs (done, implemented in CVS) @@ -396,6 +397,7 @@ Numerical Index SR 348 Exception Reorganization for Python 3.0 Cannon S 349 Allow str() to return unicode strings Schemenauer I 350 Codetags Elliott + S 351 The freeze protocol Warsaw SR 666 Reject Foolish Indentation Creighton S 754 IEEE 754 Floating Point Special Values Warnes I 3000 Python 3.0 Plans Kuchling, Cannon diff --git a/pep-0351.txt b/pep-0351.txt new file mode 100644 index 000000000..532655606 --- /dev/null +++ b/pep-0351.txt @@ -0,0 +1,170 @@ +PEP: 351 +Title: The freeze protocol +Version: 2.5 +Author: Barry A. Warsaw +Status: Active +Type: Standards Track +Content-Type: text/x-rst +Created: 14-Apr-2005 + + +Abstract +======== + +This PEP describes a simple protocol for requesting a frozen, +immutable copy of a mutable object. It also defines a new built-in +function which uses this protocol to provide an immutable copy on any +cooperating object. + + +Rationale +========= + +Built-in objects such dictionaries and sets accept only immutable +objects as keys. This means that mutable objects like lists cannot be +used as keys to a dictionary. However, a Python programmer can +convert a list to a tuple; the two objects are similar, but the latter +is immutable, and can be used as a dictionary key. + +It is conceivable that third party objects also have similar mutable +and immutable counterparts, and it would be useful to have a standard +protocol for conversion of such objects. + +sets.Set objects expose a "protocol for automatic conversion to +immutable" so that you can create sets.Sets of sets.Sets. PEP 218 +deliberately dropped this feature from built-in sets. This PEP +advances that the feature is still useful and proposes a standard +mechanism for its support. + + +Proposal +======== + +It is proposed that a new built-in function called freeze() is added. + +If freeze() is passed an immutable object, as determined by hash() on +that object not raising a TypeError, then the object is returned +directly. + +If freeze() is passed a mutable object (i.e. hash() of that object +raises a TypeError), then freeze() will call that object's +__freeze__() method to get an immutable copy. If the object does not +have a __freeze__() method, then a TypeError is raised. + + +Sample implementations +====================== + +Here is a Python implementation of the freeze() built-in:: + + 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')`` + +Here are some code samples which show the intended semantics:: + + 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 "", line 1, in ? + TypeError: set objects are unhashable + >>> t = freeze(s) + Traceback (most recent call last): + File "", 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 "", line 1, in ? + TypeError: dict objects are unhashable + >>> hash(freeze(d)) + -1210776116 + >>> {d: 4} + Traceback (most recent call last): + File "", line 1, in ? + TypeError: dict objects are unhashable + >>> {freeze(d): 4} + {{'a': 7, 'c': 9, 'b': 8}: 4} + + +Reference implementation +======================== + +Patch 1335812_ provides the C implementation of this feature. It adds the +freeze() built-in, along with implementations of the __freeze__() +method for lists and sets. Dictionaries are not easily freezable in +current Python, so an implementation of dict.__freeze__() is not +provided yet. + +.. _1335812: http://sourceforge.net/tracker/index.php?func=detail&aid=1335812&group_id=5470&atid=305470 + +Open issues +=========== + +- Should we define a similar protocol for thawing frozen objects? + +- Should dicts and sets automatically freeze their mutable keys? + +- Should we support "temporary freezing" (perhaps with a method called + __congeal__()) a la __as_temporarily_immutable__() in sets.Set? + +- For backward compatibility with sets.Set, should we support + __as_immutable__()? Or should __freeze__() just be renamed to + __as_immutable__()? + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + End: