Question

After having a lot of trouble trying to reduce nested ifs (and a script that stopped working), I realized perhaps I am having the wrong idea of what and how boolean stuff works in python.

I had this (working fine but contorted):

if (not gotside):
    if (j > 1):
        if (j < a.shape[1] - 1):
            if a[i, j+unit]:
                print "only now I do stuff!"

And tried this (looking sreamlined by not working as desired):

if (not gotside) and (j > 1) and (j < a.shape[1] - 1) and a[i, j+unit]:
    print "I'm well tested but not so indented..."

Then I tried to use "or" instead of "and", but didn' work, because (later I found) when you use x and y or even x or y you get one of x, y, and not one of True, False, acording to docs.

So, I don't know how I can put a handful of tests one after another (preferrably in the same line, with boolean operators) in a way that the whole expression returns False as soon as the first test evaluates to False.

Thanks for reading!

Was it helpful?

Solution

Your example should work.

if x and y and z:
    ...

Should happen only if none of x, y and z evaluate to False, and in Python, and short-circuits, so will return the False value as soon as one item fails. We can show this quite easily:

>>> def test(n):
...     print("test", n)
...     return n
... 
>>> test(1) and test(2)
test 1
test 2
2
>>> test(0) and test(2)
test 0
0
>>> test(0) and test(2) and test(3)
test 0
0
>>> test(1) and test(0) and test(3)
test 1
test 0
0

OTHER TIPS

I see your concern, but remember that whenever something is in an if statement in Python, it will be implicitly converted to bool for the conditional. Thus while 3 or 2 returns 3 and 3 and 2 returns 2 when done stand-alone, saying if 3 or 2 is actually equivalent to saying if bool(3 or 2), so you will get the falsey or truey value of what the logic returns when used in a conditional regardless of what the boolean logic would return in other contexts.

Yeah, I have to agree with the others in saying that your example should be working as you intend. You're right that x or y returns one of x, y, but that object will be able to be evaluated as True or False. That is how python evaluates if statements. It should work as written because your expressions will be evaluated in order and will return False once any test in the line returns as False (or 0, or [] or {} etc.). You can see that with a test that would raise an error if python actually tried it.

x = 1; y = 2
if x < y and x == y and d['a']: # d doesn't exist
    print 'This will never be printed'

If your code isn't working as intended, please elaborate on exactly what you expect it to do, and what it is actually doing.

I made some assumptions about the code you did not include and added it to get the program running:

gotside = False
j = 2
i = 1
unit = 3

class A:
    def __init__(self):
        self.shape = [1, 4]
    def __getitem__(self, pos):
        return pos

a = A()


if (not gotside):
    if (j > 1):
        if (j < a.shape[1] - 1):
            if a[i, j+unit]:
                print("only now I do stuff!")

if (not gotside) and (j > 1) and (j < a.shape[1] - 1) and a[i, j+unit]:
   print("I'm well tested but not so indented...")

For me this works with python 2.5, 2.6, 2.7 and 3.2:

only now I do stuff!
I'm well tested but not so indented...

Can you please check the above program if this works for you? If so, can you please give more information about the classes you use - especially the class of variable a.

The boolean and operator in Python (and most other programming languages) provides "short-circuit" functionality. This means, that if the fist term or the expression evaluates to false, the second term is not even evaluated:

>>> False and expensiveFunctionReturningBool()
False

The expensive function will never be called, because the Python interpreter immediately evalues the expression as False after the first term is determined to be False. This works, because in boolean logic, if one side of an and expression is false, the whole expression is false by definition

Python also uses short-circuit logic for or. In this case, if the first term is determined to be True, the second term is never evaluated.

>>> True or expensive()
True

Thus, boolean expressions can be used to collapse nested if statements (provided they are declared immediately one after another), and if they are used cleverly by keeping short-circuit logic in mind, they can also optimize conditional expressions.

Good Luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top