This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Clarify Boolean Clause Results
Type: enhancement Stage: resolved
Components: Documentation Versions: Python 3.4
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, ethan.furman, josh.r, jpotelle, r.david.murray
Priority: normal Keywords:

Created on 2015-01-02 22:13 by jpotelle, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (8)
msg233330 - (view) Author: John Potelle (jpotelle) Date: 2015-01-02 22:13
From v3.4 Tutorial section 5.7

It is possible to assign the result of a comparison or other Boolean expression to a variable. For example,
>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> string1 or string2 or string3
'Trondheim'
>>> bool(string1 or string2 or string3)
True

In most languages a Boolean clause (comparison) returns a Boolean or it's equivalent, not the last argument evaluated.  Please add a reference to bool function (or some better? method) in this section for clarification.
msg233334 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2015-01-03 00:12
A few questions/comments:

1. How would the reference clarify matters?

2. "Most languages" is perhaps overstating the matter. Lower level languages and strictly typed languages tend to return a boolean value, but many high level scripting languages (among them Perl, Python and JavaScript) return the last value evaluated.

3. Referencing the bool() constructor doesn't seem like it would add much, and might encourage the wrong behaviors; idiomatic Python rarely bothers to coerce to True/False because it's unnecessary extra work when an if or while condition can simply evaluate the "truthiness" of the value being tested without coercion. I kind of like the fact that it omits use of bool(), because down that road lies madness (if bool(a or b) == False: madness).
msg233345 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2015-01-03 04:07
`or` does not return the last item evaluated -- it returns the first truthy item, or, if no truthy items, the last false item:

  --> 0 or {}
  {}
  --> 0 or 1 or {}
  1
msg233356 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-01-03 13:19
Indeed, the short circuit and value return behavior is described in that section just before the example.

I agree with Joel.  This is a tutorial, and part of the zen of Python is that all expressions have a boolean value.  There are very few places in python programs where it would be considered Pythonic to "cast" a value to one of the two uniquely boolean values via the Bool operator, so it is better that it *not* be mentioned in this context.
msg233359 - (view) Author: John Potelle (jpotelle) Date: 2015-01-03 16:00
I'm learning Python and informing you this is confusing - and you close the ticket without hearing any response to your questions?

Re: Josh
1. To show how to return a Boolean result from a Boolean clause. If there's a better way, I'm all for it.
2. "Most" is a generalization. Perhaps "Many" is a better term? All traditional 3GLs and some other scripting languages don't; e.g. REXX and Beanshell return Boolean. But it's not important here. 
3. As I said, "or some better method". I've been programming 30 years but am only now learning Python. All I asking for is better clarification in the tutorial. If this were a wiki I would add one myself.

Re: Ethan; quote from the line above, same section in the Tutorial:
"When used as a general value and not as a Boolean, the return value of a short-circuit operator is the last evaluated argument." If this isn't correct, please fix it. And this whole sentence is a bit weird to me - Boolean operators are *always* used in a Boolean context - unless the op is overloaded with some other functionality. Why would it return anything else? (well let's not go there...)

Re: R.David
Sorry I didn't see any input from "Joel". But, yes, this is a tutorial.

I argue that using A = (B or C or D) construct is not good, intuitive programming style, anyway. To me this looks like A should hold a Boolean, even only from a pseduocode standpoint. Even so, one wouldn't need to "cast" a Boolean if a Boolean was returned, as old programmers like me would expect. 

But, OK, so don't use bool() - but what you said is basically what I'm looking for IN the tutorial - eduction about why a Boolean should NOT be expected. Or how to achieve a Boolean, since it's a valid data type since version 2.3. This is a tutorial, after all.

For example, the full documentation for v3.4 section 4.1: "Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)". Even here the docs says this is an "exception".
msg233363 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2015-01-03 18:57
Apologies, my wording was poor -- the last item evaluated is the one returned, but all items may not be evaluated.  As soon as the answer is known Python stops evaluating any remaining items.

So in the example:

  --> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
  --> string1 or string2 or string3
  'Trondheim'

string2 is returned because it satifies the `or` conditions, and string3 is not evaluated.


Re: John

I appreciate you have many years of programming experience, but there are going to be differences between what is good practice in those languages and what is good practice in Python.  IMO, the big three differences are:

  - white space indentation
  - everything is an object (variables, functions, classes, instances,
    any piece of data...)
  - everything has a truthy of falsey value -- e.g.

    --> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
    --> if string2:
    ...    print('string2 has a value!  It is %s' % string2)
    ...
    'string2 has a value!  It is Trondheim'

    notice there is no `if bool(string2)` or `if string2 == False` (which would be False).

As far as finding that bit of the tutorial confusing, there is no way to have a single document that is crystal clear to everyone who reads it.  This section is correct, as is section 4.1 -- `or` is being used, so the operand is returned, not True or False.
msg233373 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-01-03 22:22
I mistyped 'josh' as 'joel', sorry.

Ethan covers it pretty well, but I'll add a few things.

Boolean operators are indeed not always used in a boolean context.  There is a long tradition in Python of using them to return values via the short-circuit mechanism.  Python is not the only language that does this.

That said, there are disadvantages to that use of boolean operators, and eventually the trinary expression 'x if y else z' was introduced, and is now the preferred way to compute such values.  The tutorial has not been updated to reflect that, and that is something that could be done, but probably requires a significant rewrite...someone on irc pointed out that the passage we are discussing is the first introduction of 'or' in the tutorial).  However, the short-circuit-and-value-returning behavior of the boolean operators will not change, since it is a long standing part of the language.

Your suggestion that this whole thing be discussed more is a valid point, but the question is, is this point in the tutorial the place to do it?  Again, a more extensive rewrite is probably needed in order to make a real improvement (a project that is being discussed, whose status I don't know).

Finally, the 4.1 text you quote is noting and/or as an exception is talking about the built-in functions and operators.  and and or are important exceptions both because their default is different from other logical operations and because, unlike the other python operators, a type cannot override them.  Thus they always return a value, whereas other *logical* operations will return a boolean *unless otherwise documented* in the documentation for the type.  (I'm not sure there are any exceptions to that in the sdtlib, but there are, for example, in numpy.)

Now, that all said, the tutorial section explicitly mentions the behavior of and and or, so I don't see how their being exceptional in this regard is an issue with the tutorial text.  If you assigned another logical expression to a variable, you'd get True or False, but in Python's philosophy that's just a special case of the fact that all values in python have a truth value, as discussed by Ethan.

So, in summary, I hear you that as an experienced programmer this tutorial section did not give you all the information you wanted.  However, it is a *tutorial*, and so it *can't* (and be a readable *tutorial*) cover all the issues.  Perhaps it could cover more if it were rewritten, but I don't think changing this section in any of the ways suggested so far would, as it is currently organized, be an improvement.  If anyone wants to take another stab at it, though, we'll definitely evaluate it.

willingc on IRC suggested adding links to other parts of the docs, for further reading, and that might be worthwhile if someone wants to take  a look at making a suggestion in that regard.
msg233382 - (view) Author: John Potelle (jpotelle) Date: 2015-01-04 01:10
Thank you for your reasoned responses. I'm beginning to see just how much Python is its own animal. This and/or thing has history; I get it. Links back to the reference documentation is a good idea.
History
Date User Action Args
2022-04-11 14:58:11adminsetgithub: 67342
2015-01-04 01:10:04jpotellesetmessages: + msg233382
2015-01-03 22:22:24r.david.murraysetmessages: + msg233373
2015-01-03 18:57:26ethan.furmansetmessages: + msg233363
2015-01-03 16:00:38jpotellesetmessages: + msg233359
2015-01-03 13:19:57r.david.murraysetstatus: open -> closed

nosy: + r.david.murray
messages: + msg233356

resolution: not a bug
stage: resolved
2015-01-03 04:07:36ethan.furmansetnosy: + ethan.furman
messages: + msg233345
2015-01-03 00:12:33josh.rsetnosy: + josh.r
messages: + msg233334
2015-01-02 22:13:42jpotellecreate