Discussion:
TypeCheck vs IsInstance in C API
(too old to reply)
Andrew Wang
2015-08-25 02:12:14 UTC
Permalink
Hi.

I know this thread is ancient, but I would like to know the answer as well (
https://mail.python.org/pipermail/python-list/2006-May/413542.html).

Thanks.
Andrew
r***@fastmail.us
2015-08-25 14:32:33 UTC
Permalink
Post by Andrew Wang
Hi.
I know this thread is ancient, but I would like to know the answer
as well
( https://mail.python.org/pipermail/python-list/2006-May/413542.html).
Of course, the answer in 2015 is actually very different from the
answer in 2006, since we didn't have either Python 3 or abstract
classes back then.

The IsInstance (and IsSubclass) function documentation mentions that
they use the methods __instancecheck__ [and __subclasscheck__],
presumably to support abstract classes.

The actual implementation of TypeCheck is a macro:
PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
#define PyObject_TypeCheck(ob, tp) \
(Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp)))

PyType_IsSubtype (in typeobject.c) only appears to deal with the
real types, not any abstract class methods.

So it looks like PyObject_TypeCheck/PyType_IsSubtype was originally
introduced to check for real types (and not old style classes), and
continued in that niche as IsInstance/IsSubclass were repurposed to
deal with PEP 3119 ABC logic.

Incidentally, this made me wonder what was done before
PyObject_IsInstance was added in 2.1. In 2.0, substantially the same
code exists inside builtin_isinstance.

Stuff I found researching this:
http://comments.gmane.org/gmane.comp.python.cython.devel/2928
https://groups.google.com/forum/#!topic/comp.lang.python/z594gnaBhwY
https://groups.google.com/forum/#!topic/comp.lang.python/ywqzu3JD6Nw
Post by Andrew Wang
raise ob
return 1
else: return 0
Terry Reedy
2015-08-25 16:56:49 UTC
Permalink
[question snipped]
Huh?? I fail to see the point of this buggy code.
Post by Andrew Wang
raise ob
return 1
else: return 0
The extra marginal '>' quote makes it look like this buggy code was
posted by Andrew, but it comes from random832. In 3.x, both ob and cl
must be exceptions and isa(1, int) cannot work. In 2.7, ob must be an
exception or old-style class (not documented that I see).
Post by Andrew Wang
raise 1
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
raise 1
TypeError: exceptions must be old-style classes or derived from
BaseException, not int

Hence, isa(1, int) raises TypeError instead of returning 1. If 'else' is
changed to 'except', it returns 0 instead of 1.
--
Terry Jan Reedy
r***@fastmail.us
2015-08-25 17:42:44 UTC
Permalink
Post by Terry Reedy
Huh?? I fail to see the point of this buggy code.
...
Post by Terry Reedy
The extra marginal '>' quote makes it look like this buggy code was
posted by Andrew, but it comes from random832.
Actually, it comes from one of the links I posted right above it. It
was, apparently, the recommended way to do this in python up to 1.4,
before isinstance existed.

It only worked with [old-style, goes without saying] instance and class
objects and not, say, ints, but AFAICT isinstance in 1.5 didn't support
anything else either. Since these couldn't be subclassed you could
simply add "if type(cl) is types.TypeType: return type(ob) is cl" to the
top.

Loading...