It is hard to distinguish a sequence and a mapping in Python 3. Both
have __getitem__, __len__ and __iter__ methods, but with different semantic.
In Python code you can use isinstance() and issubclass() checks against
collections.abc.Mapping, but it works only with types which was
explicitly registered in Mapping. Autodectection does not work as for
Iterable or Hashable. Also importing collections.abc.Mapping and calling
PyObject_IsInstance() or PyObject_IsSubclass() is cumbersome and
inefficient in the C code. It is rarely used.
It is more common to check for the existence of the keys() method. The
dict constructor and update() method do this, as well as other code
which emulates the behavior of dict. This is the only non-dunder method
used by the core operations. There are problems with this:
* Since it is not a dunder method, it is not reserved, and may conflicts
with the user attribute.
* Since it is not a dunder method, it is checked for the instance, not
for the type. Instances of the same type can look as a mapping or as not
a mapping for the same code. Checking the attribute of the class does
not give you information about the attribute of the instance.
* There is no a corresponding slot in the type object. So checking the
existence of the keys attribute is slow, non-atomic, can execute an
arbitrary code and raise an exception. It can't be used in
PyMapping_Check() and slows down the dict constructor.
* The keys() method is not called in the dict constructor. Just the
existence of the keys attribute is checked, its value is not used.
* It is a special case. All other implicitly called methods which
determined the behavior of builtin types are dunder names.
I propose to add support for special methods `__keys__` or `__items__`
and corresponding type slot (`tp_mapping->mp_keys` or
`tp_mapping->mp_items`). At first stage, the code which checked for
"keys" should check also for the special method and use them if defined.
At second stage it should emit a warning if "keys" is defined, but the
special method is not defined. At third stage, it should use the result
of the special method and ignore "keys". PyMapping_Check() can be made
checking the corresponding slot.
I am not sure about some details:
1. What special method should be added, `__keys__` or `__items__`? The
former returns keys, it needs to call `__getitem__` repeatedly to get
values. The latter returns key-value pairs, it does not need to call
`__getitem__`, but you should always pay the cost of creating a tuple
even if you do not need values.
2. What type should they return?
* An iterator.
* An iterable which can be iterated only once. Easy to implement in
Python as generator methods.
* An iterable which can be iterated multiple times.
* More complex view object which may support other protocols (for
example support `__or__` and `__and__`).
What do you think about this?
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/python-ideas@python.org/message/A3CK7Y2ICIIVYKMAXSCUVYLK7IC7CH6G/
Code of Conduct: http://python.org/psf/codeofconduct/