[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