| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0d3350d commit 3ee0e48
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4622,6 +4622,12 @@ support membership tests: | |||
| 4622 | 4622 | .. versionchanged:: 3.8 | |
| 4623 | 4623 | Dictionary views are now reversible. | |
| 4624 | 4624 | ||
| 4625 | + .. describe:: dictview.mapping | ||
| 4626 | + | ||
| 4627 | + Return a :class:`types.MappingProxyType` that wraps the original | ||
| 4628 | + dictionary to which the view refers. | ||
| 4629 | + | ||
| 4630 | + .. versionadded:: 3.10 | ||
| 4625 | 4631 | ||
| 4626 | 4632 | Keys views are set-like since their entries are unique and hashable. If all | |
| 4627 | 4633 | values are hashable, so that ``(key, value)`` pairs are unique and hashable, | |
@@ -4661,6 +4667,12 @@ An example of dictionary view usage:: | |||
| 4661 | 4667 | >>> keys ^ {'sausage', 'juice'} | |
| 4662 | 4668 | {'juice', 'sausage', 'bacon', 'spam'} | |
| 4663 | 4669 | ||
| 4670 | + >>> # get back a read-only proxy for the original dictionary | ||
| 4671 | + >>> values.mapping | ||
| 4672 | + mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}) | ||
| 4673 | + >>> values.mapping['spam'] | ||
| 4674 | + 500 | ||
| 4675 | + | ||
| 4664 | 4676 | ||
| 4665 | 4677 | .. _typecontextmanager: | |
| 4666 | 4678 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -74,6 +74,11 @@ New Features | |||
| 74 | 74 | number of ones in the binary expansion of a given integer, also known | |
| 75 | 75 | as the population count. (Contributed by Niklas Fiekas in :issue:`29882`.) | |
| 76 | 76 | ||
| 77 | + * The views returned by :meth:`dict.keys`, :meth:`dict.values` and | ||
| 78 | + :meth:`dict.items` now all have a ``mapping`` attribute that gives a | ||
| 79 | + :class:`types.MappingProxyType` object wrapping the original | ||
| 80 | + dictionary. (Contributed by Dennis Sweeney in :issue:`40890`.) | ||
| 81 | + | ||
| 77 | 82 | ||
| 78 | 83 | Other Language Changes | |
| 79 | 84 | ====================== | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -105,6 +105,26 @@ def test_items(self): | |||
| 105 | 105 | self.assertRaises(TypeError, d.items, None) | |
| 106 | 106 | self.assertEqual(repr(dict(a=1).items()), "dict_items([('a', 1)])") | |
| 107 | 107 | ||
| 108 | + def test_views_mapping(self): | ||
| 109 | + mappingproxy = type(type.__dict__) | ||
| 110 | + class Dict(dict): | ||
| 111 | + pass | ||
| 112 | + for cls in [dict, Dict]: | ||
| 113 | + d = cls() | ||
| 114 | + m1 = d.keys().mapping | ||
| 115 | + m2 = d.values().mapping | ||
| 116 | + m3 = d.items().mapping | ||
| 117 | + | ||
| 118 | + for m in [m1, m2, m3]: | ||
| 119 | + self.assertIsInstance(m, mappingproxy) | ||
| 120 | + self.assertEqual(m, d) | ||
| 121 | + | ||
| 122 | + d["foo"] = "bar" | ||
| 123 | + | ||
| 124 | + for m in [m1, m2, m3]: | ||
| 125 | + self.assertIsInstance(m, mappingproxy) | ||
| 126 | + self.assertEqual(m, d) | ||
| 127 | + | ||
| 108 | 128 | def test_contains(self): | |
| 109 | 129 | d = {} | |
| 110 | 130 | self.assertNotIn('a', d) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Each dictionary view now has a ``mapping`` attribute that provides a :class:`types.MappingProxyType` wrapping the original dictionary. Patch contributed by Dennis Sweeney. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4122,6 +4122,23 @@ _PyDictView_New(PyObject *dict, PyTypeObject *type) | |||
| 4122 | 4122 | return (PyObject *)dv; | |
| 4123 | 4123 | } | |
| 4124 | 4124 | ||
| 4125 | + static PyObject * | ||
| 4126 | + dictview_mapping(PyObject *view) | ||
| 4127 | + { | ||
| 4128 | + assert(view != NULL); | ||
| 4129 | + assert(PyDictKeys_Check(view) | ||
| 4130 | + || PyDictValues_Check(view) | ||
| 4131 | + || PyDictItems_Check(view)); | ||
| 4132 | + PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict; | ||
| 4133 | + return PyDictProxy_New(mapping); | ||
| 4134 | + } | ||
| 4135 | + | ||
| 4136 | + static PyGetSetDef dictview_getset[] = { | ||
| 4137 | + {"mapping", (getter)dictview_mapping, (setter)NULL, | ||
| 4138 | + "dictionary that this view refers to", NULL}, | ||
| 4139 | + {0} | ||
| 4140 | + }; | ||
| 4141 | + | ||
| 4125 | 4142 | /* TODO(guido): The views objects are not complete: | |
| 4126 | 4143 | ||
| 4127 | 4144 | * support more set operations | |
@@ -4635,7 +4652,7 @@ PyTypeObject PyDictKeys_Type = { | |||
| 4635 | 4652 | (getiterfunc)dictkeys_iter, /* tp_iter */ | |
| 4636 | 4653 | 0, /* tp_iternext */ | |
| 4637 | 4654 | dictkeys_methods, /* tp_methods */ | |
| 4638 | - 0, | ||
| 4655 | + .tp_getset = dictview_getset, | ||
| 4639 | 4656 | }; | |
| 4640 | 4657 | ||
| 4641 | 4658 | static PyObject * | |
@@ -4741,7 +4758,7 @@ PyTypeObject PyDictItems_Type = { | |||
| 4741 | 4758 | (getiterfunc)dictitems_iter, /* tp_iter */ | |
| 4742 | 4759 | 0, /* tp_iternext */ | |
| 4743 | 4760 | dictitems_methods, /* tp_methods */ | |
| 4744 | - 0, | ||
| 4761 | + .tp_getset = dictview_getset, | ||
| 4745 | 4762 | }; | |
| 4746 | 4763 | ||
| 4747 | 4764 | static PyObject * | |
@@ -4822,7 +4839,7 @@ PyTypeObject PyDictValues_Type = { | |||
| 4822 | 4839 | (getiterfunc)dictvalues_iter, /* tp_iter */ | |
| 4823 | 4840 | 0, /* tp_iternext */ | |
| 4824 | 4841 | dictvalues_methods, /* tp_methods */ | |
| 4825 | - 0, | ||
| 4842 | + .tp_getset = dictview_getset, | ||
| 4826 | 4843 | }; | |
| 4827 | 4844 | ||
| 4828 | 4845 | static PyObject * | |
| Back | FazBrowse Home | New Git URL |
0 commit comments