issubclass(dict, Mapping)

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Dec 22 17:36:14 EST 2010


On Wed, 22 Dec 2010 14:20:51 +0000, kj wrote:

> Here's another example, fresh from today's crop of wonders:
> 
> (v. 2.7.0)
>>>> from collections import Mapping
>>>> issubclass(dict, Mapping)
> True
>>>> dict.__bases__
> (<type 'object'>,)
>>>> [issubclass(b, Mapping) for b in dict.__bases__]
> [False]
> 
> 
> So dict is a subclass of Mapping, even though none of the bases of dict
> is either Mapping or a subclass of Mapping.  Great.

Yes. So what?

(1) What *actual* problem does this cause you? 

(2) Do you have an example of code that breaks because of this?

(3) Do you understand that since the introduction of ABC (abstract base 
classes) in Python 2.6 (I think), isinstance and issubclass checks are 
performed cooperatively? The instance or class are asked if they wish to 
be known as an instance/subclass of the second argument. Classes can 
register themselves as subclasses of (say) Mapping without sharing any 
actual code with Mapping.

This is a good thing, and the problem isn't that the abstraction leaks, 
as you believe, but the opposite: you're *ignoring* the abstraction and 
looking for concrete details that may or may not exist.

I fear that you have fundamentally misunderstood the concept of "leaky 
abstraction". It does not mean, as you seem to think, that some concrete 
implementation detail differs between two classes (or functions). It 
means that some difference in behaviour is exposed, that difference being 
irrelevant to the abstraction but nevertheless important in some other 
sense. A contrived example:

class MyList(list):
    def __len__(self):
        import time
        time.sleep(3600000)
        return list.__len__(self)

MyList can be used anywhere a regular list can be used. Functionally the 
two are identical. The abstraction is that MyList is the same as list. 
But the leak is that len(MyList()) is *incredibly* slow.


Coming back to Mapping:

Abstraction: issubclass(dict, Mapping)

One possible concrete implementation detail of how issubclass is 
implemented:
    any(base is Mapping for base in dict.__bases__)


The statement "dict is a subclass of Mapping" is about an abstract 
relationship. It's not necessarily a statement about __bases__.

To give an analogy, if you insist on doing DNA testing to determine 
whether a boy is a son of a man, you're going to be confused and 
distressed every time you find fathers whose sons are genetically 
unrelated to them.


-- 
Steven



More information about the Python-list mailing list