Fwd: Boolean behavior of None
Hi all, I ran into an issue in expression evaluation with Python for Windows 2.7.3. Consider the following code: expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff. This code does not work. What happens on the 'flag' assignment row, is that if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None. To me as a primarily C++ programmer it seems there could be two different changes here, either change the behavior of the 'and' expression, forcing it to return Boolean even if the latter part is not evaluated, and/or make the comparison "False == None" return True. Although potentially complex, I'd myself go for the first approach. It seems to me more logical that False != None than an 'and' expression returning non-boolean. Also the latter change might require people change their code, while the former should not require any modifications. This behavior probably results in lots of errors when people like me, used to more traditional languages, take on Python in a serious manner. I like the concept 'pythonic', and am trying to apply it to practice like above. Hoping to hear your thoughts, Regards, Ilkka Pelkonen
On Thu, Jan 17, 2013 at 02:44:03PM +0200, Ilkka Pelkonen <ica@iki.fi> wrote:
expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff.
This code does not work. What happens on the 'flag' assignment row, is that if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None.
No need to change the language. Just do flag = bool(element and element.is_visible()) Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.
Hi Oleg, others, It's not that it can't be done, just that it does something you don't expect. I've been professionally working with C++ for nine years in large-scale Windows systems, and I do expect a boolean expression return a boolean value. Or, can you show me an example how the developer would benefit of the current behavior? Any operator traditionally considered as boolean will do. Regards, Ilkka On Thu, Jan 17, 2013 at 2:51 PM, Oleg Broytman <phd@phdru.name> wrote:
expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff.
This code does not work. What happens on the 'flag' assignment row, is
On Thu, Jan 17, 2013 at 02:44:03PM +0200, Ilkka Pelkonen <ica@iki.fi> wrote: that
if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None.
No need to change the language. Just do
flag = bool(element and element.is_visible())
Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN. _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
On Thu, Jan 17, 2013 at 03:10:45PM +0200, Ilkka Pelkonen <ilkka.pelkonen@iki.fi> wrote:
It's not that it can't be done, just that it does something you don't expect. I've been professionally working with C++ for nine years in large-scale Windows systems, and I do expect a boolean expression return a boolean value.
It does something Python developers expect. It's a well-known behaviour and there are many programs that rely on that behaviour.
Or, can you show me an example how the developer would benefit of the current behavior? Any operator traditionally considered as boolean will do.
address = user and user.address if address is None: raise ValueError("Unknown address") In the example neither user nor user.address are allowed to be None. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.
On 17 January 2013 11:10, Ilkka Pelkonen <ilkka.pelkonen@iki.fi> wrote:
Hi Oleg, others, It's not that it can't be done, just that it does something you don't expect. I've been professionally working with C++ for nine years in large-scale Windows systems, and I do expect a boolean expression return a boolean value.
Or, can you show me an example how the developer would benefit of the current behavior? Any operator traditionally considered as boolean will do.
Ikka, Python is a dynamic typed language. As such, there is no strict type checking for most operations. The behavior of boolean operations for Python 2.x is well defiend and described here: http://docs.python.org/2/reference/expressions.html#boolean-operations If you are testing for "truthfullness" of a given object, using the "==" value for that, as in your "if flag == expected_result:" is definetelly a non-recomended pratice. Objects that have False or True value have always been well defined in Python, and that definition follows common sense closely, on what should be False. No one would expect "None" to be True. The behavior of yielding the first part of the expression in a failed "and" operation is not unique to Python, and AFAIK, has been inspired from C - and there are tons of code which rely directly on this behavior. (Even though I'd agree a lot of this code, emulating the ternary operator in a time before it was available in Python 2.5 is very poorly written)
Regards, Ilkka
Le Thu, 17 Jan 2013 15:10:45 +0200, Ilkka Pelkonen <ilkka.pelkonen@iki.fi> a écrit :
Hi Oleg, others, It's not that it can't be done, just that it does something you don't expect. I've been professionally working with C++ for nine years in large-scale Windows systems, and I do expect a boolean expression return a boolean value.
"and" is not a boolean operator, it is a shortcutting control flow operator. Basically, what you are looking for is: flag = element.is_visible() if element else False (or, more explicitly: flag = element.is_visible() if element is not None else False ) Regards Antoine.
On 1/17/2013 8:10 AM, Ilkka Pelkonen wrote:
Hi Oleg, others, It's not that it can't be done, just that it does something you don't expect. I've been professionally working with C++ for nine years in large-scale Windows systems, and I do expect a boolean expression return a boolean value.
Or, can you show me an example how the developer would benefit of the current behavior? Any operator traditionally considered as boolean will do.
Regards, Ilkka
Ilkka, welcome to the Python community. Python is a wonderfully expressive language once you learn its subtleties. Python and C++ are different. If they weren't, we'd only have one language, not two. The short-circuiting operations "and" and "or" behave as they do for a reason. As an example, a common way to deal with default values: def accumulate(value, to=None): to = to or [] to.append(value) # Forget whether this is a good function or not.. return to If "or" always returned a boolean, as I'm assuming you'd prefer, then we'd have a much clumsier time defaulting values like this. --Ned.
On 17 January 2013 10:44, Ilkka Pelkonen <ica@iki.fi> wrote:
Hi all, I ran into an issue in expression evaluation with Python for Windows 2.7.3. Consider the following code:
expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff.
This code does not work. What happens on the 'flag' assignment row, is that if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None.
To me as a primarily C++ programmer it seems there could be two different changes here, either change the behavior of the 'and' expression, forcing it to return Boolean even if the latter part is not evaluated, and/or make the comparison "False == None" return True.
Hi Ikka.. My personal suggestion - rewrite your code to read: flag = bool(element and element.is_visible()) instead. That way you don't have to mention trying to change a 20 year old behavior in a language with billions of lines of code in the wild which should be kept compatible, at expense of thinking your expressions. Nor wait for the next major "4.0" release of Python for being able to write your code. js -><-
This change would break a lot of existing code and would make Python awkwardly stand out from all other modern dynamically typed languages (e.g. Ruby and JavaScript). You often write things like this: def foo(bar=None): bar = bar or [] ... Or: obj = obj and obj.property The proposed change would needlessly complicate these things and break existing code. Forcing a bool type really doesn't require that much code (bool(expr)) and is good practise anyway. On 01/17/2013 01:44 PM, Ilkka Pelkonen wrote:
Hi all, I ran into an issue in expression evaluation with Python for Windows 2.7.3. Consider the following code:
expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff.
This code does not work. What happens on the 'flag' assignment row, is that if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None.
To me as a primarily C++ programmer it seems there could be two different changes here, either change the behavior of the 'and' expression, forcing it to return Boolean even if the latter part is not evaluated, and/or make the comparison "False == None" return True. Although potentially complex, I'd myself go for the first approach. It seems to me more logical that False != None than an 'and' expression returning non-boolean. Also the latter change might require people change their code, while the former should not require any modifications.
This behavior probably results in lots of errors when people like me, used to more traditional languages, take on Python in a serious manner. I like the concept 'pythonic', and am trying to apply it to practice like above.
Hoping to hear your thoughts, Regards,
Ilkka Pelkonen
Thank you all. It was just that when I started with Python, everything worked right like I expected, and I found the ways to do anything I've needed all the way until today, so when I came across with this, it appeared to me a clear bug in the language/interpreter. Casting to bool is indeed a good solution and practice, and I do now agree that there's no point in changing the language - like Antoine said, we're talking control flow operators here, not exactly boolean. (This might be a good addition to the documentation.) Thank you Ned for the warm welcome and everyone for your input. I hope to be able to contribute in the future. :) Best Regards, Ilkka On Thu, Jan 17, 2013 at 6:07 PM, Mathias Panzenböck < grosser.meister.morti@gmx.net> wrote:
This change would break a lot of existing code and would make Python awkwardly stand out from all other modern dynamically typed languages (e.g. Ruby and JavaScript). You often write things like this:
def foo(bar=None): bar = bar or [] ...
Or:
obj = obj and obj.property
The proposed change would needlessly complicate these things and break existing code. Forcing a bool type really doesn't require that much code (bool(expr)) and is good practise anyway.
On 01/17/2013 01:44 PM, Ilkka Pelkonen wrote:
Hi all, I ran into an issue in expression evaluation with Python for Windows 2.7.3. Consider the following code:
expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff.
This code does not work. What happens on the 'flag' assignment row, is that if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None.
To me as a primarily C++ programmer it seems there could be two different changes here, either change the behavior of the 'and' expression, forcing it to return Boolean even if the latter part is not evaluated, and/or make the comparison "False == None" return True. Although potentially complex, I'd myself go for the first approach. It seems to me more logical that False != None than an 'and' expression returning non-boolean. Also the latter change might require people change their code, while the former should not require any modifications.
This behavior probably results in lots of errors when people like me, used to more traditional languages, take on Python in a serious manner. I like the concept 'pythonic', and am trying to apply it to practice like above.
Hoping to hear your thoughts, Regards,
Ilkka Pelkonen
______________________________**_________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/**mailman/listinfo/python-ideas<http://mail.python.org/mailman/listinfo/python-ideas>
To sum this up, I also thought of the None vs False issue some more, and found a use case which can bring a benefit for the separation: a function could normally return True or False, or None in a special case. Because of the separation, the developer can handle all the cases appropriately. Too little thinking, too much action. I wonder why I didn't google it this time, the issue is all over the net like any question you can imagine to ask, at least in case of Python. :) Sorry for the trouble. I'll stay around with a little lower profile. :) Regards again, Ilkka On Thu, Jan 17, 2013 at 7:03 PM, Ilkka Pelkonen <ilkka.pelkonen@iki.fi>wrote:
Thank you all. It was just that when I started with Python, everything worked right like I expected, and I found the ways to do anything I've needed all the way until today, so when I came across with this, it appeared to me a clear bug in the language/interpreter. Casting to bool is indeed a good solution and practice, and I do now agree that there's no point in changing the language - like Antoine said, we're talking control flow operators here, not exactly boolean. (This might be a good addition to the documentation.)
Thank you Ned for the warm welcome and everyone for your input. I hope to be able to contribute in the future. :)
Best Regards, Ilkka
On Thu, Jan 17, 2013 at 6:07 PM, Mathias Panzenböck < grosser.meister.morti@gmx.net> wrote:
This change would break a lot of existing code and would make Python awkwardly stand out from all other modern dynamically typed languages (e.g. Ruby and JavaScript). You often write things like this:
def foo(bar=None): bar = bar or [] ...
Or:
obj = obj and obj.property
The proposed change would needlessly complicate these things and break existing code. Forcing a bool type really doesn't require that much code (bool(expr)) and is good practise anyway.
On 01/17/2013 01:44 PM, Ilkka Pelkonen wrote:
Hi all, I ran into an issue in expression evaluation with Python for Windows 2.7.3. Consider the following code:
expected_result = (expected_string != 'TRUE') # Boolean element = find_element() # Can return None or an instance of Element flag = (element and element.is_visible()) if flag == expected_result: ..# Ok ..return # Otherwise perform some failure related stuff.
This code does not work. What happens on the 'flag' assignment row, is that if 'element' is None, the expression returns None, not False. This makes the if comparison to fail if expected_result is False, since boolean False is not None.
To me as a primarily C++ programmer it seems there could be two different changes here, either change the behavior of the 'and' expression, forcing it to return Boolean even if the latter part is not evaluated, and/or make the comparison "False == None" return True. Although potentially complex, I'd myself go for the first approach. It seems to me more logical that False != None than an 'and' expression returning non-boolean. Also the latter change might require people change their code, while the former should not require any modifications.
This behavior probably results in lots of errors when people like me, used to more traditional languages, take on Python in a serious manner. I like the concept 'pythonic', and am trying to apply it to practice like above.
Hoping to hear your thoughts, Regards,
Ilkka Pelkonen
______________________________**_________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/**mailman/listinfo/python-ideas<http://mail.python.org/mailman/listinfo/python-ideas>
participants (7)
-
Antoine Pitrou
-
Ilkka Pelkonen
-
Ilkka Pelkonen
-
Joao S. O. Bueno
-
Mathias Panzenböck
-
Ned Batchelder
-
Oleg Broytman