python-peps/peps/pep-0351.rst

181 lines
5.0 KiB
ReStructuredText
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

PEP: 351
Title: The freeze protocol
Version: 2.5
Last-Modified: $Date$
Author: Barry Warsaw <barry@python.org>
Status: Rejected
Type: Standards Track
Content-Type: text/x-rst
Created: 14-Apr-2005
Post-History:
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.
Rejection Notice
================
This PEP was rejected. For a rationale, see `this thread on python-dev`_.
.. _this thread on python-dev: https://mail.python.org/pipermail/python-dev/2006-February/060793.html
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: