On Tue, Oct 1, 2019 at 9:26 AM Andrew Barnert <abarn...@yahoo.com> wrote:
> On Sep 30, 2019, at 23:46, Ben Rudiak-Gould <benrud...@gmail.com> wrote:
> > ABC membership is a subtype relationship in some sense, and ordinary Python 
> > subclassing is a subtype relationship in some sense, but they aren't quite 
> > the same sense,
>
> But in this case, they actually match. Hashable is correctly checking for 
> structural subtyping, and the problem is that list isn’t actually a proper 
> subtype of object, not that object isn’t a proper subtype of Hashable.

If you take the perspective that the ABC notion of subtyping is the
correct one, then list isn't a proper subtype of object. I wasn't
taking the perspective that either one is the correct one. I think
they're probably both okay in isolation.

I can understand the ordinary subclass relation in Python as the
partial order generated by the inheritance dag, which is a perfectly
good notion of subtyping. (Yes a subclass instance might not
*actually* work where a superclass instance is expected, but that's
true in any OOP language. A 1234 may not work where an int instance is
expected either. Perfect substitutability is not achievable, but at
least there's a partial ordering of classes.)

I think I can understand the ABC subclass test as a subset relation,
which is also a perfectly good notion of subtyping.

The problem is that when you combine them, you have neither of those
things. I'm not even certain how they're being combined (is it just
the union of the graphs of the two relations?) but the result has none
of the properties that you'd expect a subtype relation to have, and
that the two subtype relations do have in isolation.

> >>>> class A(collections.abc.Hashable):
> >    ...     __hash__ = None
> >    ...
> >>>> issubclass(A, collections.abc.Hashable)
> >    True
>
> This one is a direct consequence of the fact that you can lie to ABCs—if you 
> inherit from an ABC you are treated as a subtype even if you don’t qualify, 
> and the check isn’t perfect. You are explicitly, and obviously, lying to the 
> system here.

My problem is not that I can't justify the current behavior, it's that
if it behaved differently, I could justify that behavior too. I feel
like you're using CPython as an oracle of what ABCs should do, and
that if issubclass had returned False in this example, you would have
been ready with an explanation for that too - namely that I broke the
subtyping relation by deleting __hash__, the same explanation you used
earlier in the case where it did return False.

What *should* it mean to inherit from an ABC? The module encourages
you to use them as mixins, but maybe that isn't the intended meaning,
just a side hack? Is the primary meaning to do the equivalent of
registering the class with the predicate?

I was worried that someone would complain about my A not making sense,
and thought about using a more complicated example:

    class A(Hashable):
        def __hash__(self): return 4

    class B(A):
        __hash__ = None

    issubclass(B, Hashable)  # True

So empirically, inheriting from Hashable registers not only that class
but all subclasses of it that may later be defined with the predicate.
Is that the intended behavior, or is it an accidental side effect of
combining two different notions of subclassing in a single test? You
could end up with a situation where you'd have to choose between using
an ABC as a mixin and living with potentially incorrect ABC predicate
tests in subclasses, or implementing the methods yourself (in the same
way the mixin would have) to get the correct predicate behavior.
Hashable isn't useful as a mixin and I think none of the other ABCs
test deletable properties, but that doesn't seem to be a design
principle, just a coincidence.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DTELBD2WUJ2V6PKSZZQUY5LYK3TCD2DG/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to