Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4622,6 +4622,11 @@ support membership tests:
.. versionchanged:: 3.8
Dictionary views are now reversible.

.. describe:: dictview.mapping

Return the dictionary the view refers to. If ``d`` is a
dictionary, then ``d is d.keys().mapping``, ``d is d.values().mapping``,
and ``d is d.items().mapping``.

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,
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@ def test_items(self):
self.assertRaises(TypeError, d.items, None)
self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])")

def test_views_mapping(self):
d = {}
self.assertIs(d.keys().mapping, d)
self.assertIs(d.items().mapping, d)
self.assertIs(d.values().mapping, d)

class MyDict(dict):
pass
my_dict = MyDict()
self.assertIs(my_dict.keys().mapping, my_dict)
self.assertIs(my_dict.items().mapping, my_dict)
self.assertIs(my_dict.values().mapping, my_dict)

def test_contains(self):
d = {}
self.assertNotIn('a', d)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Each dictionary view now has a ``mapping`` attribute that references the original dictionary. Patch contributed by Dennis Sweeney.
13 changes: 10 additions & 3 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ converting the dict to the combined table.
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "dict-common.h"
#include "stringlib/eq.h" // unicode_eq()
#include "structmember.h" // PyMemberDef

/*[clinic input]
class dict "PyDictObject *" "&PyDict_Type"
Expand Down Expand Up @@ -4448,6 +4449,12 @@ static PyNumberMethods dictviews_as_number = {
(binaryfunc)dictviews_or, /*nb_or*/
};

static PyMemberDef dictview_members[] = {
{"mapping", T_OBJECT, offsetof(_PyDictViewObject, dv_dict),
READONLY, "dictionary that this view refers to"},
{NULL} /* Sentinel */
};

static PyObject*
dictviews_isdisjoint(PyObject *self, PyObject *other)
{
Expand Down Expand Up @@ -4545,7 +4552,7 @@ PyTypeObject PyDictKeys_Type = {
(getiterfunc)dictkeys_iter, /* tp_iter */
0, /* tp_iternext */
dictkeys_methods, /* tp_methods */
0,
.tp_members = dictview_members,
};

static PyObject *
Expand Down Expand Up @@ -4651,7 +4658,7 @@ PyTypeObject PyDictItems_Type = {
(getiterfunc)dictitems_iter, /* tp_iter */
0, /* tp_iternext */
dictitems_methods, /* tp_methods */
0,
.tp_members = dictview_members,
};

static PyObject *
Expand Down Expand Up @@ -4732,7 +4739,7 @@ PyTypeObject PyDictValues_Type = {
(getiterfunc)dictvalues_iter, /* tp_iter */
0, /* tp_iternext */
dictvalues_methods, /* tp_methods */
0,
.tp_members = dictview_members,
};

static PyObject *
Expand Down