[Python-Dev] PEP 560: bases classes / confusion

Jim J. Jewett jimjjewett at gmail.com
Wed Nov 15 09:20:09 EST 2017


(1)  I found the following (particularly "bases classes") very confusing:

"""
If an object that is not a class object appears in the bases of a class

definition, then ``__mro_entries__`` is searched on it. If found,
it is called with the original tuple of bases as an argument. The result
of the call must be a tuple, that is unpacked in the bases classes in place
of this object. (If the tuple is empty, this means that the original bases
is
simply discarded.)
"""

Based on the following GenericAlias/NewList/Tokens example, I think I
now I understand what you mean, and would have had somewhat less
difficulty if it were expressed as:

"""
When an object that is not a class object appears in the (tuple of)
bases of a class
definition, then attribute ``__mro_entries__`` is searched on that
non-class object.  If ``__mro_entries__`` found,
it is called with the entire original tuple of bases as an argument. The result
of the call must be a tuple, which is unpacked and replaces only the
non-class object in the tuple of bases.  (If the tuple is empty, this
means that the original bases
is
simply discarded.)
"""

Note that this makes some assumptions about the __mro_entries__
signature that I wasn't quite sure about from the example.  So
building on that:

    class ABList(A, NewList[int], B):

I *think* the following will happen:

    "NewList[int]" will be evaluated, and __class_getitem__ called, so
that the bases tuple will be (A, GenericAlias(NewList, int), B)

    # (A)  I *think* __mro_entries__ gets called with the full tuple,
    # instead of just the object it is found on.
    # (B) I *think* it is called on the results of evaluating
    # the terms within the tuple, instead of the original
    # string representation.
    _tmp = __mro_entries__(A, GenericAlias(NewList, int), B)

    # (C)  I *think* __mro_entries__ returns a replacement for
    # just the single object, even though it was called on
    # the whole tuple, without knowing which object it
    # represents.
    bases = (A, _tmp, B)

    # (D) If there are two non-class objects, I *think* the
    # second one gets the same arguments as the first,
    # rather than an intermediate tuple with the first such
    # object already substituted out.

-jJ


More information about the Python-Dev mailing list