[Python-ideas] Fix documentation for __instancecheck__
Terry Reedy
tjreedy at udel.edu
Sat Oct 27 16:09:03 EDT 2018
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
More information about the Python-ideas
mailing list