python-peps/pep-0455/index.html

415 lines
31 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 455 Adding a key-transforming dictionary to collections | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0455/">
<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 455 Adding a key-transforming dictionary to collections | peps.python.org'>
<meta property="og:description" content="This PEP proposes a new data structure for the collections module, called “TransformDict” in this PEP. This structure is a mutable mapping which transforms the key using a given function when doing a lookup, but retains the original key when reading.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0455/">
<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 proposes a new data structure for the collections module, called “TransformDict” in this PEP. This structure is a mutable mapping which transforms the key using a given function when doing a lookup, but retains the original key when reading.">
<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 455</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 455 Adding a key-transforming dictionary to collections</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Antoine Pitrou &lt;solipsis&#32;&#97;t&#32;pitrou.net&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Raymond Hettinger</dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-even">Type<span class="colon">:</span></dt>
<dd class="field-even"><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-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">13-Sep-2013</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">3.5</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><ul>
<li><a class="reference internal" href="#rejection">Rejection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a><ul>
<li><a class="reference internal" href="#constructor">Constructor</a></li>
<li><a class="reference internal" href="#getting-the-original-key">Getting the original key</a></li>
<li><a class="reference internal" href="#getting-the-transformation-function">Getting the transformation function</a></li>
</ul>
</li>
<li><a class="reference internal" href="#alternative-proposals-and-questions">Alternative proposals and questions</a><ul>
<li><a class="reference internal" href="#retaining-the-last-original-key">Retaining the last original key</a></li>
<li><a class="reference internal" href="#using-an-encoder-decoder-pair">Using an encoder / decoder pair</a></li>
<li><a class="reference internal" href="#providing-a-transformation-function-for-values">Providing a transformation function for values</a></li>
<li><a class="reference internal" href="#providing-a-specialized-container-not-generic">Providing a specialized container, not generic</a></li>
<li><a class="reference internal" href="#other-constructor-patterns">Other constructor patterns</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#existing-work">Existing work</a><ul>
<li><a class="reference internal" href="#other-languages">Other languages</a><ul>
<li><a class="reference internal" href="#c-net">C# / .Net</a></li>
<li><a class="reference internal" href="#java">Java</a></li>
<li><a class="reference internal" href="#c">C++</a></li>
</ul>
</li>
</ul>
</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 proposes a new data structure for the <code class="docutils literal notranslate"><span class="pre">collections</span></code> module,
called “TransformDict” in this PEP. This structure is a mutable mapping
which transforms the key using a given function when doing a lookup, but
retains the original key when reading.</p>
<section id="rejection">
<h3><a class="toc-backref" href="#rejection" role="doc-backlink">Rejection</a></h3>
<p>See the rationale at
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-May/140003.html">https://mail.python.org/pipermail/python-dev/2015-May/140003.html</a>
and for an earlier partial review, see
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2013-October/129937.html">https://mail.python.org/pipermail/python-dev/2013-October/129937.html</a> .</p>
</section>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Numerous specialized versions of this pattern exist. The most common
is a case-insensitive case-preserving dict, i.e. a dict-like container
which matches keys in a case-insensitive fashion but retains the original
casing. It is a very common need in network programming, as many
protocols feature some arrays of “key / value” properties in their
messages, where the keys are textual strings whose case is specified to
be ignored on receipt but by either specification or custom is to be
preserved or non-trivially canonicalized when retransmitted.</p>
<p>Another common request is an identity dict, where keys are matched
according to their respective id()s instead of normal matching.</p>
<p>Both are instances of a more general pattern, where a given transformation
function is applied to keys when looking them up: that function being
<code class="docutils literal notranslate"><span class="pre">str.lower</span></code> or <code class="docutils literal notranslate"><span class="pre">str.casefold</span></code> in the former example and the built-in
<code class="docutils literal notranslate"><span class="pre">id</span></code> function in the latter.</p>
<p>(It could be said that the pattern <em>projects</em> keys from the user-visible
set onto the internal lookup set.)</p>
</section>
<section id="semantics">
<h2><a class="toc-backref" href="#semantics" role="doc-backlink">Semantics</a></h2>
<p>TransformDict is a <code class="docutils literal notranslate"><span class="pre">MutableMapping</span></code> implementation: it faithfully
implements the well-known API of mutable mappings, like <code class="docutils literal notranslate"><span class="pre">dict</span></code> itself
and other dict-like classes in the standard library. Therefore, this PEP
wont rehash the semantics of most TransformDict methods.</p>
<p>The transformation function neednt be bijective, it can be strictly
surjective as in the case-insensitive example (in other words, different
keys can lookup the same value):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">TransformDict</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">casefold</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s1">&#39;SomeKey&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s1">&#39;somekey&#39;</span><span class="p">]</span>
<span class="go">5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s1">&#39;SOMEKEY&#39;</span><span class="p">]</span>
<span class="go">5</span>
</pre></div>
</div>
<p>TransformDict retains the first key used when creating an entry:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">TransformDict</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">casefold</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s1">&#39;SomeKey&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="s1">&#39;somekey&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
<span class="go">[(&#39;SomeKey&#39;, 2)]</span>
</pre></div>
</div>
<p>The original keys neednt be hashable, as long as the transformation
function returns a hashable one:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">TransformDict</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">l</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="n">l</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">l</span> <span class="ow">in</span> <span class="n">d</span>
<span class="go">True</span>
</pre></div>
</div>
<section id="constructor">
<h3><a class="toc-backref" href="#constructor" role="doc-backlink">Constructor</a></h3>
<p>As shown in the examples above, creating a TransformDict requires passing
the key transformation function as the first argument (much like creating
a <code class="docutils literal notranslate"><span class="pre">defaultdict</span></code> requires passing the factory function as first argument).</p>
<p>The constructor also takes other optional arguments which can be used
to initialize the TransformDict with certain key-value pairs. Those
optional arguments are the same as in the <code class="docutils literal notranslate"><span class="pre">dict</span></code> and <code class="docutils literal notranslate"><span class="pre">defaultdict</span></code>
constructors:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">TransformDict</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">casefold</span><span class="p">,</span> <span class="p">[(</span><span class="s1">&#39;Foo&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)],</span> <span class="n">Bar</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">d</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
<span class="go">[(&#39;Bar&#39;, 2), (&#39;Foo&#39;, 1)]</span>
</pre></div>
</div>
</section>
<section id="getting-the-original-key">
<h3><a class="toc-backref" href="#getting-the-original-key" role="doc-backlink">Getting the original key</a></h3>
<p>TransformDict also features a lookup method returning the stored key
together with the corresponding value:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="n">TransformDict</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">casefold</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;Foo&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">getitem</span><span class="p">(</span><span class="s1">&#39;FOO&#39;</span><span class="p">)</span>
<span class="go">(&#39;Foo&#39;, 1)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="o">.</span><span class="n">getitem</span><span class="p">(</span><span class="s1">&#39;bar&#39;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">KeyError</span>: <span class="n">&#39;bar&#39;</span>
</pre></div>
</div>
<p>The method name <code class="docutils literal notranslate"><span class="pre">getitem()</span></code> follows the standard <code class="docutils literal notranslate"><span class="pre">popitem()</span></code> method
on mutable mappings.</p>
</section>
<section id="getting-the-transformation-function">
<h3><a class="toc-backref" href="#getting-the-transformation-function" role="doc-backlink">Getting the transformation function</a></h3>
<p>TransformDict has a simple read-only property <code class="docutils literal notranslate"><span class="pre">transform_func</span></code> which
gives back the transformation function.</p>
</section>
</section>
<section id="alternative-proposals-and-questions">
<h2><a class="toc-backref" href="#alternative-proposals-and-questions" role="doc-backlink">Alternative proposals and questions</a></h2>
<section id="retaining-the-last-original-key">
<h3><a class="toc-backref" href="#retaining-the-last-original-key" role="doc-backlink">Retaining the last original key</a></h3>
<p>Most python-dev respondents found retaining the first user-supplied key
more intuitive than retaining the last. Also, it matches the dict
objects own behaviour when using different but equal keys:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;hello&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span><span class="p">[</span><span class="mf">1.0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;world&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">d</span>
<span class="go">{1: &#39;world&#39;}</span>
</pre></div>
</div>
<p>Furthermore, explicitly retaining the last key in a first-key-retaining
scheme is still possible using the following approach:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">d</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="n">d</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
</pre></div>
</div>
<p>while the converse (retaining the first key in a last-key-retaining
scheme) doesnt look possible without rewriting part of the containers
code.</p>
</section>
<section id="using-an-encoder-decoder-pair">
<h3><a class="toc-backref" href="#using-an-encoder-decoder-pair" role="doc-backlink">Using an encoder / decoder pair</a></h3>
<p>Using a function pair isnt necessary, since the original key is retained
by the container. Moreover, an encoder / decoder pair would require the
transformation to be bijective, which prevents important use cases
like case-insensitive matching.</p>
</section>
<section id="providing-a-transformation-function-for-values">
<h3><a class="toc-backref" href="#providing-a-transformation-function-for-values" role="doc-backlink">Providing a transformation function for values</a></h3>
<p>Dictionary values are not used for lookup, their semantics are totally
irrelevant to the containers operation. Therefore, there is no point in
having both an “original” and a “transformed” value: the transformed
value wouldnt be used for anything.</p>
</section>
<section id="providing-a-specialized-container-not-generic">
<h3><a class="toc-backref" href="#providing-a-specialized-container-not-generic" role="doc-backlink">Providing a specialized container, not generic</a></h3>
<p>It was asked why we would provide the generic TransformDict construct
rather than a specialized case-insensitive dict variant. The answer
is that its nearly as cheap (code-wise and performance-wise) to provide
the generic construct, and it can fill more use cases.</p>
<p>Even case-insensitive dicts can actually elicit different transformation
functions: <code class="docutils literal notranslate"><span class="pre">str.lower</span></code>, <code class="docutils literal notranslate"><span class="pre">str.casefold</span></code> or in some cases <code class="docutils literal notranslate"><span class="pre">bytes.lower</span></code>
when working with text encoded in an ASCII-compatible encoding.</p>
</section>
<section id="other-constructor-patterns">
<h3><a class="toc-backref" href="#other-constructor-patterns" role="doc-backlink">Other constructor patterns</a></h3>
<p>Two other constructor patterns were proposed by Serhiy Storchaka:</p>
<ul>
<li>A type factory scheme:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">d</span> <span class="o">=</span> <span class="n">TransformDict</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">casefold</span><span class="p">)(</span><span class="n">Foo</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li>A subclassing scheme:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CaseInsensitiveDict</span><span class="p">(</span><span class="n">TransformDict</span><span class="p">):</span>
<span class="n">__transform__</span> <span class="o">=</span> <span class="nb">str</span><span class="o">.</span><span class="n">casefold</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">CaseInsensitiveDict</span><span class="p">(</span><span class="n">Foo</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ul>
<p>While both approaches can be defended, they dont follow established
practices in the standard library, and therefore were rejected.</p>
</section>
</section>
<section id="implementation">
<h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2>
<p>A patch for the collections module is tracked on the bug tracker at
<a class="reference external" href="http://bugs.python.org/issue18986">http://bugs.python.org/issue18986</a>.</p>
</section>
<section id="existing-work">
<h2><a class="toc-backref" href="#existing-work" role="doc-backlink">Existing work</a></h2>
<p>Case-insensitive dicts are a popular request:</p>
<ul class="simple">
<li><a class="reference external" href="http://twistedmatrix.com/documents/current/api/twisted.python.util.InsensitiveDict.html">http://twistedmatrix.com/documents/current/api/twisted.python.util.InsensitiveDict.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-list/2013-May/647243.html">https://mail.python.org/pipermail/python-list/2013-May/647243.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-list/2005-April/296208.html">https://mail.python.org/pipermail/python-list/2005-April/296208.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-list/2004-June/241748.html">https://mail.python.org/pipermail/python-list/2004-June/241748.html</a></li>
<li><a class="reference external" href="http://bugs.python.org/msg197376">http://bugs.python.org/msg197376</a></li>
<li><a class="reference external" href="http://stackoverflow.com/a/2082169">http://stackoverflow.com/a/2082169</a></li>
<li><a class="reference external" href="http://stackoverflow.com/a/3296782">http://stackoverflow.com/a/3296782</a></li>
<li><a class="reference external" href="http://code.activestate.com/recipes/66315-case-insensitive-dictionary/">http://code.activestate.com/recipes/66315-case-insensitive-dictionary/</a></li>
<li><a class="reference external" href="https://gist.github.com/babakness/3901174">https://gist.github.com/babakness/3901174</a></li>
<li><a class="reference external" href="http://www.wikier.org/blog/key-insensitive-dictionary-in-python">http://www.wikier.org/blog/key-insensitive-dictionary-in-python</a></li>
<li><a class="reference external" href="http://en.sharejs.com/python/14534">http://en.sharejs.com/python/14534</a></li>
<li><a class="reference external" href="http://www.voidspace.org.uk/python/archive.shtml#caseless">http://www.voidspace.org.uk/python/archive.shtml#caseless</a></li>
</ul>
<p>Identity dicts have been requested too:</p>
<ul class="simple">
<li><a class="reference external" href="https://mail.python.org/pipermail/python-ideas/2010-May/007235.html">https://mail.python.org/pipermail/python-ideas/2010-May/007235.html</a></li>
<li><a class="reference external" href="http://www.gossamer-threads.com/lists/python/python/209527">http://www.gossamer-threads.com/lists/python/python/209527</a></li>
</ul>
<p>Several modules in the standard library use identity lookups for object
memoization, for example <code class="docutils literal notranslate"><span class="pre">pickle</span></code>, <code class="docutils literal notranslate"><span class="pre">json</span></code>, <code class="docutils literal notranslate"><span class="pre">copy</span></code>, <code class="docutils literal notranslate"><span class="pre">cProfile</span></code>,
<code class="docutils literal notranslate"><span class="pre">doctest</span></code> and <code class="docutils literal notranslate"><span class="pre">_threading_local</span></code>.</p>
<section id="other-languages">
<h3><a class="toc-backref" href="#other-languages" role="doc-backlink">Other languages</a></h3>
<section id="c-net">
<h4><a class="toc-backref" href="#c-net" role="doc-backlink">C# / .Net</a></h4>
<p>.Net has a generic <code class="docutils literal notranslate"><span class="pre">Dictionary</span></code> class where you can specify a custom
<code class="docutils literal notranslate"><span class="pre">IEqualityComparer</span></code>: <a class="reference external" href="http://msdn.microsoft.com/en-us/library/xfhwa508.aspx">http://msdn.microsoft.com/en-us/library/xfhwa508.aspx</a></p>
<p>Using it is the recommended way to write case-insensitive dictionaries:
<a class="reference external" href="http://stackoverflow.com/questions/13230414/case-insensitive-access-for-generic-dictionary">http://stackoverflow.com/questions/13230414/case-insensitive-access-for-generic-dictionary</a></p>
</section>
<section id="java">
<h4><a class="toc-backref" href="#java" role="doc-backlink">Java</a></h4>
<p>Java has a specialized <code class="docutils literal notranslate"><span class="pre">CaseInsensitiveMap</span></code>:
<a class="reference external" href="http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/CaseInsensitiveMap.html">http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/CaseInsensitiveMap.html</a></p>
<p>It also has a separate <code class="docutils literal notranslate"><span class="pre">IdentityHashMap</span></code>:
<a class="reference external" href="http://docs.oracle.com/javase/6/docs/api/java/util/IdentityHashMap.html">http://docs.oracle.com/javase/6/docs/api/java/util/IdentityHashMap.html</a></p>
</section>
<section id="c">
<h4><a class="toc-backref" href="#c" role="doc-backlink">C++</a></h4>
<p>The C++ Standard Template Library features an <code class="docutils literal notranslate"><span class="pre">unordered_map</span></code>
with customizable hash and equality functions:
<a class="reference external" href="http://www.cplusplus.com/reference/unordered_map/unordered_map/">http://www.cplusplus.com/reference/unordered_map/unordered_map/</a></p>
</section>
</section>
</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-0455.rst">https://github.com/python/peps/blob/main/peps/pep-0455.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0455.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><ul>
<li><a class="reference internal" href="#rejection">Rejection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#semantics">Semantics</a><ul>
<li><a class="reference internal" href="#constructor">Constructor</a></li>
<li><a class="reference internal" href="#getting-the-original-key">Getting the original key</a></li>
<li><a class="reference internal" href="#getting-the-transformation-function">Getting the transformation function</a></li>
</ul>
</li>
<li><a class="reference internal" href="#alternative-proposals-and-questions">Alternative proposals and questions</a><ul>
<li><a class="reference internal" href="#retaining-the-last-original-key">Retaining the last original key</a></li>
<li><a class="reference internal" href="#using-an-encoder-decoder-pair">Using an encoder / decoder pair</a></li>
<li><a class="reference internal" href="#providing-a-transformation-function-for-values">Providing a transformation function for values</a></li>
<li><a class="reference internal" href="#providing-a-specialized-container-not-generic">Providing a specialized container, not generic</a></li>
<li><a class="reference internal" href="#other-constructor-patterns">Other constructor patterns</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">Implementation</a></li>
<li><a class="reference internal" href="#existing-work">Existing work</a><ul>
<li><a class="reference internal" href="#other-languages">Other languages</a><ul>
<li><a class="reference internal" href="#c-net">C# / .Net</a></li>
<li><a class="reference internal" href="#java">Java</a></li>
<li><a class="reference internal" href="#c">C++</a></li>
</ul>
</li>
</ul>
</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-0455.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>