bpo-40890: Add `mapping` property to dict views (GH-20749)
This commit is contained in:
parent
0d3350daa8
commit
3ee0e48b03
|
@ -4622,6 +4622,12 @@ support membership tests:
|
|||
.. versionchanged:: 3.8
|
||||
Dictionary views are now reversible.
|
||||
|
||||
.. describe:: dictview.mapping
|
||||
|
||||
Return a :class:`types.MappingProxyType` that wraps the original
|
||||
dictionary to which the view refers.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
Keys views are set-like since their entries are unique and hashable. If all
|
||||
values are hashable, so that ``(key, value)`` pairs are unique and hashable,
|
||||
|
@ -4661,6 +4667,12 @@ An example of dictionary view usage::
|
|||
>>> keys ^ {'sausage', 'juice'}
|
||||
{'juice', 'sausage', 'bacon', 'spam'}
|
||||
|
||||
>>> # get back a read-only proxy for the original dictionary
|
||||
>>> values.mapping
|
||||
mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500})
|
||||
>>> values.mapping['spam']
|
||||
500
|
||||
|
||||
|
||||
.. _typecontextmanager:
|
||||
|
||||
|
|
|
@ -74,6 +74,11 @@ New Features
|
|||
number of ones in the binary expansion of a given integer, also known
|
||||
as the population count. (Contributed by Niklas Fiekas in :issue:`29882`.)
|
||||
|
||||
* The views returned by :meth:`dict.keys`, :meth:`dict.values` and
|
||||
:meth:`dict.items` now all have a ``mapping`` attribute that gives a
|
||||
:class:`types.MappingProxyType` object wrapping the original
|
||||
dictionary. (Contributed by Dennis Sweeney in :issue:`40890`.)
|
||||
|
||||
|
||||
Other Language Changes
|
||||
======================
|
||||
|
|
|
@ -105,6 +105,26 @@ class DictTest(unittest.TestCase):
|
|||
self.assertRaises(TypeError, d.items, None)
|
||||
self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")
|
||||
|
||||
def test_views_mapping(self):
|
||||
mappingproxy = type(type.__dict__)
|
||||
class Dict(dict):
|
||||
pass
|
||||
for cls in [dict, Dict]:
|
||||
d = cls()
|
||||
m1 = d.keys().mapping
|
||||
m2 = d.values().mapping
|
||||
m3 = d.items().mapping
|
||||
|
||||
for m in [m1, m2, m3]:
|
||||
self.assertIsInstance(m, mappingproxy)
|
||||
self.assertEqual(m, d)
|
||||
|
||||
d["foo"] = "bar"
|
||||
|
||||
for m in [m1, m2, m3]:
|
||||
self.assertIsInstance(m, mappingproxy)
|
||||
self.assertEqual(m, d)
|
||||
|
||||
def test_contains(self):
|
||||
d = {}
|
||||
self.assertNotIn('a', d)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Each dictionary view now has a ``mapping`` attribute that provides a :class:`types.MappingProxyType` wrapping the original dictionary. Patch contributed by Dennis Sweeney.
|
|
@ -4122,6 +4122,23 @@ _PyDictView_New(PyObject *dict, PyTypeObject *type)
|
|||
return (PyObject *)dv;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
dictview_mapping(PyObject *view)
|
||||
{
|
||||
assert(view != NULL);
|
||||
assert(PyDictKeys_Check(view)
|
||||
|| PyDictValues_Check(view)
|
||||
|| PyDictItems_Check(view));
|
||||
PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict;
|
||||
return PyDictProxy_New(mapping);
|
||||
}
|
||||
|
||||
static PyGetSetDef dictview_getset[] = {
|
||||
{"mapping", (getter)dictview_mapping, (setter)NULL,
|
||||
"dictionary that this view refers to", NULL},
|
||||
{0}
|
||||
};
|
||||
|
||||
/* TODO(guido): The views objects are not complete:
|
||||
|
||||
* support more set operations
|
||||
|
@ -4635,7 +4652,7 @@ PyTypeObject PyDictKeys_Type = {
|
|||
(getiterfunc)dictkeys_iter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
dictkeys_methods, /* tp_methods */
|
||||
0,
|
||||
.tp_getset = dictview_getset,
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
|
@ -4741,7 +4758,7 @@ PyTypeObject PyDictItems_Type = {
|
|||
(getiterfunc)dictitems_iter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
dictitems_methods, /* tp_methods */
|
||||
0,
|
||||
.tp_getset = dictview_getset,
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
|
@ -4822,7 +4839,7 @@ PyTypeObject PyDictValues_Type = {
|
|||
(getiterfunc)dictvalues_iter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
dictvalues_methods, /* tp_methods */
|
||||
0,
|
||||
.tp_getset = dictview_getset,
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
|
|
Loading…
Reference in New Issue