Apologies if this has been asked before, but I have searched in vain for an answer to my exact question. Basically, with Python 2.7, I have a program running a series of geoprocessing tools, depended on what is reqested via a series of True/False variables that the user adjusts in the script e.g.
x = True
if x:
run function
However, I have now discovered that x does not need to be literally "True" for the function to run. For example:
In: x = True
if x:
print True
Out: True
In: x = 123
if x:
print True
Out: True
In: x = 'False'
if x:
print True
Out: True
In: x = False
if x:
print True
Out:
So any value other than False appears to evaluate to True, which would not be the case for if x == True or if x is True. Seeing as PEP 8 strongly recommends only using the if x: variant, can anybody explain why this behaviour occurs? It seems that if x: is more a test for "if x is not False" or "if x exists". With that in mind, I believe I should be using if x is True: in this case, despite what PEP 8 has to say.
The following values in Python are false in the context of if and other logical contexts:
False
None
numeric values equal to 0, such as 0, 0.0, -0.0
empty strings: '' and u''
empty containers (such as lists, tuples and dictionaries)
anything that implements __bool__ (in Python3) to return False, or __nonzero__ (in Python2) to return False or 0.
anything that doesn't implement __bool__ (in Python3) or __nonzero__ (in Python2), but does implement __len__ to return a value equal to 0
An object is considered "false" if any of those applies, and "true" otherwise, regardless of whether it's actually equal to or identical with False or True
Now, if you've arranged that x is necessarily one of the objects True or False, then you can safely write if x. If you've arranged that the "trueness" of x indicates whether or not to perform the operation, regardless of type, then you can safely write if x. Where you can write that you should prefer to do so, since it's cleaner to read.
Normally, if it is allowed for x to take the value True then you're in one of those two cases, and so you would not write if x is True. The important thing is to correctly document the meaning of x, so that it reflects the test used in the code.
Python programmers are expected to know what's considered true, so if you just document, "runs the function if x is true", then that expresses what your original code does. Documenting it, "runs the function if x is True" would have a different meaning, and is less commonly used precisely because of the style rule in PEP8 that says to test for trueness rather than the specific value True.
However, if you wanted the code to behave differently in the case where x is an empty container from the case where it is None, then you would write something like if x is not None.
I'd like to add a short example where those 3 tests differ:
def test(x):
print(x, ":", bool(x), x == True, x is True)
test("something")
test(1)
test(True)
The output (pretty formatted):
# "something" : True False False
# 1 : True True False
# True : True True True
x = 'False'
x = 123
Are both True
Other truth values.
The document explains other values.
As far as the PEP8 reason, its far more semantic to read if this_file_is_green
Other falsey values include 0, '', []. You should just use the if x: version.
It goes without saying that you should write code that does what you need. But in most cases, you simply don't need to say == True or is True, because you don't need to distinguish True from other "truthy" values. So it's recommended to leave that out for simplicity.
The case where you definitely should use == True or is True is when you do need to distinguish True from other truthy values.
In your example, do you care about the difference between True and 123? That would tell you which way to code it.
One thing about coding == True or is True: it will raise a minor red flag when other developers read your code. They won't think it's wrong, they will just wonder why it's there and will want to know why it's important to treat True differently from other truthy values in this particular case.
In other words, if you don't need it, it's best not to use it.
The ability to say
if x:
...
is considered a feature. You can also specify when the test should be considered to pass or not for user defined classes (just define the method __nonzero__ in Python 2.x or __bool__ in Python 3).
For example for strings and containers like lists, dictionaries or sets the test if x ... means "if x is not empty".
Note that the rationale is not that this allows less code to write, but that resulting code is easier to read and to understand.
If you like instead to write if x is True ... have you considered to go farther down that path to if (x is True) is True ... or if ((x is True) is True) is True ... ? :-)
In Python 2.7, if a: and if a==True are not giving the same output for values different to 1. Here are some snippets of code to demonstrate the different behaviors:
with a=1
a=1
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (1,True)
a=1
if a:
print (a,"True")
else:
print (a,"Not True")
output> (1, True)
with a=2
a=2
if a:
print (a,"True")
else:
print (a,"Not True")
output> (2, True)
a=2
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (2, Not True)
if you use if x ,it means it has to evaluate x for its truth value.But when you use x ==True or x is True.It means checking whether type(x)==bool and whether x is True.
attention : x is True is no equal to bool(x)==True
when you use x is True , you are checking the id of x and True.
Related
Apologies if this has been asked before, but I have searched in vain for an answer to my exact question. Basically, with Python 2.7, I have a program running a series of geoprocessing tools, depended on what is reqested via a series of True/False variables that the user adjusts in the script e.g.
x = True
if x:
run function
However, I have now discovered that x does not need to be literally "True" for the function to run. For example:
In: x = True
if x:
print True
Out: True
In: x = 123
if x:
print True
Out: True
In: x = 'False'
if x:
print True
Out: True
In: x = False
if x:
print True
Out:
So any value other than False appears to evaluate to True, which would not be the case for if x == True or if x is True. Seeing as PEP 8 strongly recommends only using the if x: variant, can anybody explain why this behaviour occurs? It seems that if x: is more a test for "if x is not False" or "if x exists". With that in mind, I believe I should be using if x is True: in this case, despite what PEP 8 has to say.
The following values in Python are false in the context of if and other logical contexts:
False
None
numeric values equal to 0, such as 0, 0.0, -0.0
empty strings: '' and u''
empty containers (such as lists, tuples and dictionaries)
anything that implements __bool__ (in Python3) to return False, or __nonzero__ (in Python2) to return False or 0.
anything that doesn't implement __bool__ (in Python3) or __nonzero__ (in Python2), but does implement __len__ to return a value equal to 0
An object is considered "false" if any of those applies, and "true" otherwise, regardless of whether it's actually equal to or identical with False or True
Now, if you've arranged that x is necessarily one of the objects True or False, then you can safely write if x. If you've arranged that the "trueness" of x indicates whether or not to perform the operation, regardless of type, then you can safely write if x. Where you can write that you should prefer to do so, since it's cleaner to read.
Normally, if it is allowed for x to take the value True then you're in one of those two cases, and so you would not write if x is True. The important thing is to correctly document the meaning of x, so that it reflects the test used in the code.
Python programmers are expected to know what's considered true, so if you just document, "runs the function if x is true", then that expresses what your original code does. Documenting it, "runs the function if x is True" would have a different meaning, and is less commonly used precisely because of the style rule in PEP8 that says to test for trueness rather than the specific value True.
However, if you wanted the code to behave differently in the case where x is an empty container from the case where it is None, then you would write something like if x is not None.
I'd like to add a short example where those 3 tests differ:
def test(x):
print(x, ":", bool(x), x == True, x is True)
test("something")
test(1)
test(True)
The output (pretty formatted):
# "something" : True False False
# 1 : True True False
# True : True True True
x = 'False'
x = 123
Are both True
Other truth values.
The document explains other values.
As far as the PEP8 reason, its far more semantic to read if this_file_is_green
Other falsey values include 0, '', []. You should just use the if x: version.
It goes without saying that you should write code that does what you need. But in most cases, you simply don't need to say == True or is True, because you don't need to distinguish True from other "truthy" values. So it's recommended to leave that out for simplicity.
The case where you definitely should use == True or is True is when you do need to distinguish True from other truthy values.
In your example, do you care about the difference between True and 123? That would tell you which way to code it.
One thing about coding == True or is True: it will raise a minor red flag when other developers read your code. They won't think it's wrong, they will just wonder why it's there and will want to know why it's important to treat True differently from other truthy values in this particular case.
In other words, if you don't need it, it's best not to use it.
The ability to say
if x:
...
is considered a feature. You can also specify when the test should be considered to pass or not for user defined classes (just define the method __nonzero__ in Python 2.x or __bool__ in Python 3).
For example for strings and containers like lists, dictionaries or sets the test if x ... means "if x is not empty".
Note that the rationale is not that this allows less code to write, but that resulting code is easier to read and to understand.
If you like instead to write if x is True ... have you considered to go farther down that path to if (x is True) is True ... or if ((x is True) is True) is True ... ? :-)
In Python 2.7, if a: and if a==True are not giving the same output for values different to 1. Here are some snippets of code to demonstrate the different behaviors:
with a=1
a=1
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (1,True)
a=1
if a:
print (a,"True")
else:
print (a,"Not True")
output> (1, True)
with a=2
a=2
if a:
print (a,"True")
else:
print (a,"Not True")
output> (2, True)
a=2
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (2, Not True)
if you use if x ,it means it has to evaluate x for its truth value.But when you use x ==True or x is True.It means checking whether type(x)==bool and whether x is True.
attention : x is True is no equal to bool(x)==True
when you use x is True , you are checking the id of x and True.
Apologies if this has been asked before, but I have searched in vain for an answer to my exact question. Basically, with Python 2.7, I have a program running a series of geoprocessing tools, depended on what is reqested via a series of True/False variables that the user adjusts in the script e.g.
x = True
if x:
run function
However, I have now discovered that x does not need to be literally "True" for the function to run. For example:
In: x = True
if x:
print True
Out: True
In: x = 123
if x:
print True
Out: True
In: x = 'False'
if x:
print True
Out: True
In: x = False
if x:
print True
Out:
So any value other than False appears to evaluate to True, which would not be the case for if x == True or if x is True. Seeing as PEP 8 strongly recommends only using the if x: variant, can anybody explain why this behaviour occurs? It seems that if x: is more a test for "if x is not False" or "if x exists". With that in mind, I believe I should be using if x is True: in this case, despite what PEP 8 has to say.
The following values in Python are false in the context of if and other logical contexts:
False
None
numeric values equal to 0, such as 0, 0.0, -0.0
empty strings: '' and u''
empty containers (such as lists, tuples and dictionaries)
anything that implements __bool__ (in Python3) to return False, or __nonzero__ (in Python2) to return False or 0.
anything that doesn't implement __bool__ (in Python3) or __nonzero__ (in Python2), but does implement __len__ to return a value equal to 0
An object is considered "false" if any of those applies, and "true" otherwise, regardless of whether it's actually equal to or identical with False or True
Now, if you've arranged that x is necessarily one of the objects True or False, then you can safely write if x. If you've arranged that the "trueness" of x indicates whether or not to perform the operation, regardless of type, then you can safely write if x. Where you can write that you should prefer to do so, since it's cleaner to read.
Normally, if it is allowed for x to take the value True then you're in one of those two cases, and so you would not write if x is True. The important thing is to correctly document the meaning of x, so that it reflects the test used in the code.
Python programmers are expected to know what's considered true, so if you just document, "runs the function if x is true", then that expresses what your original code does. Documenting it, "runs the function if x is True" would have a different meaning, and is less commonly used precisely because of the style rule in PEP8 that says to test for trueness rather than the specific value True.
However, if you wanted the code to behave differently in the case where x is an empty container from the case where it is None, then you would write something like if x is not None.
I'd like to add a short example where those 3 tests differ:
def test(x):
print(x, ":", bool(x), x == True, x is True)
test("something")
test(1)
test(True)
The output (pretty formatted):
# "something" : True False False
# 1 : True True False
# True : True True True
x = 'False'
x = 123
Are both True
Other truth values.
The document explains other values.
As far as the PEP8 reason, its far more semantic to read if this_file_is_green
Other falsey values include 0, '', []. You should just use the if x: version.
It goes without saying that you should write code that does what you need. But in most cases, you simply don't need to say == True or is True, because you don't need to distinguish True from other "truthy" values. So it's recommended to leave that out for simplicity.
The case where you definitely should use == True or is True is when you do need to distinguish True from other truthy values.
In your example, do you care about the difference between True and 123? That would tell you which way to code it.
One thing about coding == True or is True: it will raise a minor red flag when other developers read your code. They won't think it's wrong, they will just wonder why it's there and will want to know why it's important to treat True differently from other truthy values in this particular case.
In other words, if you don't need it, it's best not to use it.
The ability to say
if x:
...
is considered a feature. You can also specify when the test should be considered to pass or not for user defined classes (just define the method __nonzero__ in Python 2.x or __bool__ in Python 3).
For example for strings and containers like lists, dictionaries or sets the test if x ... means "if x is not empty".
Note that the rationale is not that this allows less code to write, but that resulting code is easier to read and to understand.
If you like instead to write if x is True ... have you considered to go farther down that path to if (x is True) is True ... or if ((x is True) is True) is True ... ? :-)
In Python 2.7, if a: and if a==True are not giving the same output for values different to 1. Here are some snippets of code to demonstrate the different behaviors:
with a=1
a=1
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (1,True)
a=1
if a:
print (a,"True")
else:
print (a,"Not True")
output> (1, True)
with a=2
a=2
if a:
print (a,"True")
else:
print (a,"Not True")
output> (2, True)
a=2
if a==True:
print (a,"True")
else:
print (a,"Not True")
output> (2, Not True)
if you use if x ,it means it has to evaluate x for its truth value.But when you use x ==True or x is True.It means checking whether type(x)==bool and whether x is True.
attention : x is True is no equal to bool(x)==True
when you use x is True , you are checking the id of x and True.
I found a snippet in our code base that looks kind of useless to me but I suspect that somebody put it there for a reason that eludes me; so I thought I'd ask around. The part is something like this:
someParam = 'nope' # someParam is actually a query result, not a fixed string
if someParam != 'nope' and True or False
In my opinion the and True or False is doing exactly nothing for the evaluation and can be removed since the first part, the equality check, combined with the and True (operator precedence and > or, IIRC) is the same as the first part:
If first part evaluates to True -> True and True -> True
If the first part is False -> False and True -> False
now those results with the appended or False:
True or False -> True
False or False -> False
So the result of the condition would not change if I removed the and True or False, correct? Or am I missing something here?
Also could the behaviour of this change while switching from Python 2 to 3? I think not but I'm not quite sure.
You can remove and True or False from if statement, as it return same result what someParam != 'nope' will give.
You can check it by simple example as:
True and True or False
The output is always True Whereas
False and True or False
The output is always False
As you say, the expression foo and True or False is just a complicated way of converting the "truthiness" of the value foo into an actual boolean:
>>> 'foo' and True or False # non-empty strings are truth-y
True
>>> '' and True or False # empty strings are false-y
False
(You can see the rules for built-in types' truthiness here.)
This is because and and or return one of their operands, per the docs:
The expression x and y first evaluates x; if x is false, its
value is returned; otherwise, y is evaluated and the resulting value
is returned.
The expression x or y first evaluates x; if x is true, its value
is returned; otherwise, y is evaluated and the resulting value is
returned.
and, as you say, the operator precedence for and is higher than or.
That code is totally redundant, for a number of reasons:
Because Python already gives you a built-in way to do that, bool:
>>> bool('foo')
True
>>> bool('')
False
Because foo is already a boolean anyway; != is a comparison, and the result of any comparison is either True or False, so any conversion to boolean is redundant.
Because in a context like if foo:, even if foo wasn't already boolean, Python will automatically evaluate the truthiness of foo rather than only accepting a boolean, so if foo and True or False: and if bool(foo) are both pointless; you can just write if foo:.
And no, none of the above points changed between Python 2 and 3. You can check the equivalent links for all of the above in the new version:
Truthiness
Boolean operations
Operator precedence
bool
Comparisons
Yes, x and True or False can be simplified to just x when x is a boolean value.
I am reading about booleans in my book, and it says:
x and y------------If x is false, return x. Otherwise, return y.
x or y--------------If x is true, return x. Otherwise, return y.
This doesn't make sense to me from the everyday usage of "or" and "and"
To me, it would make sense if it said:
x and y------------If x is false, do nothing. If y is false, do nothing. If x and y are true, return x and y
x or y--------------If x is true, return x. If x is false, check y. If y is false, do nothing. If y is true, return y
Do I just need to blindly accept the actual definitions, or can I understand them because they actually make sense.
"Do nothing" isn't an option. The mathematical expression x or y must have a value (which is true if either x, y, or both is true). And x and y must have a value (which is true if and only if x and y are both true).
The way your book defines them is mathematically correct, but confusing (until you get into things like short-circuit evaluation).
The behavior may seem strange, but consider the following hypothetical examples. Starting with something obvious,
>>> True and False
False
>>> False and True
False
this is really easy to understand since we're dealing with boolean values. Remember this example, because every other example can be thought of this way.
Now consider if the and and or operators were to convert every object to a boolean before comparing. For example, an empty string or empty list would be False, and non-empty ones would be True. It would look like this (obviously this is not what it ACTUALLY looks like)
>>> "vanilla" and ""
False
>>> "" and "vanilla"
False
This makes perfect sense. After all bool("vanilla") and bool("") would be the same as True and False which we already know is False
Instead of actually converting them to True or False, though, it can do the comparison without ever converting them. As a result, you don't really need it to return True or False. It can just return the actual object it tested.
>>> "vanilla" and ""
""
>>> "" and "vanilla"
""
For truth testing purposes, returning "" is the same as returning False, so there's no need to convert it to a boolean. That's why it always returns an object whose truth value is the same as the result of the operator.
Unlike some other languages, you can use any object as operands of boolean operations. All your books says is that you can use boolean operators as a quick "filter" of values.
For instance, say you want to choose a non-empty list between two lists. The following is a valid (and more Pythonic) way to do it:
>>> [] or ['something', 'here']
['something', 'here']
Contrast to (not making use of Python idioms in Python):
if len(l1) != 0:
return l1
else:
return l2
Your book is right - see the documentation. It might be unintuitive at first, but this behavior (called short-circuiting) is extremely useful. In a simple case, it allows you to save a lot of time when checking certain conditions. In this example, where function f takes 10 seconds to evaluate, you can definitely see one use:
if f(foo) or f(bar) or f(baz):
If f(foo) is True, then there is no need to evaluate f(bar) or f(baz), as the whole if statement will be True. Those values are unnecessary and you'll just be wasting your time computing them.
Another extremely common use of this behavior is in null (or for python None) checking. It allows safe usage of functions all within one line:
if obj != None and obj.foo():
If obj is None, the if statement is guaranteed to be False, and so there is no need to check (or even evaluate) obj.foo(), which is good, since that would cause an exception.
Short-circuiting is very common in many programming languages, and is very useful once you fully understand how to use it.
While the book presents it in a slightly confusing way, it is correct. Boolean logic must evaluate to either true or false.
For X and Y in order to return true they both must be true, if X is false then it returns false. If X is true then it returns Y which is either true or false and also the correct answer.
For X or Y to return false they both must be false. If X is true then it can return true (X). If X is false then it returns whatever the value of Y is.
Many (most?) programming languages, including Python, implement short-circuiting in their boolean operators and and or. So they evaluate their operands from left to right, and stop as soon as the final result can be determined.
Since x and y and z and ... is guaranteed be false if any operand is false, it stops evaluating the operands as soon as it encounters a false one. And x or y or z or ... is guaranteed to be true if any operand is true, so it stops as soon as it reaches a true operand. In either case, if they make it all the way to the last operand, they return its value.
In some languages, the boolean operators just return a strict boolean result, either true or false (in some languages these are represented as 1 and 0). But in Python (and some others, such as Javascript and Common Lisp), they return the value of the last operand that was evaluated, which determined the final result. This is often more useful than just the truth value of the expression.
When you put these features together, it allows some succinct idioms, e.g.
quotient = b != 0 && a/b
instead of
if b != 0:
quotient = false
else:
quotient = a/b
The first set of descriptions are shortcuts: following these will give you exactly the same results as the "usual definitions" of true and false.
But your own descriptions don't make much sense. You can't "do nothing"; you have to return some value from a comparison, either true or false. And you can't return both a and b, either: again, the result of a boolean comparison must be a boolean, not a pair of booleans.
Its probably easier if you think about it in each literal case
x and y------------If x is false, return x. Otherwise, return y.
x or y--------------If x is true, return x. Otherwise, return y.
CASE 1: x = true, y = true
"if x is false, return x. Otherwise, return y."
Then this will return y which is true. This makes sense because x and y are both true.
(true and true == true)
"If x is true, return x. Otherwise, return y."
The this will return x which is true. This makes sense because one of x or y is true.
(true or true == true)
CASE 2: x = false, y = true
"if x is false, return x. Otherwise, return y."
Then this will return x which is false. This makes sense because x and y are not both true.
(false and true == false)
"If x is true, return x. Otherwise, return y."
The this will return y. This makes sense because one of x or y is true.
(false or true == true)
CASE 3: x = true, y = false
"if x is false, return x. Otherwise, return y."
Then this will return y which is false. This makes sense because x and y are not both true.
(true and false == false)
"If x is true, return x. Otherwise, return y."
Then this will return x which is true. This makes sense because x or y is true
(true or false == true)
CASE 4: x = false, y = false
"if x is false, return x. Otherwise, return y."
Then this will return x which is false. This makes sense because x and y are not both true.
(false and false == false)
"If x is true, return x. Otherwise, return y."
The this will return y which is false. This makes sense because neither x nor y is true.
(false or false == false)
Can anybody explain why in python builtin buinction all return True in this case all([])?
In [33]: all([])
Out[33]: True
In [34]: all([0])
Out[34]: False
In [35]: __builtins__.all([])
Out[35]: True
I'm not convinced that any of the other answers have really address the question of why this should be the case.
The definition for Python's all() comes from boolean logic. If for example we say that "all swans are white" then a single black swan disproves the statement. However, if we say that "all unicorns are pink" logicians would take that as a true statement simply because there are no non-pink unicorns. Or in other words "all " is vacuously true.
Practically it gives us a useful invariant. If all(A) and all(B) are both true then the combination of all(A + B) is also true. If all({}) was false we should have a less useful situation because combining two expressions one of which is false suddenly gives an unexpected true result.
So Python takes all([]) == True from boolean logic, and for consistency with other languages with a similar construct.
Taking that back into Python, in many cases the vacuous truth makes algorithms simpler. For example, if we have a tree and want to validate all of the nodes we might say a node is valid if it meets some conditions and all of its children are valid. With the alternative definition of all() this becomes more complex as we have to say it is valid if it meets the conditions and either has no children or all its children are valid.
class Node:
def isValid(self):
return some_condition(self) and all(child.isValid for child in self.children)
From the docs:
Return True if all elements of the iterable are true (or if the iterable is empty).
So, roughly, it's simply defined this way.
You can get around that by using
list = []
if list and all(list):
pass
As the docs say, all is equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
For an empty iterable the loop body is never executed, so True is immediately returned.
Another explanation for this is that all and any are generalisations of the binary operators and and or for arbitrarily long numbers of parameters. Thus, all and any can be defined as:
def all(xs):
return reduce(lambda x,y: x and y, xs, True)
def any(xs):
return reduce(lambda x,y: x or y, xs, False)
The True and False parameters show that all([]) == True and any([]) == False.
Any expression with all can be rewritten by any and vice versa:
not all(iterable)
# is the same as:
any(not x for x in iterable)
and symmetrically
not any(iterable)
# is the same as:
all(not x for x in iterable)
These rules require that all([]) == True.
The function all is very useful for readable asserts:
assert all(required_condition(x) for x in some_results_being_verified)
(It is not so bad if a task has no results, but something is very broken if any result is incorrect.)