PEP 351, the freeze protocol.

This commit is contained in:
Barry Warsaw 2005-10-23 22:39:17 +00:00
parent 28b01bed0e
commit 9c2d269ad4
2 changed files with 172 additions and 0 deletions

View File

@ -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

170
pep-0351.txt Normal file
View File

@ -0,0 +1,170 @@
PEP: 351
Title: The freeze protocol
Version: 2.5
Author: Barry A. Warsaw <barry@python.org>
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 "<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}
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: