Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Implicit conversion to boolean in if and while statements (http://www.velocityreviews.com/forums/t948127-implicit-conversion-to-boolean-in-if-and-while-statements.html)

 Andrew Berg 07-15-2012 08:34 AM

Implicit conversion to boolean in if and while statements

This has probably been discussed before, but why is there an implicit
conversion to a boolean in if and while statements?

if not None:
print('hi')
prints 'hi' since bool(None) is False.

If this was discussed in a PEP, I would like a link to it. There are so
many PEPs, and I wouldn't know which ones to look through.

Converting 0 and 1 to False and True seems reasonable, but I don't see
the point in converting other arbitrary values.

--
CPython 3.3.0b1 | Windows NT 6.1.7601.17803

 Steven D'Aprano 07-15-2012 10:56 AM

Re: Implicit conversion to boolean in if and while statements

On Sun, 15 Jul 2012 03:34:46 -0500, Andrew Berg wrote:

> This has probably been discussed before,

By the hoary hosts of Hoggoth, has it ever!

> but why is there an implicit
> conversion to a boolean in if and while statements?

It's nothing to do with if and while. All Python objects are duck-typed
as bools.

1) It's generally part of the duck-typing philosophy. If an object quacks
like a bool, why not treat it as a bool?

2) It's useful and convenient for short-circuit boolean expressions such
as any(), all(), and various things like:

for x in mylist or []:
...

is better than:

if mylist is not None:
for x in mylist:
...

3) Rather than distinguishing "true" from "false", a more useful
dichotomy is between "something" and "nothing". Python includes a number
of ways of spelling "nothing" of various types, such as:

None, 0, 0.0, '', [], {}, set()

and nearly everything else is "something".

4) Other languages such as Ruby, Javascript, PHP, Clojure and others also
distinguish between true-like and false-like ("truthy" and "falsey")
values. Although some of them have made some pretty weird and arbitrary
choices for what counts as true-like and false-like, without Python's
general principle that "nothing" values should be false.

(E.g. Javascript considers Boolean(false) to be a true value!!!)

5) Prior to Python 2.2, there was no bool type and no True and False
values. In fact, here is an impassioned plea from an educator begging
Guido not to introduce True and False to the language, because duck-typed
truthy/falsey values are *so much better*.

Sadly, or happily, Python did grow True and False values, but the
fundamental distinction between something and nothing still exists.

(For the record, I can only think of one trap for the unwary: time
objects are false at *exactly* midnight.)

--
Steven

 Ian Kelly 07-15-2012 04:19 PM

Re: Implicit conversion to boolean in if and while statements

On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> (For the record, I can only think of one trap for the unwary: time
> objects are false at *exactly* midnight.)

Ugh, that's irritating. I can't think of any scenario where I would
ever want the semantics "if timeval (is not midnight):". This
reinforces the point that if you only want to test whether you have
None, you should use "is not None" rather than relying on __bool__.

 Rick Johnson 07-15-2012 04:50 PM

Re: Implicit conversion to boolean in if and while statements

On Sunday, July 15, 2012 11:19:16 AM UTC-5, Ian wrote:
> On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
> > (For the record, I can only think of one trap for the unwary: time
> > objects are false at *exactly* midnight.)

>
> Ugh, that's irritating. I can't think of any scenario where I would
> ever want the semantics "if timeval (is not midnight):". This
> reinforces the point that if you only want to test whether you have
> None, you should use "is not None" rather than relying on __bool__.

I think this issue is not so much a "bool test" vs "type test", but more anambiguous syntax issue. Consider this:

## EXAMPLE A ##
py> if money:
.... do_something()

The syntax "if money" implies we are testing/measuring some attribute of "money", but what exactly about money are we testing/measuring? The problem lies in the syntax. To understand this syntax, we must first interpret what *IF* means, and we should *NEVER* need to interpret such a well defined word as *IF*! This syntax is far too opaque. Consider the alternative:

## EXAMPLE B ##
py> if bool(money):
.... do_something()

Now we have a hint. Even if we don't understand the inner workings of the "bool" function, we *do* understand that the statement "bool(money)" *must* return True or the block *will not* execute.

We must NEVER present "if" in such confusing manner as ExampleA. I believe Guido made a grave mistake allowing this syntax to flourish. His intentionswhere noble, to save people a few keystrokes, but all he accomplished was to pave a road directly into hell.

"Explict is better than Implict"

 Rick Johnson 07-15-2012 04:50 PM

Re: Implicit conversion to boolean in if and while statements

On Sunday, July 15, 2012 11:19:16 AM UTC-5, Ian wrote:
> On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
> > (For the record, I can only think of one trap for the unwary: time
> > objects are false at *exactly* midnight.)

>
> Ugh, that's irritating. I can't think of any scenario where I would
> ever want the semantics "if timeval (is not midnight):". This
> reinforces the point that if you only want to test whether you have
> None, you should use "is not None" rather than relying on __bool__.

I think this issue is not so much a "bool test" vs "type test", but more anambiguous syntax issue. Consider this:

## EXAMPLE A ##
py> if money:
.... do_something()

The syntax "if money" implies we are testing/measuring some attribute of "money", but what exactly about money are we testing/measuring? The problem lies in the syntax. To understand this syntax, we must first interpret what *IF* means, and we should *NEVER* need to interpret such a well defined word as *IF*! This syntax is far too opaque. Consider the alternative:

## EXAMPLE B ##
py> if bool(money):
.... do_something()

Now we have a hint. Even if we don't understand the inner workings of the "bool" function, we *do* understand that the statement "bool(money)" *must* return True or the block *will not* execute.

We must NEVER present "if" in such confusing manner as ExampleA. I believe Guido made a grave mistake allowing this syntax to flourish. His intentionswhere noble, to save people a few keystrokes, but all he accomplished was to pave a road directly into hell.

"Explict is better than Implict"

 Andrew Berg 07-15-2012 05:02 PM

Re: Implicit conversion to boolean in if and while statements

On 7/15/2012 5:56 AM, Steven D'Aprano wrote:
> 3) Rather than distinguishing "true" from "false", a more useful
> dichotomy is between "something" and "nothing". Python includes a number
> of ways of spelling "nothing" of various types, such as:
>
> None, 0, 0.0, '', [], {}, set()
>
> and nearly everything else is "something".

Okay, I see the value in this, but I don't understand why None has a
truth value. I would expect None to mean "doesn't exist" or "unknown" or
something like that - e.g., a value of 0 means 0 jelly beans in the jar
and None means there isn't a jar.

FWIW, I have, for a reason I forget, gotten into the habit of writing
"if x is not None" when testing for None. However, I have not been
writing "if x is True: ..."/"elif x is False: ..."/"else: 'ruh-roh'"
when testing for True (in cases where a value of True or False makes
sense, but any other value would not). Should I?

--
CPython 3.3.0b1 | Windows NT 6.1.7601.17803

 Andrew Berg 07-15-2012 05:16 PM

Re: Implicit conversion to boolean in if and while statements

On 7/15/2012 11:19 AM, Ian Kelly wrote:
> Ugh, that's irritating. I can't think of any scenario where I would
> ever want the semantics "if timeval (is not midnight):".

It's not implemented with such a test, but
logging.handlers.TimedRotatingFileHandler has an option to rollover at
midnight.
--
CPython 3.3.0b1 | Windows NT 6.1.7601.17803

 Ian Kelly 07-15-2012 05:45 PM

Re: Implicit conversion to boolean in if and while statements

On Sun, Jul 15, 2012 at 11:16 AM, Andrew Berg <bahamutzero8825@gmail.com> wrote:
> On 7/15/2012 11:19 AM, Ian Kelly wrote:
>> Ugh, that's irritating. I can't think of any scenario where I would
>> ever want the semantics "if timeval (is not midnight):".

> It's not implemented with such a test, but
> logging.handlers.TimedRotatingFileHandler has an option to rollover at
> midnight.

Nor could it be implemented with such a test, since the rollover check
would then have to run at exactly midnight for the test to evaluate
false. If it were off by 1 microsecond, it would miss it.

 Ian Kelly 07-15-2012 06:01 PM

Re: Implicit conversion to boolean in if and while statements

On Sun, Jul 15, 2012 at 10:50 AM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> I think this issue is not so much a "bool test" vs "type test", but more an ambiguous syntax issue. Consider this:
>
> ## EXAMPLE A ##
> py> if money:
> ... do_something()
>
> The syntax "if money" implies we are testing/measuring some attribute of "money", but what exactly about money are we testing/measuring? The problemlies in the syntax. To understand this syntax, we must first interpret what *IF* means, and we should *NEVER* need to interpret such a well defined word as *IF*! This syntax is far too opaque. Consider the alternative:
>
> ## EXAMPLE B ##
> py> if bool(money):
> ... do_something()
>
> Now we have a hint. Even if we don't understand the inner workings of the"bool" function, we *do* understand that the statement "bool(money)" *must* return True or the block *will not* execute.

So now instead of having to understand how "if" handles arbitrary
values, we have to understand how "bool" handles arbitrary values.
How is that an improvement?

What should "if" do if presented a value that isn't True or False?
Raise a TypeError?

Next thing we know, people get so used to wrapping everything they
present to "if" in a "bool()" call, that they start writing silly
things like "if bool(x == 7)" and "if bool(isinstance(x, int))". Why?
Because it's faster and easier to automatically wrap the value in
"bool" than it is to put in the effort to verify that the value will
always be a bool to begin with in order to avoid a useless and
annoying exception. At the point that happens, the "bool()" is
effectively just part of the if syntax, and we're back to where we
started.

 Rick Johnson 07-15-2012 06:56 PM

Re: Implicit conversion to boolean in if and while statements

On Sunday, July 15, 2012 1:01:58 PM UTC-5, Ian wrote:

> So now instead of having to understand how "if" handles arbitrary
> values, we have to understand how "bool" handles arbitrary values.
> How is that an improvement?

Because we are keeping the condition consistent. We are not relying on implicit resolution of an object's value based on some dark, esoteric and inconsistent rules that defy all normal logic.

> What should "if" do if presented a value that isn't True or False?
> Raise a TypeError?

YES! Because IT IS the author's responsibility to present a condition that evaluates to either True or False. Anything else would be ridiculously inconsistent.

> Next thing we know, people get so used to wrapping everything they
> present to "if" in a "bool()" call, that they start writing silly
> things like "if bool(x == 7)" and "if bool(isinstance(x, int))".

We cannot prevent morons from doing stupid things. "x==7" IS an explicit statement that evaluates to either True or False. Likewise, isinstance(obj, type) is a function that evaluates to either True or False. Wrapping either example in a bool call is redundant and only obfuscates the meaning. True equals True and False equal False. Why do you need to test that truth?

The only time you will be forced to use the bool is when you are NOT using rich comparisons or NOT using truth testing functions in a condition. The following require NO bool function:

obj == obj -> bool
obj != obj -> bool
obj > obj -> bool
obj < obj -> bool
obj >= obj -> bool
obj <= obj -> bool
isinstance(obj, type) -> bool
callable(obj) -> bool
hasattr(obj, name) -> bool
issubclass(obj, name) -> bool
...along with any function that returns a bool

Whereas:
"if obj" -> Some esoteric semantics that defies all logic!

> Why?
> Because it's faster and easier to automatically wrap the value in
> "bool" than it is to put in the effort to verify that the value will
> always be a bool to begin with in order to avoid a useless and
> annoying exception.

No, because we want our code to be EXPLICIT and consistent! Remember, writing obfuscated code is easy, however, interpreting obfuscated code is difficult! A good measure of your programming skill is to see how easily your code is read by the majority.

"""If it's difficult to explain, it's probably a bad idea""".

"if blah" is difficult to explain, whereas "if bool(blah)" is not.

> At the point that happens, the "bool()" is
> effectively just part of the if syntax, and we're back to where we
> started.

That's a ridiculous conclusion. See points above^^^

All times are GMT. The time now is 07:01 PM.