Programming recommendations (PEP 8) and boolean values

Hey all, True and False are singletons, so if you want to check precisely for True and False then an identity check seems appropriate. However the "Programming Recommendations" section of PEP 8 has this to say on the topic: Don't compare boolean values to True or False using ==. Yes: if greeting: No: if greeting == True: Worse: if greeting is True: http://www.python.org/dev/peps/pep-0008/#programming-recommendations It seems to me that there is an important distinction between testing that an object is either the boolean True or False and merely checking the "truthiness" of an object. Many a bug has been caused by an empty container object (or some other falsey object) falling into an "if not value" clause that was actually meant to check for the presence of False or None. Why does PEP 8 recommend not testing "boolean values" (which to me implies "values you expect to be a bool") using equality or identity, and more specifically why does it say that using an identity check is worse than an equality check? As this is Python-ideas and not python-list, my specific suggestion is to modify the wording of that section - or just removing it altogether as I don't think it can be adequately clarified without using lots of words. All the best, Michael Foord -- http://www.voidspace.org.uk/ May you do good and not evil May you find forgiveness for yourself and forgive others May you share freely, never taking more than you give. -- the sqlite blessing http://www.sqlite.org/different.html

I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.) --Guido On Wednesday, August 8, 2012, Michael Foord wrote:
Hey all,
True and False are singletons, so if you want to check precisely for True and False then an identity check seems appropriate.
However the "Programming Recommendations" section of PEP 8 has this to say on the topic:
Don't compare boolean values to True or False using ==.
Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
http://www.python.org/dev/peps/pep-0008/#programming-recommendations
It seems to me that there is an important distinction between testing that an object is either the boolean True or False and merely checking the "truthiness" of an object. Many a bug has been caused by an empty container object (or some other falsey object) falling into an "if not value" clause that was actually meant to check for the presence of False or None.
Why does PEP 8 recommend not testing "boolean values" (which to me implies "values you expect to be a bool") using equality or identity, and more specifically why does it say that using an identity check is worse than an equality check?
As this is Python-ideas and not python-list, my specific suggestion is to modify the wording of that section - or just removing it altogether as I don't think it can be adequately clarified without using lots of words.
All the best,
Michael Foord
--
May you do good and not evil
May you find forgiveness for yourself and forgive others May you share freely, never taking more than you give. -- the sqlite blessing http://www.sqlite.org/different.html
-- --Guido van Rossum (python.org/~guido)

On 09/08/12 00:28, Guido van Rossum wrote:
I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
Furthermore, the problem with testing flags for their truth-value (truthiness) using "flag is True" is that you never know when to stop, since the comparison also returns a flag which needs to be checked for its truth-value: if (flag is True) is True is True is True is ... # and so on ad infinitum which of course is absurd. If you can trust the truthiness of "flag is True", you can also trust the truthiness of flag on its own. If you truly need to check that flag is not only a true-value, but is specifically the bool True, then "flag is True" might be acceptable, provided it was clear in context why you were doing that. (But why would you need to? Presumably that should be a rare occurrence.) An isinstance check makes it obvious that the type matters. "type(flag) is bool" makes it even more obvious that you want a bool and nothing but a bool, not even a subclass. I note, however, that all three of CPython, IronPython and Jython prohibit you from subclassing bool, but this seems to be an implementation detail. At least, it isn't documented as a language requirement here: http://docs.python.org/py3k/library/stdtypes.html#boolean-values Coming back to Paul's request to modify the wording, I think that it is fine as it stands. We know that PEP 8 allows breaking the rules when necessary. Not every exception to PEP 8 needs to be explicitly documented, and we shouldn't dilute the message that "if flag" is the idiomatic Pythonic way to test a flag by talking about the rare case where it isn't. -- Steven

Le 08/08/2012 16:28, Guido van Rossum a écrit :
I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
That said, I'm also curious about the answer to Michael's following question: “why does it say that using an identity check is worse than an equality check?” Regards Antoine.

On Thu, Aug 9, 2012 at 10:15 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:
Le 08/08/2012 16:28, Guido van Rossum a écrit :
I'd be strongly against changing that rule. If you don't want other
types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
That said, I'm also curious about the answer to Michael's following question: “why does it say that using an identity check is worse than an equality check?”
In python 3.2.3: >>> 1 == True True * >>> 13 == True* * False* >>> bool(1) True >>> bool(13) True >>> 1 is True False >>> 13 is True False To my surprise identity is actually less confusing than equality. So I agree with Antoine and Michael on that point.

In [1]: True + True Out[1]: 2 I think Python 4 should raise ValueError. On Thu, Aug 9, 2012 at 4:35 PM, Yuval Greenfield <ubershmekel@gmail.com> wrote:
On Thu, Aug 9, 2012 at 10:15 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:
Le 08/08/2012 16:28, Guido van Rossum a écrit :
I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
That said, I'm also curious about the answer to Michael's following question: “why does it say that using an identity check is worse than an equality check?”
In python 3.2.3:
>>> 1 == True True >>> 13 == True False >>> bool(1) True >>> bool(13) True >>> 1 is True False >>> 13 is True False
To my surprise identity is actually less confusing than equality. So I agree with Antoine and Michael on that point.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- INADA Naoki <songofacandy@gmail.com>

I think you're reading to much into the "is". Sure, "x is True" reads like "x has the property of being true", but that's not what the "is" operator is all about. It's about an identity check that works fine when you want to check for identity, but doesn't otherwise. For "None" and other singletons, the "is" operator is the perfect choice, since it avoids programming errors and is a very fast way to check a value against the singleton. For non-singletons, "is" rarely makes sense and can indeed introduce programming errors. Now, True and False are singletons in their own right, but they are also special integers 1 and 0, nothing more, nothing less. So if you are interested in checking whether a function does indeed use these special integers, you can use the "is" operator, but apart from testing, where this may sometimes be needed, the much more common use case is not to check for the special integers, but instead check for property of the return value, i.e. whether the return value has the true property or not and you usually apply that check in a different way: if x: print 'true assumption' else: print 'false assumption' By checking just for the True singleton, it is well possible that you'll miss a lot of other true values, e.g. 42 is true, but a different integer, so "42 is True" will return false. Likewise, checking for False won't catch the 0.0 float value, an empty string or an empty list. INADA Naoki wrote:
In [1]: True + True Out[1]: 2
I think Python 4 should raise ValueError.
On Thu, Aug 9, 2012 at 4:35 PM, Yuval Greenfield <ubershmekel@gmail.com> wrote:
On Thu, Aug 9, 2012 at 10:15 AM, Antoine Pitrou <solipsis@pitrou.net> wrote:
Le 08/08/2012 16:28, Guido van Rossum a écrit :
I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
That said, I'm also curious about the answer to Michael's following question: “why does it say that using an identity check is worse than an equality check?”
In python 3.2.3:
>>> 1 == True True >>> 13 == True False >>> bool(1) True >>> bool(13) True >>> 1 is True False >>> 13 is True False
To my surprise identity is actually less confusing than equality. So I agree with Antoine and Michael on that point.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Aug 09 2012)
Python/Zope Consulting and Support ... http://www.egenix.com/ mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
2012-08-25: FrOSCon, St. Augustin, Germany ... 16 days to go ::: Try our new mxODBC.Connect Python Database Interface for free ! :::: eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/

Yuval Greenfield writes:
In python 3.2.3:
>>> 1 == True True * >>> 13 == True* * False* >>> bool(1) True >>> bool(13) True >>> 1 is True False >>> 13 is True False
To my surprise identity is actually less confusing than equality. So I agree with Antoine and Michael on that point.
FWIW, I don't find any of the above confusing. "1 == True" => True is unexpected in some sense, but I don't find it counter-intuitive, and I find the "don't break old code" rationale satisfactory. Inada-san's example of addition is a little disconcerting in that particular spelling. But sum(predicate(x) for x in seq) seems preferable to a boolean-specific count function, and it generalizes nicely to the creation of dummy variables in statistical applications. Steve

They're both equally bad IMO. On Thursday, August 9, 2012, Antoine Pitrou wrote:
Le 08/08/2012 16:28, Guido van Rossum a écrit :
I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
That said, I'm also curious about the answer to Michael's following question: “why does it say that using an identity check is worse than an equality check?”
Regards
Antoine.
______________________________**_________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/**mailman/listinfo/python-ideas<http://mail.python.org/mailman/listinfo/python-ideas>
-- --Guido van Rossum (python.org/~guido)

On 09/08/12 17:15, Antoine Pitrou wrote:
Le 08/08/2012 16:28, Guido van Rossum a écrit :
I'd be strongly against changing that rule. If you don't want other types than bool, use an isinstance check. Code using "is True" is most likely a bug. (It's different for None, since that has no second value that is assumed.)
That said, I'm also curious about the answer to Michael's following question: “why does it say that using an identity check is worse than an equality check?”
1) Identity checks put the emphasis on the wrong thing: object identity rather than value. Why do you care that True and False are singletons? Your algorithm almost certainly does not depend on that fact. And who knows? Perhaps some day your code will be running on some Python implementation which fails to enforce True and False being singletons. 2) In old code, 0 and 1 were the idiomatic flags. 0 == False and 1 == True, but if you use identity checks, your code will unnecessarily break old code. Postel's Law (the Robustness Principle) tells us that we should be strict in what we send and liberal in what we accept. This rule has greater applicability than just networking. It tells us that when returning a boolean flag, we should strictly always return True or False. But when accepting a boolean flag as argument to our function, we should not unnecessarily limit what counts as a valid argument. So in order of preference: 1) under most circumstances, we should accept duck-typed truthy values (e.g. use "if x") as the most liberal way to test a flag in Python; 2) if we have a good reason not to duck-type a flag, then next best is to compare by value, not identity ("if x == True"); 3) least preferred (worst) is to be a Boolean Fascist and only accept True and False by identity ("if x is True"). There may be some cases where you rightly wish to insist on an actual bool rather than any truthy or falsey value, but that should be the exception rather than the rule. -- Steven

Michael Foord <fuzzyman@gmail.com> writes:
True and False are singletons, so if you want to check precisely for True and False then an identity check seems appropriate.
What is a compelling use case for checking precisely for True or False? Why is a simple boolean expression (‘if foo’) not good enough? I can't think of any code checking precisely for True or False that wouldn't be much improved by using different values altogether. But maybe you have code examples that would be convincing.
It seems to me that there is an important distinction between testing that an object is either the boolean True or False and merely checking the "truthiness" of an object.
The distinction is real and important, but that doesn't make both sides useful or that one shouldn't be deprecated.
Many a bug has been caused by an empty container object (or some other falsey object) falling into an "if not value" clause that was actually meant to check for the presence of False or None.
What bugs do you have in mind? -- \ “I see little commercial potential for the Internet for at | `\ least ten years.” —Bill Gates, 1994 | _o__) | Ben Finney

On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On Wed, Aug 8, 2012 at 9:59 AM, Oleg Broytman <phd@phdru.name> wrote:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney < ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
I'd probably write that this way: if t is None: # not specified elif t: # true else: # false on the other hand, if I had a variable that could be either a number or True/False, I would probably write: if t is True: # elif t is False: # else: # use t as a number just as I would for any other singleton value. Why does the PEP say that == True is preferred to is True? --- Bruce Follow me: http://www.twitter.com/Vroo http://www.vroospeak.com

On 09/08/12 03:27, Bruce Leban wrote:
On Wed, Aug 8, 2012 at 9:59 AM, Oleg Broytman<phd@phdru.name> wrote:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney< ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
I'd probably write that this way:
if t is None: # not specified elif t: # true else: # false
Which treats None specially, otherwise falls back to the standard Python concept of truth-value or truthiness. Which is just a form of duck-typing.
on the other hand, if I had a variable that could be either a number or True/False, I would probably write:
This sounds like poor design to me, but okay, for the sake of the argument, let's accept that you do.
if t is True: # elif t is False: # else: # use t as a number
just as I would for any other singleton value.
Keeping the duck-typing of truth-values: if isinstance(t, numbers.Number) and not isinstance(t, bool): ... elif t: # True, or any other true-like value ... else: # False, or any other false-like value pass There are many subtle variations on this. We surely don't need, or want, to have to cover them in PEP 8.
Why does the PEP say that == True is preferred to is True?
Because there surely are still libraries out there that return 0 and 1 as true/false values. The bool type was introduced in (by memory) Python 2.2 or 2.3, so very old code may fail, or worse, silently do the wrong thing if you use "is True". -- Steven

On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False? To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Oleg. Other cases: 1) I have written a function that returns True, False or a string error message. (No doubt an Exception-subclass object might be better
On 08/08/2012 17:59, Oleg Broytman wrote: style.) So sometimes I really want to test if the result "is True". 2) Say you are writing a function to process an arbitrary object, e.g. a custom version of repr. You might well choose to write if obj is True: # processing elif obj is False: # processing elif type(obj) is int: # processing # etc. etc. I am sure the examples could be multiplied. I can see no reason why we should be discouraged from writing if x is True: if that is really what we mean (and need) and not just a verbose way of spelling "if x:". Also I find the advice that if x is True: is worse than if x==True: baffling. I have been taught that the former executes faster, and indeed when I test it I find it is (significantly faster). What is the rationale? Rob Cliffe

On 08.08.2012 19:53, Rob Cliffe wrote:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False? To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Oleg. Other cases: 1) I have written a function that returns True, False or a string error message. (No doubt an Exception-subclass object might be better
On 08/08/2012 17:59, Oleg Broytman wrote: style.)
Using the (only) return value for either a result or an error indication is ugly and error-prone. It is what makes many APIs painful in languages that don't have the comfort of e.g. returning a tuple (result, error or None). Not to mention that there's nothing wrong with raising exceptions.
So sometimes I really want to test if the result "is True". 2) Say you are writing a function to process an arbitrary object, e.g. a custom version of repr. You might well choose to write if obj is True: # processing elif obj is False: # processing elif type(obj) is int: # processing # etc. etc. I am sure the examples could be multiplied. I can see no reason why we should be discouraged from writing if x is True: if that is really what we mean (and need) and not just a verbose way of spelling "if x:".
Yeah, just that in most cases that is not really what "we" mean. And if it is, why do you feel discouraged anyway?
Also I find the advice that if x is True: is worse than if x==True: baffling. I have been taught that the former executes faster, and indeed when I test it I find it is (significantly faster). What is the rationale?
Because in most cases you want to accept 1 and 0 too for True and False. For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug. cheers, Georg

Le mercredi 08 août 2012 à 22:29 +0200, Georg Brandl a écrit :
On 08.08.2012 19:53, Rob Cliffe wrote:
On 08/08/2012 17:59, Oleg Broytman wrote:
Also I find the advice that if x is True: is worse than if x==True: baffling. I have been taught that the former executes faster, and indeed when I test it I find it is (significantly faster). What is the rationale?
Because in most cases you want to accept 1 and 0 too for True and False.
For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug.
But do you really want to accept 1.0 but reject 1.0001? I would say that using "x == True" is the stealthier bug:
def do_stuff(n): ... a = 1; a /= n; a *= n ... if a == True: ... return 0 ... else: ... return "BOOM!" ... [do_stuff(n) for n in range(42, 54)] [0, 0, 0, 0, 0, 0, 0, 'BOOM!', 0, 0, 0, 0]
-- Ronan Lamy <ronan.lamy@gmail.com>

For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug. It's easy to make other objects == None, by writing buggy __eq__ methods. That doesn't happen much, but it's easier with __ne__, where
On 8/8/2012 4:29 PM, Georg Brandl wrote: the negated logic is easy to screw up. I've seen it happen. Use "is None", not "== None". --Ned.

On 08.08.2012 23:56, Ned Batchelder wrote:
For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug. It's easy to make other objects == None, by writing buggy __eq__ methods. That doesn't happen much, but it's easier with __ne__, where
On 8/8/2012 4:29 PM, Georg Brandl wrote: the negated logic is easy to screw up. I've seen it happen. Use "is None", not "== None".
That's true indeed. Georg

On 09/08/2012 06:48, Georg Brandl wrote:
On 08.08.2012 23:56, Ned Batchelder wrote:
For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug. It's easy to make other objects == None, by writing buggy __eq__ methods. That doesn't happen much, but it's easier with __ne__, where
On 8/8/2012 4:29 PM, Georg Brandl wrote: the negated logic is easy to screw up. I've seen it happen. Use "is None", not "== None".
That's true indeed.
Georg
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
Surely that's a reason to fix the buggy __eq__ and __ne__ methods, not to avoid using them. (Sorry Georg I accidentally replied to you not to the list.) Rob Cliffe

On 8/9/2012 4:09 AM, Rob Cliffe wrote:
On 09/08/2012 06:48, Georg Brandl wrote:
On 08.08.2012 23:56, Ned Batchelder wrote:
For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug. It's easy to make other objects == None, by writing buggy __eq__ methods. That doesn't happen much, but it's easier with __ne__, where
On 8/8/2012 4:29 PM, Georg Brandl wrote: the negated logic is easy to screw up. I've seen it happen. Use "is None", not "== None".
That's true indeed.
Georg
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
Surely that's a reason to fix the buggy __eq__ and __ne__ methods, not to avoid using them. (Sorry Georg I accidentally replied to you not to the list.)
Of course you should fix those. But if the two methods are "equivalent" except one isn't susceptible to this sort of error, why not recommend and use the more robust technique? Use "is None", not "== None". --Ned.
Rob Cliffe
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas

On 09/08/12 18:09, Rob Cliffe wrote:
On 09/08/2012 06:48, Georg Brandl wrote:
On 08.08.2012 23:56, Ned Batchelder wrote:
For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug. It's easy to make other objects == None, by writing buggy __eq__ methods. That doesn't happen much, but it's easier with __ne__, where
On 8/8/2012 4:29 PM, Georg Brandl wrote: the negated logic is easy to screw up. I've seen it happen. Use "is None", not "== None".
[...]
Surely that's a reason to fix the buggy __eq__ and __ne__ methods, not to avoid using them. (Sorry Georg I accidentally replied to you not to the list.)
It may not be in your power to fix the buggy method, because it may be in the caller's code, not yours. Or it may not even be a bug -- maybe the caller has some good reason for wanting his object to compare equal to None. If I write a function like this: def spam(n=None): """Print spam n times. If n is not given or is None, print a nasty message.""" if n == None: print("Nobody expects the SPANISH INQUISITION!!! ***ominous chords***") else: for i in range(n-1): print("Spam! ", end='') print("Glorious SPAM!!!") my intention, and the documented behaviour, is that n=None, and nothing but n=None, should trigger the nasty message. So my function has a bug, not the caller, because my code fails to live up to my promise. Blaming the caller for passing a "buggy" object is just a cop-out. I made a promise that None and only None is special, and my code breaks that promise. My bug, not the caller's. The fix is, of course, to use "is None" unless I genuinely want to match None by equality for some strange reason. -- Steven

Ned Batchelder wrote:
On 8/8/2012 4:29 PM, Georg Brandl wrote:
For None, "==" and "is" are equivalent, because no other object is equal to None. For True and False, this is different, and using "is" here is a very stealthy bug.
It's easy to make other objects == None, by writing buggy __eq__ methods. That doesn't happen much, but it's easier with __ne__, where the negated logic is easy to screw up. I've seen it happen. Use "is None", not "== None".
It's also easy to make objects == None because that's the behavior you want. Like most things, there are exceptions to the rules, and you need to know the package you are dealing with to use it properly. ~Ethan~

Rob Cliffe <rob.cliffe@btinternet.com> writes:
On 08/08/2012 17:59, Oleg Broytman wrote:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
By “compelling use case for”, I mean “a use case which is best satisfied by”. So use cases which *could* use this are not compelling if they are better satisfied by some other, existing way.
1) I have written a function that returns True, False or a string error message. (No doubt an Exception-subclass object might be better style.)
You get to the nub of it: there are clearly better ways to meet the use case (for this one, use an exception), so this is not a compelling use case for precise checking of True and False.
2) Say you are writing a function to process an arbitrary object, e.g. a custom version of repr. You might well choose to write if obj is True: # processing elif obj is False: # processing elif type(obj) is int: # processing
Again, this is much clearer written as: if type(obj) is bool: # processing if type(obj) is int: # processing So not a compelling use case for checking specific values.
I am sure the examples could be multiplied. I can see no reason why we should be discouraged from writing if x is True: if that is really what we mean (and need) and not just a verbose way of spelling "if x:".
I don't see any of the cases presented so far (other than unit testing, which is already special enough to break most of the rules) as best satisfied by precise checking for specific values of bool. On the other hand, ‘if foo is True’ is a common beginner mistake that we meet frequently in ‘comp.lang.python’, and is almost always better written as ‘if foo’. It's that kind of advice that belongs in PEP 8. -- \ “The difference between religions and cults is determined by | `\ how much real estate is owned.” —Frank Zappa | _o__) | Ben Finney

On 08/08/2012 09:23 PM, Ben Finney wrote:> Rob Cliffe <rob.cliffe@btinternet.com> writes:
[...]
2) Say you are writing a function to process an arbitrary object,
e.g.
a custom version of repr. You might well choose to write if obj is True: # processing elif obj is False: # processing elif type(obj) is int: # processing
Again, this is much clearer written as:
if type(obj) is bool: # processing if type(obj) is int: # processing
So not a compelling use case for checking specific values.
Your replacement is not equivalent. I think what you meant was, if type(obj) is bool: if obj: # processing else: # processing elif type(obj) is int: # processing I don't find that clearer at all, let alone "much clearer" than, if obj is True: # processing elif obj is False: # processing elif type(obj) is int: # processing (On the other hand I wouldn't claim the latter is "much clearer" than the former either, but your claim is wrong IMO.)
[...] On the other hand, ‘if foo is True’ is a common beginner mistake that we meet frequently in ‘comp.lang.python’, and is almost always better written as ‘if foo’. It's that kind of advice that belongs in PEP 8.
Perhaps correcting beginner's mistakes should be done in the tutorial while PEP-8 should be aimed at a broader and on average more advanced audience. I realize that one purpose of style conventions are to avoid mistakes, including beginner one's but I and several times found the simplest, most intuitive way to implement tri-value logic was to use {True, False, None} and so think that if "is True" is to be officially discouraged because misuse by some people in the first .5% of their Python careers, the reason for that discouragement should at least be explained in PEP-8.

On 8/9/2012 10:58 AM, rurpy@yahoo.com wrote:
I realize that one purpose of style conventions are to avoid mistakes, including beginner one's but I and several times found the simplest, most intuitive way to implement tri-value logic was to use {True, False, None} and so think that if "is True" is to be officially discouraged because misuse by some people in the first .5% of their Python careers, the reason for that discouragement should at least be explained in PEP-8.
To repeat what I said at the beginning of the thread. if x is True: is redundant and unnecessary and wasteful EXCEPT in those rare cases where one specifically wants to know that x *is* True AND x could be another true value, so that 'is True' is necessary to differentiate True from other true values. Tri-value logic with {True, False, None} is not such an exceptional case for True. 'if tri_value:' is equivalent to 'if tri_value is True:'. If you prefer the latter anyway, then ignore PEP 8 on that point. The same principle applies to False: if x is False: is equivalent to if not x: EXCEPT when one wants to know if x is False AND it could be another false value. The same tri-value logic is such an exception for False and one would need 'x is False' to deal with False before None. Of course, one *could* always write if x: Trueproc() elif x is None: Noneproc() else: Falseproc() -- Terry Jan Reedy

On 8 August 2012 17:59, Oleg Broytman <phd@phdru.name> wrote:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney < ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Or when testing, I often want to check that a method *really* returns True or False rather than some object that happens to evaluate to True or False. Michael
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
-- http://www.voidspace.org.uk/ May you do good and not evil May you find forgiveness for yourself and forgive others May you share freely, never taking more than you give. -- the sqlite blessing http://www.sqlite.org/different.html

I don't think PEP 8 is meant to cover a specialized cases like testing. Keep in mind the recommendation in the beginning of the style guide: "But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply." For example, a similar argument to yours could be made about the recommendation to "use the fact that empty sequences are false" instead of checking len(sequence). E.g.: Yes: if not seq: if seq No: if len(seq) If not len(seq) If you want to test that your __len__ method is working, then of course the latter would be acceptable--because you aren't concerned about checking that the list is full; you're concerned about the functionality of the __len__ method. Common sense should indicate that the style guide doesn't apply here because the use case is different. The same goes for truth or falsity. In situations in which you are concerned about the truth or falsity of an object, then you should never use "== True" or "is True", because of the possibility of bugs that others have already pointed out. There are clearly cases in which the style guide just doesn't apply--testing to ensure that a returned value actually "is" a given singleton is one of them. The style guide need not list every case in which the recommendation possibly might not apply. People with advanced needs are advanced enough to know when to break the style guide. =) Matthew Lefavor From: Michael Foord <fuzzyman@gmail.com> Date: Wednesday, August 8, 2012 6:04 PM To: "python-ideas@python.org" <python-ideas@python.org> Subject: Re: [Python-ideas] Programming recommendations (PEP 8) and boolean values On 8 August 2012 17:59, Oleg Broytman <phd@phdru.name> wrote: On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au <mailto:ben%2Bpython@benfinney.id.au>> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak. Or when testing, I often want to check that a method *really* returns True or False rather than some object that happens to evaluate to True or False. Michael 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 -- http://www.voidspace.org.uk/ May you do good and not evil May you find forgiveness for yourself and forgive others May you share freely, never taking more than you give. -- the sqlite blessing http://www.sqlite.org/different.html

On Thu, Aug 9, 2012 at 8:39 AM, Lefavor, Matthew (GSFC-582.0)[MICROTEL LLC] <matthew.lefavor@nasa.gov> wrote:
I don't think PEP 8 is meant to cover a specialized cases like testing. Keep in mind the recommendation in the beginning of the style guide: "But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply."
Right, there are broad swathes of programming guidelines that simply *don't apply* when writing tests. In order to properly isolate the behaviours you want to test, you often end up doing things that would be legitimately considered downright evil if you ever did them in production code. The recommendations in PEP 8 are for production code that is meant to *do things*. Test code, which is checking whether or not *other* code is doing the expected things, isn't typical production code. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 09/08/12 08:04, Michael Foord wrote:
Or when testing, I often want to check that a method *really* returns True or False rather than some object that happens to evaluate to True or False.
I consider that three separate unit tests: def testGivesTrue(self): for x in self.args_giving_true: self.assertTrue(method(x)) def testGivesFalse(self): for x in self.args_giving_false: self.assertFalse(method(x)) def testIsBool(self): for x in self.args_giving_true + self.args_giving_false: self.assertTrue(isinstance(method(x), bool)) -- Steven

Oleg Broytman <phd@phdru.name> writes:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Since True and False are strongly coupled with a *two*-state type, that just seems needlessly confusing to the reader of the code. Better to use a non-bool type which makes it explicit that there are three valid values. -- \ “In case you haven't noticed, [the USA] are now almost as | `\ feared and hated all over the world as the Nazis were.” —Kurt | _o__) Vonnegut, 2004 | Ben Finney

Ben Finney writes:
Oleg Broytman <phd@phdru.name> writes:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Since True and False are strongly coupled with a *two*-state type, that just seems needlessly confusing to the reader of the code. Better to use a non-bool type which makes it explicit that there are three valid values.
I occasionally use an abstract base class that initializes a Boolean member to None, and assert "is not None" in testing or validation code. I wouldn't call it "compelling," but I find this convention very useful in validating my own code, as if such variables weren't properly initialized in a derived class, I probably screwed up something else, too.

On Thu, Aug 09, 2012 at 01:15:38PM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
Oleg Broytman <phd@phdru.name> writes:
On Thu, Aug 09, 2012 at 02:18:53AM +1000, Ben Finney <ben+python@benfinney.id.au> wrote:
What is a compelling use case for checking precisely for True or False?
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Since True and False are strongly coupled with a *two*-state type, that just seems needlessly confusing to the reader of the code. Better to use a non-bool type which makes it explicit that there are three valid values.
I am not always free to use my own classes and values. Sometimes (quite often, actually) I receive values from 3rd-party libraries. Example - DB API drivers: cursor.execute("SELECT boolean FROM mytable") row = cursor.fetchone() Now row[0] is that tri-state variable with possible values 1/0/None or True/False/None. None is of course for SQL NULL. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On 09/08/12 04:59, Oleg Broytman wrote:
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Er, not quite best practice. As any DailyWTFer knows, the correct third value for a boolean is FileNotFound. http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx -- Greg

On Thu, Aug 09, 2012 at 03:24:59PM +1200, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 09/08/12 04:59, Oleg Broytman wrote:
To distinguish False and None for a tri-state variable that can have 3 values - "yes", "no" and "unspecified" - True, False and None in Python-speak.
Er, not quite best practice.
Unavoidable. E.g. in SQL a boolean column stores True, False and None (SQL NULL). Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On 8/8/2012 10:11 AM, Michael Foord wrote:
Hey all,
True and False are singletons, so if you want to check precisely for True and False then an identity check seems appropriate.
However the "Programming Recommendations" section of PEP 8 has this to say on the topic:
Don't compare boolean values to True or False using ==.
Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
http://www.python.org/dev/peps/pep-0008/#programming-recommendations
I understand 'boolean values' to when you KNOW that <greeting> is a boolean. For instance 'isinstance(x, tuple)'. In that situation, 'if isinstance(x, tuple) is True' is a stupid redundancy, since the actual test, with the internal comparison, becomes 'if (isinstance(x, tuple) is True) is True'. An newbies not really understanding 'if' have done the latter, as seen on python-list On the other hand, when the tested value might not be boolean for item in [1, None, 'a', True, []]: if item is True: do_True() else: do_all_else() 'is True' is necessary.
It seems to me that there is an important distinction between testing that an object is either the boolean True or False and merely checking the "truthiness" of an object.
That is the distinction drawn above.
Many a bug has been caused by an empty container object (or some other falsey object) falling into an "if not value" clause that was actually meant to check for the presence of False or None.
One should generally know what group of classes one is testing in any if. -- Terry Jan Reedy

On Wed, Aug 8, 2012 at 10:11 AM, Michael Foord <fuzzyman@gmail.com> wrote:
True and False are singletons, so if you want to check precisely for True and False then an identity check seems appropriate.
Technically speaking, True and False are not singletons - they are each an instance of the bool class and a singleton is the *only* instance of a class. I am not sure what the right term is for bool instances behavior, but the key feature here is that if x is known to be bool, x == True is equivalent to x is True. This property is not unique to bool an singletons like None. For example, in CPython if x is an int, x == 0 is equivalent to x is 0 because a few small integers are preallocated. However, in the case of int, this property is clearly an implementation detail and alternative implementations should be free to vary the number of preallocated integers or not preallocate at all. With respect to bool, an argument can be made that it having only two preallocated instances is a language feature rather than an implementation detail and user can rely on the fact that True, bool(1) and say not [] all return the same instance. If this is so, I think this fact should be mentioned somewhere, but probably not in PEP 8.

On 09/08/12 08:37, Alexander Belopolsky wrote:
With respect to bool, an argument can be made that it having only two preallocated instances is a language feature rather than an implementation detail and user can rely on the fact that True, bool(1) and say not [] all return the same instance. If this is so, I think this fact should be mentioned somewhere, but probably not in PEP 8.
Yes, this is documented: http://docs.python.org/py3k/library/functions.html#bool However, the question is not whether if x is True: and if isinstance(x, bool) and x: are equivalent, or whether there are obscure edge-cases where one genuinely needs to test whether or not an object is identical to True. The question is what is the idiomatic Python code for testing a flag. That is simply if x: which duck-types truthiness and accepts any true value, not just True. Like almost all identity tests, testing "x is True" puts the emphasis on the wrong thing: object identity instead of object value. It restricts the value's type instead of duck-typing, and that's usually unpythonic. If you do have a special need to do so, okay, that's fine, but there's no need for PEP 8 to cover your special use-case. PEP 8 is for conventions for idiomatic code, not every exception. PEP 8 already gives its blessing to break the rules when you need to. Besides, even when it is not, "x is True" looks like a rookie mistake. Beginners often write "if flag == True" even in statically-typed languages where flags cannot be other than a bool. -- Steven

On Wed, Aug 8, 2012 at 9:20 PM, Steven D'Aprano <steve@pearwood.info> wrote:
Yes, this is documented:
Indeed. I was actually looking under "Built-in Types", <http://docs.python.org/py3k/library/stdtypes.html> rather than "Built-in Functions." I now remember that I noted this issue before. This part of the manual is not optimally subdivided into sections: 2. Built-in Functions (covers bool() and other builtin type constructors) 3. Built-in Constants (covers True and False) 4. Built-in Types 4.1. Truth Value Testing 4.2. Boolean Operations — and, or, not 4.3. Comparisons 4.4. Numeric Types — int, float, complex ... As a result, there is no one place where one can find information about bool. I wonder if it should go somewhere under section 4.4. After all,
isinstance(True, int) True

On 08/08/2012 09:11 AM, Michael Foord wrote:
True and False are singletons, so if you want to check precisely for True and False then an identity check seems appropriate.
However the "Programming Recommendations" section of PEP 8 has this to say on the topic:
Don't compare boolean values to True or False using ==.
Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
http://www.python.org/dev/peps/pep-0008/#programming-recommendations
It seems to me that there is an important distinction between testing that an object is either the boolean True or False and merely checking the "truthiness" of an object. Many a bug has been caused by an empty container object (or some other falsey object) falling into an "if not value" clause that was actually meant to check for the presence of False or None.
Why does PEP 8 recommend not testing "boolean values" (which to me implies "values you expect to be a bool") using equality or identity, and more specifically why does it say that using an identity check is worse than an equality check?
Near the top of the web page you referred is ...
This document gives coding conventions for the Python code comprising the standard library in the main Python distribution.
I think in the context of coding Python's library, the "if greeting:" case makes the function more general and easier to use in more situations. Cheers, Ron

Am I the only one that noticed this? PEP 8 says: "Don't compare boolean values to True or False using ==." To me, all the talk about wanting to test variables that might not hold True of False (i.e. - True/False/None or True/False/String or ...) are off topic, as those values *aren't* boolean values. So this bit of the PEP doesn't really apply to those cases. Some of the responses have touched on this by saying you should check that the values are/aren't boolean before testing them, which would mean the above would apply to the tests on the boolean branch. But the arguments are all couched in terms of better style, as opposed whether or not the this rule in the PEP actually applies. Am I wrong here? Has my exposure to Hindley-Milner type systems tainted me to the point where I just don't get it any more? Thanks, <mike

On 11/08/12 13:47, Mike Meyer wrote:
Am I the only one that noticed this?
PEP 8 says: "Don't compare boolean values to True or False using ==."
To me, all the talk about wanting to test variables that might not hold True of False (i.e. - True/False/None or True/False/String or ...) are off topic, as those values *aren't* boolean values. So this bit of the PEP doesn't really apply to those cases.
That's debatable. If I have an object which could be True/False/Other, or even many different Others, once I've eliminated the Other case(s), I'm left with a binary choice between two bools. Hence PEP 8 apparently applies even when dealing with tri-state logic values.
Some of the responses have touched on this by saying you should check that the values are/aren't boolean before testing them, which would mean the above would apply to the tests on the boolean branch.
Exactly.
But the arguments are all couched in terms of better style, as opposed whether or not the this rule in the PEP actually applies.
I don't understand. The rule is a style rule, and programming style is intended to result in better code. So what's your point?
Am I wrong here? Has my exposure to Hindley-Milner type systems tainted me to the point where I just don't get it any more?
I don't anything about Hindley-Milner, but I do know that duck-typing means that any object can quack like a bool. I also know that even in languages with strict True/False bools, like Pascal, writing "if flag == True" is a common rookie mistake. In both cases, a recommendation to avoid both "flag == True" and "flag is True" is good advice. PEP 8 already gives us permission to break the rules when necessary. What else do we need? -- Steven
participants (24)
-
Alexander Belopolsky
-
Antoine Pitrou
-
Ben Finney
-
Bruce Leban
-
Ethan Furman
-
Georg Brandl
-
Greg Ewing
-
Guido van Rossum
-
INADA Naoki
-
Lefavor, Matthew (GSFC-582.0)[MICROTEL LLC]
-
M.-A. Lemburg
-
Michael Foord
-
Mike Meyer
-
Ned Batchelder
-
Nick Coghlan
-
Oleg Broytman
-
Rob Cliffe
-
Ron Adam
-
Ronan Lamy
-
rurpy@yahoo.com
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Terry Reedy
-
Yuval Greenfield