question about True values

Antoon Pardon apardon at forel.vub.ac.be
Mon Oct 30 10:01:39 CET 2006


On 2006-10-29, Steven D'Aprano <steve at REMOVE.THIS.cybersource.com.au> wrote:
> On Sun, 29 Oct 2006 00:31:23 -0700, Carl Banks wrote:
>
> That's why (for example) Python allows + to operate on lists, or strings,
> or floats

That was IMO a mistake. There are types for which concatenation as well as
addition are meaningfull operators. By using the "+" for both these
operations, writing such a class becomes awkward in Python because you
have to stray away from Python idiom for one of the two operations.
Should Python have chosen the "_" character for concatenating writing
amnd working with such a class would have looked more natural.

> -- but that doesn't imply that you can add a list to a float,
> or that the same code will operate happily on both lists and floats. You,
> the developer, don't need to care what data types you are adding, you just
> use the same syntax: a+b.

Of course the developer needs to care. It's not because a+b will give
a result that the result will also be meaningfull. It is not because
a class has defined the operators "+", "-", "/", "*" it will give
a meaningfull result if you throw a matrix of instances into procdure
that solves equations.

> The objects themselves know what addition
> means to themselves. In practice, string addition threatens to be so
> inefficient that you might wish to avoid doing it, but as a general
> principle, Python idioms and syntax are as type-independent as possible.

Which isn't necesarrily a good thing. I think there is even a warning
somewhere against too easily overloading the arithmetic operators
for operations that don't act at all as such operators. I think
they should have thought of that before using "+" for concatenation.

> That's why obj[index] works whether you are getting or setting or deleting
> an item, whether it is a sequence or a mapping or a custom class. As much
> as possible, you don't need to know what the object is to know what syntax
> to use. The idiom for item-access should always be obj[index], not
> obj[index] for some types, obj.get(index) for some others, and
> getitem(obj, index) for the rest.
>
> (Custom classes are, of course, free to break these guidelines, just as
> the numpy developers were free to have __nonzero__ raise an exception. One
> hopes they have good reasons for doing so.)
>
> And that's why Python not only allows but prefers "if any_object_at_all:"
> over type-dependent tricks. The *object itself* is supposed to know
> whether it is equivalent to true or false

But the objects idea of true and false may not be the most usefull
distinction the programmer wants to make. Look at the following
example:

  if container:
    Prepare()
    Treat(container)

Now Treat will throw an exception if container is not enough
list like. But that exception will be throw after Prepare has
done useless work in this case. If I replace "if container"
with "if len(container)" the exception will be thrown earlier.
So using "if len(container)" gives more usefull information
than a simple "if container".

> (or, in rare cases like numpy
> arrays, raise an exception if truth-testing doesn't mean anything for the
> type). You, the developer, are not supposed to spend your time wondering
> how to recognise if the object is equivalent to false, you just ask the
> object.
>
> If some well-meaning person argued that the correct way to test for a
> numeric value of zero/non-zero was like this:
>
> if x*2 != x:
>     # x must be non-zero
>
> you'd fall down laughing (at least, I hope you'd fall down laughing). Yes,
> such a test works, but you'd be crazy to do such unnecessary work if all
> you want to know if x was nonzero. (And beware of floating point rounding:
> what if x is tiny?)
>
> And then someone passes a class that implements infinity or the alephs to
> this function (that could simply mean an INF float on a platform that
> supports the IE standard) and the code wrongly decides that INF is zero.
> Oops.
>
> "if x == 0:" is better, but still not good enough, because you're
> still making assumptions about the data type. What if it is a numeric type
> that works with interval arithmetic? You don't know what the right way to
> test for a False interval is -- but the interval class itself will know.

But you have no idea that the interval of "False" will guide you to the
right branch. And inteval class might treat all zero length intervals
as False or it could have a special empty interval which would be the
only False interval. Both could be argued for, but you would want to
know which before you would rely on "if some_interval:" to guide
you to the right branch.

> And that's the point -- you're making unnecessary assumptions about the
> data, *and* doing unnecessary calculations based on those assumptions. At
> best, you're wasting your time. At worst, you're introducing bugs.

You have to make assumptions anyway. And your kind of code could
introduce bugs just the same.

> It isn't often that I make an appeal to authority, but this is one of
> them. No offense, but when it comes to language design its a brave or
> foolish programmer who bucks the language idioms that Guido chose.

You don't have to be that brave to go against Guido's autority. It
is only recently he introduced a ternary operator and then only after
someone in the development group was hit by a bug introduced by the
then supported idiom. Python is a nice enough language with a high
quality in design. Yet it still has its warts. So I see no
reason to blindly follow the autority of its designers.

-- 
Antoon Pardon



More information about the Python-list mailing list