Guido van Rossum added the comment:

Regarding the design of __subclasshook__, these two flaws kind of cancel each 
other out. The idea is that if you have a "one-trick pony" class whose 
issubclass() check must verify that the purported sublass implements a specific 
method (e.g. __hash__), you don't want that subclass check to be inherited by a 
subclass. I suppose perhaps this ought to have been done by making 
ABCMeta.__subclasscheck__ check for the __subclasshook__ in the class dict, but 
(for reasons I've forgotten) it's not doing it that way, instead just calling 
cls.__subclasscheck__. All known __subclasshook__ implementations (those in 
collections.abc anyway :-) compensate for this by returning NotImplemented if 
the class for which they are being called isn't exactly the class in which they 
are defined. The final piece of the puzzle is object.__subclasshook__(), which 
always returns NotImplemented.

(NOTE: When reading the above paragraph, be careful to distinguish between 
__subclasscheck__, which is invoked by issubclass() and isinstance(), and 
__subclasshook__, which is only invoked by ABCMeta.__subclasscheck__().)

Here's an example showing why we don't want __subclasshook__ to be inherited. 
Suppose we have a class SupportsInt, like this:

class SupportsInt(ABC):
    @classmethod
    def __subclasshook__(cls, C):
        return hasattr(C, '__int__')

Now suppose we had a concrete class inheriting from this:

class MyInteger(SupportsInt):
    def __int__(self):
        return 0

Now, alas, everything with an __int__ method is considered to be a MyInteger, 
for example isinstance(0, MyInteger) returns True.

So what should Collection.__subclasshook__ do? It could do something like this:

class Collection(Set, Iterable, Container):
    @classmethod
    def __subclasshook__(cls, C):
        if cls is not Collection:
            return NotImplemented
        for base in Set, Iterable, Container:
            ok = base.__subclasshook__(C)
            if ok != True: return False
        return True

(Untested, hopefully you get the idea. Hope this helps.)

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue27598>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to