[Python-Dev] redefining is

Andrew Koenig ark-mlist at att.net
Fri Mar 19 12:19:11 EST 2004


> Sure, but it's long been recommended against doing stuff like:
> 
> try:
>   foo()
> except 'quit':
>   pass
> 
> def foo():
>   raise 'quit'
> 
> This doesn't seem like it's something broken that needs fixing.  Once
> you understand what's going on, it makes sense.

Indeed -- once you understand what's going on, it makes sense.

But here's a meta-comment, derived mostly from long experience with the C++
community.  There is lots of stuff in C++ that bites new users all the time:
They see a usage, make an incorrect guess about what it means, and their
programs don't work.  Or they don't realize they need to do something, and
their programs fail in ways that escape testing.

For example, every C++ programmer with more than a little experience knows
that if you're ever intending to inherit from a class, you had better give
that class a virtual destructor.  This statement is not always true, but
it's true enough of the time that there's no point in thinking about
exceptions to it.

Nevertheless, C++ programmers inherit from classes without virtual
destructors all the time.  The most benign problem that results in doing so
is a memory leak, and of course memory leaks go undetected most of the time.

Now, in the C++ world, I realize that there is no chance whatsoever of
changing the language either to make destructors virtual by default, or to
require that a base class have a virtual destructor.  One reason is that the
C++ standard library actually contains classes that inherit from others
without virtual destructors--because that part of the library makes use of
one of the exceptions.  Nevertheless, I believe that this particular C++
feature is defined in a particularly hazardous way, and if I had the power
to turn back the clock and define it differently, I would do so.


Analogously, I think that the way Python defines "is" is hazardous.  I do
not think it is nearly as big a hazard as C++'s treatment of virtual
destructors, but I still think it's a hazard.  The reason is similar:  Using
it makes it easy to write programs that appear to work by coincidence.  The
"raise 'quit'" example is a good one, because it will always work on an
implementation that interns string literals, so no amount of testing will
reveal the problem.

The reason for that, I think, is that there are really three kinds of
"equality" that make sense, and only two of them are reasonably available:

	Value equality (==, which might be user-defined, because
		the concept of "value" can be user-defined);

	Object identity ("is")

	Object equivalence (no easy way of expressing it today)

By "object equivalence", I mean mutual substitutability--which is the same
as identity for mutable objects, but not for immutable ones.

The hazard comes about because there are objects that are equivalent but not
identical, and there are contexts (such as the raise/except example above)
in which it is logical to ask for object equivalence, but what you actually
get is object identity.  Moreover, the way one asks about object identity is
so terse that one is tempted to use it even if one does not know exactly
what it means.

The original author of the proposal on comp.lang.python was clearly
disturbed at getting object identity when equivalence would have made more
sense, and was proposing to change things as follows:

	x == y		Value equality

	x is y		Object equivalence

	id(x) == id(y)	Object identity

I can completely understand why this change might be considered too large to
make to an existing language--just like changing the wan C++ handles virtual
destructors would be--but nevertheless I think it's interesting to consider
the abstract merits of an idea such as this one, perhaps for the mythical
Python 3.0.

To put it another way:  If the three operations above existed, I am finding
it hard to think of many cases in which the third of these operations would
be more useful than the second, which suggests that the second should be
easier to express.





PS:  Java has exactly the same problem, except that there, == means object
identity.  I believe that it is a common beginner's trap in Java to apply ==
to strings and expect a useful result.





More information about the Python-Dev mailing list