[Python-ideas] Fix documentation for __instancecheck__

Joy Diamond python.gem at gmail.com
Sat Oct 27 14:53:56 EDT 2018


Chris,

Yes, the following works:
"""
(Note that any object `x` is always considered to be an instance of
`type(x)`, and this cannot be overridden.)
"""

NOTE:  I fixed your sentence of `x.__class__` to `type(x)` since it is not
always true that `x.__class__ == type(x)`.

For example the actual code reference above:

https://github.com/python/cpython/blob/master/Objects/abstract.c#L2397-L2405

Says "if (Py_TYPE(inst) == (PyTypeObject *)cls)" in the actual C Python
implementation:

So it using `type(x)` not `x.__class__`

Thanks,

Joy Diamond.

====

ADDENDUM:

Here is an example where `type(x) is not x.__class__`   (there are other
not as perverse examples where you want `.__class__` to differ from `type`)

NOTE:  The final assert will fail, showing that `type(x) is not x.__class__`

#
#   This really perverse code demonstrates that `t.__class__` is *NOT*
#   always the same as type(t).
#
#  The code shows an metaclass that when you derive objects from its
classes, creates a `7`
#  instead of a derived class.
#
def not_really_a_metaclass__make_a_7(name, bases, member):
    return 7

@property
def not_really_a_class__make_a_7(t):
    return not_really_a_metaclass__make_a_7

class Metaclass__Make_A_7(type):
    __class__ = not_really_a_class__make_a_7

Make_A_7 = Metaclass__Make_A_7('Make_A_7', ((object,)), {})


#
#   Now then:
#
#       `Make_A_7` is a class that when inherited from creates a '7' instead
#       of a class ... :(
#
#   Works for python 2 & pypy (not yet fixed to work for python 3)
#
class Seven(Make_A_7):  # Calls `Make_A_7.__class__('Seven, (('Make_A_7,)),
{})` which returns `7`
    pass

print('Seven is: %s' % Seven)

assert isinstance(Make_A_7, Metaclass__Make_A_7)
assert Make_A_7.__class__ == Metaclass__Make_A_7   #  This will *FAIL* due
to the perverse definition of `.__class__`

On Sat, Oct 27, 2018 at 2:25 PM Chris Angelico <rosuav at gmail.com> wrote:

> On Sun, Oct 28, 2018 at 5:03 AM Joy Diamond <python.gem at gmail.com> wrote:
> >
> > Greetings,
> >
> > This is a request to fix the documentation for __instancecheck__.
> >
> > Please add the following (please rewrite better than I can -- I am not
> good at explaining concepts in short sentences):
> >
> > NOTE:  As an optimization, isinstance(object, classinfo) does NOT call
> classinfo.__instancecheck__(instance) when type(object) == classinfo.
> >
> > Consider the following program:
> >
> > class M(type):
> >     def __instancecheck__(m, t):
> >         print('instancecheck(%s, %s)' % (m, t))
> >         return False                                    #   LIE!
> >
> > Test = M('Test', ((object,)), {})
> >
> > something = Test()
> >
> > print('Does *NOT* call __instancecheck__:')
> > print('isinstance(something, Test): %s' % isinstance(something, Test))
>
> Here's the passage in question, for reference:
>
> """
> The following methods are used to override the default behavior of the
> isinstance() and issubclass() built-in functions.
>
> In particular, the metaclass abc.ABCMeta implements these methods in
> order to allow the addition of Abstract Base Classes (ABCs) as
> “virtual base classes” to any class or type (including built-in
> types), including other ABCs.
> """
>
> https://docs.python.org/3/reference/datamodel.html#customizing-instance-and-subclass-checks
>
> Since it uses the word "override", I agree that it's not entirely
> correct. The implication of "override" is that you can completely
> replace the normal behaviour. In this case, you can change the
> behaviour of subclass testing (for instance, you can "disown" a
> subclass by denying that instances of it are instances of yourself),
> and of course, you can claim an object as an instance of a class it
> didn't directly inherit from (the way ABCs work), but you cannot fib
> about direct instances. I think the behaviour is close enough to
> accurate that it doesn't need major rewording; how about adding this
> parenthesis:
>
> """
> (Note that any object `x` is always considered to be an instance of
> `x.__class__`, and this cannot be overridden.)
> """
>
> Would that work?
>
> ChrisA
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181027/60e89720/attachment-0001.html>


More information about the Python-ideas mailing list