[Python-ideas] Fix documentation for __instancecheck__

Joy Diamond python.gem at gmail.com
Sat Oct 27 16:15:46 EDT 2018


Thanks, Terry.

As per your suggestion, I have submitted it as a bug report to:
https://bugs.python.org/issue35083

On Sat, Oct 27, 2018 at 4:09 PM Terry Reedy <tjreedy at udel.edu> wrote:

> On 10/27/2018 2:53 PM, Joy Diamond wrote:
> > 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.)
> > """
>
> Open a doc issue on bugs.python.org with the problem, motivation, and
> proposed solution and it should get considered.
>
> > 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
> > <mailto:rosuav at gmail.com>> wrote:
> >
> >     On Sun, Oct 28, 2018 at 5:03 AM Joy Diamond
> >     <python.gem at gmail.com
> >     <mailto: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
> >     <mailto:Python-ideas at python.org>
> >     https://mail.python.org/mailman/listinfo/python-ideas
> >     Code of Conduct: http://python.org/psf/codeofconduct/
> >
> >
> >
> > _______________________________________________
> > 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/
> >
>
>
> --
> Terry Jan Reedy
>
>
> _______________________________________________
> 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/d435e760/attachment-0001.html>


More information about the Python-ideas mailing list