[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