Martin McBride, 2018-08-23

Tags operator short circuit and or comparison operator logical operator

Categories python language intermediate python

Python has a useful feature called short circuit evaluation that acts on logical operators `or`

and `and`

.

Consider this code:

x = 5 y = 10 if x > 6 or y < 20: print('OK')

When Python reaches the if statement, it starts evaluating the terms from left to right:

`x > 6`

is false`y < 20`

is true- therefore the result of the
`or`

expression is true - the print statement executes

Now compare this code:

x = 7 y = 10 if x > 6 or y < 20: print('OK')

`x > 6`

is true- therefore the result of the
`or`

expression is true - the print statement executes

In this case, as soon as Python discovers that `x`

is greater than 6, it knows that the whole `or`

statement is true, so it doesn't bother checking `y`

. It doesn't matter whether `y`

is less than 20 or not, it won't affect the outcome because an `or`

statement is always true if either of the terms is true.

Python

guaranteesnot to evaluate the second term if the first term is true.

Short circuiting with the `and`

operator works in a similar way.

x = 5 y = 10 if x > 6 and y < 20: print('OK')

In this case:

`x > 6`

is false- therefore the result of the
`and`

expression is false - the print statement doesn't execute

In this case, Python never evaluates `y < 20`

because it already knows the final result will be false.

In summary:

- An
`or`

statement stops as soon as if encounters the first`True`

case - An
`and`

statement stops as soon as if encounters the first`False`

case

We can often use short circuit evaluation to avoid errors. A common case is checking for a value being 0 before performing a calculation:

n = 3 m = 2 if m < 1/n: print('m < 1/n')

This code looks alright at first glance. But what happens if `n`

is zero? Dividing by zero is an error, so our code would thrown an exception and stop working.

A quick way to avoid this is to use short circuiting, with the `and`

operator:

n = 0 m = 2 if n and m < 1/n: print('m < 1/n')

With this new code, we have an `and`

expression. The first term in `n`

. If `n`

is 0, which of course counts as false, Python knows that the whole an expression is false, so it never evaluates `1/n`

and there is no error.

If `n`

is not zero, Python evaluates the second expression as normal.

You need to take care with this technique. Although we have successfully avoided throwing a divide by zero error, we have also ignored the fact that

`n`

is zero. This could lead to further errors in other parts of the code.

You might expect the value of a logical expression to always be `True`

or `False`

, but in fact this isn't the case. Python does something more useful.

a = 0 b = 2 c = 3 x = c or a: print(x)

You may be surprised to see it print 3.

What actually happens is that Python prints the last value it evaluates. In this case, Python evaluates `c`

, which has a value 3. Since this counts as true, it doesn't need to evaluate `a`

, so it returns the value 3.

Here are some more examples, using the same values of `a`

, `b`

and `c`

:

x = a or b: print(x) #prints 2 x = b or c: print(x) #prints 2 x = 0 or a: print(x) #prints 0 (the result is false because 0 and a are both false) x = a or b+c or b+a: print(x) #prints 5 (b+c, the first true value)

Here is a real life example:

username='' username = username or input('Enter username')

In this case, the `or`

statement first evaluates `username`

, which is an empty string, so it counts as false. It then evaluates the `input`

statement - that is, it calls the `input`

function, waits for the user to type in their name, and returns that value.

If we were to execute this statement again, later, when `username`

has a value, the `or`

expression would simply return the current value, and would not call `input()`

at all.

It doesn't usually matter that `a`

or `b`

gives a value of 2 rather than `True`

, because it works fine in an if statement.

If you really need to, you can always use the `bool()`

function. `bool()`

converts *any* value to `True`

or `False`

.

Copyright (c) Axlesoft Ltd 2020