issubclass(C, Mapping) not behaving as expected

Peter Otten __peter__ at web.de
Wed May 30 04:38:17 EDT 2012


anntzer.lee at gmail.com wrote:

> from collections import *
> class C(object):
>     def __iter__(self): pass
>     def __contains__(self, i): pass
>     def __len__(self): pass
>     def __getitem__(self, i): pass
> issubclass(C, Mapping) => False
> [issubclass(C, cls) for cls in Mapping.__mro__] => [False, True, True,
> [True, True]
> i.e. C does implement Sized, Iterable and Container.
> 
> I would have expected that just as issubclass(C, Sized) checks for the
> presence of a "__len__" method, issubclass(C, Mapping) would check for the
> presence of the three methods required by each immediate superclass?

Your expectations are wrong -- as you might have expected ;)
You have two options two get the issubclass() result you want: actually 
subclass:

>>> from collections import Mapping as M
>>> class A(M): pass
... 
>>> issubclass(A, M)
True

... or register your class:

>>> class B(object): pass
... 
>>> issubclass(B, M)
False
>>> M.register(B)
>>> issubclass(B, M)
True

In both cases you are responsible for the correct implementation of the 
protocol. Subclassing is normally easier because it fills in missing methods 
and complains about required ones on instantiation:

>>> B()
<__main__.B object at 0x7fa34bda3750>
>>> A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class A with abstract methods 
__getitem__, __iter__, __len__





More information about the Python-list mailing list