python-peps/pep-0351/index.html

274 lines
14 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 351 The freeze protocol | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0351/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 351 The freeze protocol | peps.python.org'>
<meta property="og:description" content="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.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0351/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="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.">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 351</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 351 The freeze protocol</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Barry Warsaw &lt;barry&#32;&#97;t&#32;python.org&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">14-Apr-2005</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#sample-implementations">Sample implementations</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>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.</p>
</section>
<section id="rejection-notice">
<h2><a class="toc-backref" href="#rejection-notice" role="doc-backlink">Rejection Notice</a></h2>
<p>This PEP was rejected. For a rationale, see <a class="reference external" href="https://mail.python.org/pipermail/python-dev/2006-February/060793.html">this thread on python-dev</a>.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>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.</p>
<p>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.</p>
<p>sets.Set objects expose a “protocol for automatic conversion to
immutable” so that you can create sets.Sets of sets.Sets. <a class="pep reference internal" href="../pep-0218/" title="PEP 218 Adding a Built-In Set Object Type">PEP 218</a>
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.</p>
</section>
<section id="proposal">
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
<p>It is proposed that a new built-in function called freeze() is added.</p>
<p>If freeze() is passed an immutable object, as determined by hash() on
that object not raising a TypeError, then the object is returned
directly.</p>
<p>If freeze() is passed a mutable object (i.e. hash() of that object
raises a TypeError), then freeze() will call that objects
__freeze__() method to get an immutable copy. If the object does not
have a __freeze__() method, then a TypeError is raised.</p>
</section>
<section id="sample-implementations">
<h2><a class="toc-backref" href="#sample-implementations" role="doc-backlink">Sample implementations</a></h2>
<p>Here is a Python implementation of the freeze() built-in:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>def freeze(obj):
try:
hash(obj)
return obj
except TypeError:
freezer = getattr(obj, &#39;__freeze__&#39;, None)
if freezer:
return freezer()
raise TypeError(&#39;object is not freezable&#39;)``
</pre></div>
</div>
<p>Here are some code samples which show the intended semantics:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>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(&#39;object is immutable&#39;)
__setitem__ = _immutable
__delitem__ = _immutable
clear = _immutable
update = _immutable
setdefault = _immutable
pop = _immutable
popitem = _immutable
class xdict(dict):
def __freeze__(self):
return imdict(self)
&gt;&gt;&gt; s = set([1, 2, 3])
&gt;&gt;&gt; {s: 4}
Traceback (most recent call last):
File &quot;&lt;stdin&gt;&quot;, line 1, in ?
TypeError: set objects are unhashable
&gt;&gt;&gt; t = freeze(s)
Traceback (most recent call last):
File &quot;&lt;stdin&gt;&quot;, line 1, in ?
File &quot;/usr/tmp/python-lWCjBK.py&quot;, line 9, in freeze
TypeError: object is not freezable
&gt;&gt;&gt; t = xset(s)
&gt;&gt;&gt; u = freeze(t)
&gt;&gt;&gt; {u: 4}
{frozenset([1, 2, 3]): 4}
&gt;&gt;&gt; x = &#39;hello&#39;
&gt;&gt;&gt; freeze(x) is x
True
&gt;&gt;&gt; d = xdict(a=7, b=8, c=9)
&gt;&gt;&gt; hash(d)
Traceback (most recent call last):
File &quot;&lt;stdin&gt;&quot;, line 1, in ?
TypeError: dict objects are unhashable
&gt;&gt;&gt; hash(freeze(d))
-1210776116
&gt;&gt;&gt; {d: 4}
Traceback (most recent call last):
File &quot;&lt;stdin&gt;&quot;, line 1, in ?
TypeError: dict objects are unhashable
&gt;&gt;&gt; {freeze(d): 4}
{{&#39;a&#39;: 7, &#39;c&#39;: 9, &#39;b&#39;: 8}: 4}
</pre></div>
</div>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference implementation</a></h2>
<p>Patch <a class="reference external" href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1335812&amp;group_id=5470&amp;atid=305470">1335812</a> 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.</p>
</section>
<section id="open-issues">
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open issues</a></h2>
<ul class="simple">
<li>Should we define a similar protocol for thawing frozen objects?</li>
<li>Should dicts and sets automatically freeze their mutable keys?</li>
<li>Should we support “temporary freezing” (perhaps with a method called
__congeal__()) a la __as_temporarily_immutable__() in sets.Set?</li>
<li>For backward compatibility with sets.Set, should we support
__as_immutable__()? Or should __freeze__() just be renamed to
__as_immutable__()?</li>
</ul>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0351.rst">https://github.com/python/peps/blob/main/peps/pep-0351.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0351.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#proposal">Proposal</a></li>
<li><a class="reference internal" href="#sample-implementations">Sample implementations</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference implementation</a></li>
<li><a class="reference internal" href="#open-issues">Open issues</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0351.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>