
On Mon, 24 Jan 2022 at 23:32, Bar Harel <bzvi7919@gmail.com> wrote:
Either way, the discussion about duck typing is a little irrelevant, all we're doing is basically giving a faster alternative for isinstance(obj, Sequence) and isinstance(obj, Mapping) which are frequently used. What we meant by talking about duck typing is that the current PyMapping_Check calls everything that has __getitem__ a Mapping, while we call only things that are isinstance(obj, Mapping) a mapping, which matches both isinstance in Python and type annotations. If someone wishes to support duck typing he can choose not to use the function. Again, this is 100% accurate to the current Python semantics.
There's a way to define new helper functions without harming support
for ducktyping any more than ABCs do in general: define the new API
functions as semantically equivalent to PyObject_IsInstance(obj, ref_to_collections.abc.Sequence)
and PyObject_IsInstance(obj, ref_to_collections.abc.Mapping)
(i.e the C API equivalent of the ABC
checking idiom used in Python code), rather than defining them in term
of the internal type object flags used to optimise the "True" cases of
those checks. That way anything explicitly registered with the ABCs
(or otherwise set up to pass their instance checks) will still pass
the C API type check, objects that directly inherit from types with
the internal flag set will merely pass the check a little bit faster.
If distinct PyMapping_CheckInstance and PySequence_CheckInstance functions were exposed in the C API, then they could take advantage of all the tricks used to optimise collections ABC access and checks from the interpreter runtime
Given the new helper functions, the PyMapping_Check documentation
could be updated to say something like "This function does NOT provide
the C equivalent of isinstance(obj, collections.abc.Mapping)
. Use
PyMapping_CheckInstance
to efficiently check if an object implements
the Mapping ABC", and a similar change could be made to the
PySequence_Check documentation.
One thing that definitely *shouldn't* happen is deprecating or changing PySequence_Check and PyMapping_Check. Those C API functions still do exactly what they were designed to do, it's just that what they were designed to do relates to querying details regarding function pointers stored in C structs, rather than asking whether an object implements the interface of a particular Python ABC.
Cheers, Nick.
P.S. Without accounting for error checking, refcounting, or optimisation, the gist of "correctly" checking if an object is a sequence from C code is currently:
collections_abc = PyImport_ImportModule("collections.abc");
sequence_abc = PyObject_GetAttrString(collections_abc, "Sequence");
is_sequence = PyObject_IsInstance(obj_to_check, sequence_abc);
That's already overly verbose, and adding error handling, refcount adjustments and caching for speed improvements makes it worse.
Third party code should definitely NOT be checking the contents of the type flags directly.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia