[Python-Dev] Undocumented change / bug in Python3's PyMapping_Check

Nick Coghlan ncoghlan at gmail.com
Wed May 6 16:59:30 CEST 2009


John Millikin wrote:
> In Python 2, PyMapping_Check will return 0 for list objects. In Python
> 3, it returns 1. Obviously, this makes it rather difficult to
> differentiate between mappings and other sized iterables. In addition,
> it differs from the behavior of the ``collections.Mapping`` ABC --
> isinstance([], collections.Mapping) returns False.
> 
> I believe the new behavior is erroneous, but would like to confirm
> that before filing a bug.

It's not a bug.

PyMapping_Check just tells you if a type has an entry in the
tp_as_mapping->mp_subscript slot. In 2.x, it used to have an additional
condition that the tp_as_sequence->sq_slice slot be empty, but that has
gone away in Py3k because the sq_slice slot has been removed.

Even in 2.x that test wasn't a reliable way of telling if something was
a mapping or a sequence - it happened to get it right for lists and
tuples (since they define __getslice__ and __setslice__), but this is
not the case for new-style user defined sequences:

>>> from operator import isMappingType
>>> class MySeq(object):
...   def __getitem__(self, idx):
...     # Is this a mapping or an unsliceable sequence?
...     return idx*2
...
>>> isMappingType(MySeq())
True

Using the new collections module ABCs to check for sequences and
mappings. That's what they're for, and they will give you a much more
reliable answer than the C level checks (which are really just an
implementation detail).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------


More information about the Python-Dev mailing list