I know that Python guarantees that there is only one instance of NoneType, the None object, so that you can safely use is None to test if something equals None.
Is there an equivalent guarantee for bool True and False (i.e. that there is only one instance of each)?
If not, why not?
EDIT: In particular, I've noticed that (n+0) is (0+n) gives True for n in range(-5, 257) and False otherwise. In other words, zero, the first 256 positive and the first 5 negative integers seem to be pre-cached and are not instanced again. I am guessing that that's a choice of the interpreter (CPython, in my case) and not a specification of the language. And bool derives from int, so I still have to wonder about what expectations I can have with other interpreters.
EDIT: To clarify, since this seems to have generated a lot of confusion, my intention is not to test the boolean interpretation of a value. For that I would never use is True or is False. My intention is to be able to tell apart False from everything else, in a variable that can have values of several types including empty strings, zeros, and None, and similarly for True. I'm myself an experienced programmer, of the kind who cringes when I see "if booleanvar == True".
NOTE ON DUPLICATES: The questions this one was alleged to be a duplicate of (this and this) don't answer this question; they merely state that bool is a subclass of int that differ mainly in their repr, not if True and False are guaranteed to be unique.
Also, note that it's not a question about what the names True and False are bound to, but about the instances of the class bool.
From the docs (https://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy):
Booleans
These represent the truth values False and True. The two objects representing the values False and True are the only Boolean objects.
There are only two objects, any computation producing a boolean will produce one of those two existing objects:
>>> (1 == 1) is True
True
>>> (1 == 0) is False
True
The bool type has only two instances, True and False. Furthermore, it can't be subclassed, so there's no way to create a derived class that can have additional instances.
But even though it's guaranteed, there's seldom a good reason to rely upon it. You should usually use if x rather than if x is True, and avoid situations where you need to distinguish True from other truthy values or False from other falsy values.
Related
Here is simple ST plugin. Is there a difference between commented lines? Personally, I don't see any difference in how they work, just a difference in visual appearance.
However, some plugin developers prefer second version (== 1), which looks just useless and ugly for me. Probably there are some reasons to prefer it?
import sublime_plugin
class ExpandUnexpandTabsCommand(sublime_plugin.EventListener):
def on_pre_save(self, view):
# if view.settings().get("translate_tabs_to_spaces"):
# if view.settings().get("translate_tabs_to_spaces") == 1:
# if view.settings().get("translate_tabs_to_spaces") == True:
view.run_command("expand_tabs")
else:
view.run_command("unexpand_tabs")
This is covered in PEP8, the official Python style guide's, "Programming Recommendations" section:
Don't compare boolean values to True or False using ==.
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
In other parts of the guide, they emphasize this for other use cases (e.g. testing for empty/non-empty collections should not use len()); unless a specific value is critical to your logic, use the implicit boolean nature of what you're testing (with not if it must be inverted), don't spin your wheels with comparisons that ultimately add little in terms of readability, increase fragility, and slow your code to boot.
The only reason to prefer the other approaches is if you expect there to be other truthy values that should not count as truthy. In this case, the translate_tabs_to_spaces setting is very clearly boolean in nature, so you almost certainly want to handle any truthy value the same way; if they later redesigned the setting to have a numeric value, where 0 meant "don't translate" and any positive value meant the number of spaces each tab was worth, implicit truthiness evaluation would continue to work, but for the standard four space indents, a test for == 1 or == True would suddenly decide no translation was occurring.
It depends on what the possible values are.
If the file must have 0 or 1 in it, anything else is an error, and you're reading it as an int, then you probably want == 1.
If the file can have either True or no entry at all, and you're using get(…) instead of [] so you get back None whenever it's not True, then you want to just test the truthiness. (Or maybe is not None, but definitely not == True or == 1.)
The rule is pretty simple: when writing a test, write what you mean to test.
Different tests mean different things:
if spam:: passes if spam is anything truthy. That means anything besides None, False, numeric zero, or empty containers.
if spam == 1:: passes if spam is the number 1.
if spam is True:: passes only if spam is the special constant True. If you want to make sure other truthy values fail, and only True counts, use is. You rarely want this.
if spam == True:: passes if spam is the special constant True, or some object equal to it. If you've gone out of your way to write a class whose __eq__ tests for True or something, then you might want this test, but it's hard to imagine why you would otherwise.
It happens to be true that 1 == True. But writing == True when you want to test for the number 1, or == 1 when you want to test for True but not other truthy values, is misleading to anyone who understands idiomatic Python, and mildly confusing to anyone who doesn't, and there's no benefit to anyone. So don't do it.
And writing either of those when you want to test for anything truthy isn't just misleading, it's wrong.
if view.settings().get("translate_tabs_to_spaces") is more concise and readable. There is little if ever any need to compare a Boolean to another Boolean value, and using integers of 0 and 1 to denote a Boolean value should only be considered when the programming language does not support Boolean values.
The question I'm about to ask here has been asked before, but those questions/answers make no mention of what I want to know.
I recall a few months or so ago, I had a rather sizable Python script, and I was using if x: because it was shorter and I was lazy. I don't remember which version of Python, but I do remember getting a DeprecationWarning (or PendingDeprecationWarning?) about implicit comparisons to True.
Now, I'm trying to write something someone else might read. I'm using if x == True and if x is not None everywhere, and pep8 and pylint are complaining about this, saying I should use if x:.
Personally, I think if x: is far less readable, but pep8 (the program) and PEP 8 (the document) both disagree.
Google is not being very helpful in allowing me to figure in which version, if ever, Python gave a DeprecationWarning for if x:, so I wonder if perhaps the SO community can provide insight.
Should I be worrying about this at all? Does it actually matter that much?
The correct answer as to what condition to use is, in the first place, a matter of semantics rather than style. Unless x is a boolean value, 0/False or 1/True, which your question did not specify, if x: and if x == True: are semantically different conditions and often give different results. You should use whichever is the correct one for the situation. if x: is usually the correct choice, but not always. If x is specified (known) to be a boolean, then adding == True is superfluous and a waste of time for the writer, reader, and interpreter.
Under the covers, if x: means (is implemented as) if bool(x) is True in the normal meaning of this expression, and if x == True: means if bool(x == True) is True. Since x == True return a bool and bool(a_bool) is a_bool, the latter reduces to if (x == True) is True. In general, bool(x) is not the same as x == True.
if x is None: (or not None) should be used if and only if that is the proper condition. It often correct when testing the output of a function returns either an int (or string or ...) or None. In many other situations, it is usually wrong.
It is perfectly good Python, and Python 3.+ versions don't give a warning, so if you're writing code for other people to work with in the future, using if x: is perfectly fine. And by the way, on behalf of every developer who had to maintain horribly unreadable code, THANK YOU for considering the readability of your code.
I think you have several separate issues confused.
It's best to check what the style guide actually says, and double check how your code actually behaves, rather than relying only on remembered behaviour :-)
Boolean expressions are already either true or false
The expression in an if statement is always intepreted as boolean; anyone reading Python code needs to know that anyway.
So the following all mean exactly the same thing, and piling on == True does not improve readability:
if x + y:
…
if (x + y) == True:
…
if ((x + y) == True) == True:
…
if (((x + y) == True) == True) == True:
…
which is why PEP 8 says:
Don't compare boolean values to True or False using == .
Singletons should be compared using identity
The comparison of an object to None implies that value is treated specially; it is commonly used as a sentinel for special processing. It is a singleton, so comparing whether an object is merely equal to None is ambiguous.
So, if your intent is to test a value for None, you should test whether the object is none by testing its identity:
if x is None:
…
if x is not None:
…
which is why PEP 8 says:
Comparisons to singletons like None should always be done with is or is not , never the equality operators.
None is not the only value that is boolean false
There are many values which are false in a boolean context, so doing a mere if x: is not enough to tell whether an object is actually None.
Which is why PEP 8 says:
beware of writing if x when you really mean if x is not None -- e.g. when testing whether a variable or argument that defaults to None was set to some other value.
In this answer https://stackoverflow.com/a/27680814/3456281, the following construct is presented
a=[1,2]
while True:
if IndexError:
print ("Stopped.")
break
print(a[2])
which actually prints "Stopped." and breaks (tested with Python 3.4.1).
Why?! Why is if IndexError even legal? Why does a[2] not raise an IndexError with no try ... except around?
All objects have a boolean value. If not otherwise defined, that boolean value is True.
So this code is simply the equivalent of doing if True; so execution reaches the break statement immediately and the print is never reached.
View the Python documentation, section Truth Value Testing under Built-in Types of The Python Standard Library. The first sentence, and the first sentence after the last bullet point answers your question.
Any object can be tested for truth value ...
and
All other values are considered true — so objects of many types are
always true.
Here's the full text of the documentation, (content in brackets, [], are added as an augmentation):
5.1. Truth Value Testing
Any object can be tested for truth value, for use in an if or while
condition or as operand of the Boolean operations below. The following
values are considered false:
None
False
zero of any numeric type, for example, 0, 0L, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a __bool__() [__nonzero__() in Python 2] or __len__() method, when that method returns the integer zero or bool value False. [See Data Model, Special Method Names, section Basic Customization, of The Python Language Reference]
All other values are considered true — so objects of many types are
always true.
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.)
Conclusion
So since Exception does not have a __bool__, __nonzero__, or __len__, (nor fall under the other conditions listed above) an Exception object will always test as True in a boolean context.
In /tmp/spam.py:
n = 69
if n == True:
print 'potato'
pep8 utility complains about this conditional:
wim#SDFA100461C:/tmp$ pep8 spam.py
spam.py:3:6: E712 comparison to True should be 'if cond is True:' or 'if cond:'
the first suggestion is wrong/"worse" according to pep8 itself
the second suggestion changes the behaviour of the code
What is the best practice for a case where you actually do want to check equality with True? Is identity checking with True using is OK? Why does pep8 utility offer an alternative which is explicitly discouraged in pep8 itself?
If you really do need to check equality with True then use == and ignore PEP8, but in almost any conceivable case that isn't what you want.
If you want to know whether the value you have is one of the values Python considers to be true, use if cond:. If you want to know whether the value you have is the singleton value True then use is True, the booleans True and False are singletons so it is correct to use is in this situation.
If you need to test whether your object is the singleton True, but a linter or a code reviewer complains about is True, then isinstance(x, bool) and x is a behaviorally equivalent (but slower) substitute.
Checking x == True is a halfway house. It is true when x is True is true, and false for your case of x=69, but there are other objects which are not themselves True but for which x==True gives an unexpectedly true result such as 1 == True being true. (thanks #Ant).
So putting that together:
value of n: True 1 69 False 0
-----------------------------------------------
expression result
-----------------------------------------------
if n: True True True False False
if n is True: True False False False False
if n==True: True True False False False
Pick the row from that table which gives the results you really wanted (and the last one isn't it).
Whatever you do, I think a comment is required since the code looks funny.
If you want to check equality with True then it might be clearer to write if n == 1. Someone reading the code is less likely to misinterpret it as an attempt to test logical truth.
Of course if n has a user-defined type it's possible to define n.__eq__ such that (n == True) != (n == 1), but it would be pretty nasty. So you'd have to decide whether the subtle difference in meaning is justified by the benefit of avoiding the code looking like an incorrect logical truth test.
If the difference is not justified, and if you're absolutely required to write to the PEP8 style guide, then either use assertEqual or write expected_value = True, if n == expected_value.
If the code is a unit test for an API that for some reason defines specifically that the literal True is returned, then of course you should test if n is True, not if n == True. As before, a comment or some indirection would be needed to stop the code looking wrong.
Another option is to change the API you're testing. The reason for the style guide rules is in part to discourage people from inventing or relying on APIs that specifically define that the return value must be identical or equal to the literal True, and instead define APIs and write their code in terms of logical truth. So if you "fix" the API you can "fix" the code that tests it.
Why do you need to explicitly test for True values? You rarely, if ever do need narrow your test down to a specific type. I'd rethink your use case here; if you are building an API that'll return a bool instead of in int for out-of-band conditions, then use exceptions instead.
If you do have to test for True only, then use
if n is True:
because the boolean values are meant to be singletons like None. See the Programming recommendations section:
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
Moreover, because issubtype(bool, int) is true (for historical reasons; bool was introduced rather late in Python), n == True is also true for n = 1, if you can only accept True here then you can only use is True. You could also use isinstance(n, bool) and n, which would allow for subclasses of bool, but I cannot imagine there ever be a use for such a type, and in current implementations, bool explicitly prohibits being subclassed.
The PEP 8 rule about using not using if cond is True: is specifically called out because it limits the value of cond to the bool only.
Last but not least, PEP 8 starts with this:
A Foolish Consistency is the Hobgoblin of Little Minds
[...] But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best.
Only follow PEP 8 if it suits your needs.
The second recommendation would best suit your needs. The conditional statement if cond: will return true if the condition itself is true. It will not change the behavior of the code, as it is just shorthand for if cond == True:.
I ran into unexpected results in a python if clause today:
import numpy
if numpy.allclose(6.0, 6.1, rtol=0, atol=0.5):
print 'close enough' # works as expected (prints message)
if numpy.allclose(6.0, 6.1, rtol=0, atol=0.5) is True:
print 'close enough' # does NOT work as expected (prints nothing)
After some poking around (i.e., this question, and in particular this answer), I understand the cause: the type returned by numpy.allclose() is numpy.bool_ rather than plain old bool, and apparently if foo = numpy.bool_(1), then if foo will evaluate to True while if foo is True will evaluate to False. This appears to be the work of the is operator.
My questions are: why does numpy have its own boolean type, and what is best practice in light of this situation? I can get away with writing if foo: to get expected behavior in the example above, but I like the more stringent if foo is True: because it excludes things like 2 and [2] from returning True, and sometimes the explicit type check is desirable.
You're doing something which is considered an anti-pattern. Quoting PEP 8:
Don't compare boolean values to True or False using ==.
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
The fact that numpy wasn't designed to facilitate your non-pythonic code isn't a bug in numpy. In fact, it's a perfect example of why your personal idiom is an anti-pattern.
As PEP 8 says, using is True is even worse than == True. Why? Because you're checking object identity: not only must the result be truthy in a boolean context (which is usually all you need), and equal to the boolean True value, it has to actually be the constant True. It's hard to imagine any situation in which this is what you want.
And you specifically don't want it here:
>>> np.True_ == True
True
>>> np.True_ is True
False
So, all you're doing is explicitly making your code incompatible with numpy, and various other C extension libraries (conceivably a pure-Python library could return a custom value that's equal to True, but I don't know of any that do so).
In your particular case, there is no reason to exclude 2 and [2]. If you read the docs for numpy.allclose, it clearly isn't going to return them. But consider some other function, like many of those in the standard library that just say they evaluate to true or to false. That means they're explicitly allowed to return one of their truthy arguments, and often will do so. Why would you want to consider that false?
Finally, why would numpy, or any other C extension library, define such bool-compatible-but-not-bool types?
In general, it's because they're wrapping a C int or a C++ bool or some other such type. In numpy's case, it's wrapping a value that may be stored in a fastest-machine-word type or a single byte (maybe even a single bit in some cases) as appropriate for performance, and your code doesn't have to care which, because all representations look the same, including being truthy and equal to the True constant.
why does numpy have its own boolean type
Space and speed. Numpy stores things in compact arrays; if it can fit a boolean into a single byte it'll try. You can't easily do this with Python objects, as you have to store references which slows calculations down significantly.
I can get away with writing if foo: to get expected behavior in the example above, but I like the more stringent if foo is True: because it excludes things like 2 and [2] from returning True, and sometimes the explicit type check is desirable.
Well, don't do that.