[Python-Dev] Changing semantics of issubclass when accepting atuple

Guido van Rossum guido at python.org
Sun Dec 14 21:42:47 EST 2003


> [Brett]
> >> But this is a change in semantics.  Tim said I should clear it here
> >> first so that is what I am doing.  Anyone have issues if I do this?
> >> And if so, any objections of backporting to 2.3?
> 
> [Guido]
> > Let's not mess with 2.3 semantics.
> 
> That's the rub:  the segfaults occur in 2.3 too, of course, so should also
> be fixed there.  Looks like isinstance() has the same vulnerability, and
> that the code comments don't match the docs.
> 
> """
> class C(object):
>     pass
> 
> classtup = C
> for i in xrange(50000):
>     classtup = (classtup,)
> 
> if 0:	# segfaults on both branches; maybe on your box 50000 is too small
>     print issubclass(C, classtup)
> else:
>     print isinstance(C(), classtup)
> """
> 
> The implementations even have this shared prophetic <wink> comment:
> 
> 		/* Not a general sequence -- that opens up the road to
> 		   recursion and stack overflow. */
> 
> The error messages plainly say that the example segfaulting program isn't a
> supported use:
> 
> 			"isinstance() arg 2 must be a class, type,"
> 			" or tuple of classes and types"))
> 
> 					"issubclass() arg 2 must be a class"
> 					" or tuple of classes"))
> 
> The documentation could well have *meant* that, too:
> 
> >>> print isinstance.__doc__
> isinstance(object, class-or-type-or-tuple) -> bool
> 
> Return whether an object is an instance of a class or of a subclass thereof.
> With a type as second argument, return whether that is the object's type.
> The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
> isinstance(x, A) or isinstance(x, B) or ... (etc.).
> >>> print issubclass.__doc__
> issubclass(C, B) -> bool
> 
> Return whether class C is a subclass (i.e., a derived class) of class B.
> When using a tuple as the second argument issubclass(X, (A, B, ...)),
> is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.).
> >>>
> 
> The idea that arbitrarily nested tuples is allowed comes from that the
> docstrings imply it (more accidentally than on purpose, it seems to me), and
> that the implementations don't actually check for what its error messages
> claim must be the case.
> 
> Finally, the docs in the Library Reference Manual are schizophrenic about
> the issue at hand.  The issubclass() docs appear to disallow the possibility
> of nested tuples, while the isinstance() docs explictly allow them.

It was my intention to allow nested tuples, just not insanely deeply
nested tuples.  The imagined use case was having names for types or
groups of types, and being able to combine these without having to
know whether a name refers to a type or a group.

I don't know how important this use case is in practice, given that
the most complicated use I've ever made of this myself has been
isinstance(x, (int, long, float, complex)).

So I think we could easily require a flat tuple in 2.4 and be done
with it.  On the off chance that someone uses nested tuples in 2.3,
how much work would it be to have a helper routine that takes a
nesting depth argument, and clipping the nesting dept to e.g. 20?
That should be sufficient for practical purposes. :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list