Is it? Subtyping in type theory satisfies some axioms, one of which is
transitivity. The addition of the ABCs broke transitivity:
>>> issubclass(list, object)
>>> issubclass(object, collections.abc.Hashable)
>>> issubclass(list, collections.abc.Hashable)
I am not as much of a Pythonist as others here, but this looks like a broken API design to me. I checked the official doc and indeed it says there:
Return true if class is a subclass (direct, indirect or *virtual*) of classinfo. A class is considered a subclass of itself. classinfo may be a tuple of class objects, in which case every entry in classinfo will be checked. In any other case, a TypeError exception is raised.
Where *virtual* is a hyperlink to an ABC definition.
`issubclass` will be fine without virtual and I am not sure why virtual has been added to it, if apparently it does something else (even though it pretends to be doing the same thing), and could be implemented as a function in abc. Plus while the property of being a subclass is pretty solid, from the discussion here about "Subscriptable" it looks like the ABC "subclassing" is partly a wishful thinking, like may actually be subscriptable, but no one really knows what happens until __getitem__ is called, or it may be understood differently by different people, or different application as well, as already mentioned here too:
On Mon, Sep 30, 2019 at 06:00:44PM +0900, Stephen J. Turnbull wrote:
> Technical questions: does "Subscriptable" mean non-negative ints only,
> or does it include the negative "count from the end" protocol? How
> about slices?
It means the class defines a __getitem__ method. Like __call__, the
semantics of that method, and the range of acceptable arguments, is out
of scope of the ABC.
And since the semantic is really out of the scope, why pretend that we know, when we can only guess and the actual resulting information from the test is really "class or subclass defines __getitem__ attribute and it is not None (not even saying if it is a function, and what this function might do)".
From that point of view, I would see the OP mentioning:
>if getclassattr(obj, '__getitem__', None) is not None
better fitting (while ignoring for a moment that `getclassattr` does not exist), because it does not pretend to do something it does not, and is totally explicit about what is the result. Then it is up to the caller to decide whether this particular condition defines "subscriptable" class for his particular purpose, or some other conditions should be met as well (__getitem__ is a function, returns a value, etc.).