415 lines
31 KiB
HTML
415 lines
31 KiB
HTML
|
||
<!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> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </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 <solipsis at pitrou.net></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
|
||
won’t rehash the semantics of most TransformDict methods.</p>
|
||
<p>The transformation function needn’t 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">>>> </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">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'SomeKey'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
|
||
<span class="gp">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'somekey'</span><span class="p">]</span>
|
||
<span class="go">5</span>
|
||
<span class="gp">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'SOMEKEY'</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">>>> </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">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'SomeKey'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
|
||
<span class="gp">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'somekey'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span>
|
||
<span class="gp">>>> </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">[('SomeKey', 2)]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The original keys needn’t 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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">'Foo'</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">>>> </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">[('Bar', 2), ('Foo', 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">>>> </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">'Foo'</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
|
||
<span class="gp">>>> </span><span class="n">d</span><span class="o">.</span><span class="n">getitem</span><span class="p">(</span><span class="s1">'FOO'</span><span class="p">)</span>
|
||
<span class="go">('Foo', 1)</span>
|
||
<span class="gp">>>> </span><span class="n">d</span><span class="o">.</span><span class="n">getitem</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
||
<span class="gr">KeyError</span>: <span class="n">'bar'</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
|
||
object’s own behaviour when using different but equal keys:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>
|
||
<span class="gp">>>> </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">'hello'</span>
|
||
<span class="gp">>>> </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">'world'</span>
|
||
<span class="gp">>>> </span><span class="n">d</span>
|
||
<span class="go">{1: 'world'}</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) doesn’t look possible without rewriting part of the container’s
|
||
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 isn’t 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 container’s operation. Therefore, there is no point in
|
||
having both an “original” and a “transformed” value: the transformed
|
||
value wouldn’t 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 it’s 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 don’t 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> |