Here we discuss three additional concepts related to Conditional expressions. Comparison chaining is a useful characteristic of the Python language, and precedence and short-circuiting are especially important for understanding how logical expressions are evaluated.
1. Comparison Chaining
Python supports chaining of comparison operators. For example, x < f(y) < z is equivalent to x < f(y) and f(y) < z, except that f(y) is only called once. This is a useful feature of Python that is not present in some other popular languages, such as Java.
2. Precedence of Logical Operators
Like the order of operations in math, programming language operators have well-defined precedence. Arithmetic operators typically follow an order that is very similar to the order of operations one learns in basic algebra classes. For example, division and multiplication will execute before addition and subtraction. Similarly, the logical operators follow a specific order for performing the different operations. Like the algebraic order of operations, logical expressions enclosed in parentheses have highest precedence. Then, from left to right, the operators will execute in the following order: not, and, and or.
Given a = true, b = false, and c = true, evaluate the following expression:
!(a and b) or (c or !b and a) and !(!c and (a or b))
(a) Substitute values in for a, b, and c.
!(true and false) or (false or !false and true) and !(!true and (true or false))
(b) Evaluate expression following this order: parenthesized expressions, not, and, and or (from left to right).
- !false or (false or true and true) and !(false and true)
- true or (false or true) and !false
- true or true and true
- true or true
Sometimes it is possible to determine the truth value of an expression without evaluating every clause of the expression. This is called short-circuiting, and is a useful feature of most programming languages. There are two main ways that short-circuiting can occur.
- and: Since an and-expression is true if and only if both clauses are true, if the first clause is false, the entire expression is false regardless of the truth value of the second clause. (i.e. if a = false, then a and b is false regardless of what b is because false and true is false, and false and false is also false.)
- or: Since an or-expression is true if at least one of the clauses is true, if the first clause is true, the entire expression is true regardless of the truth value of the second clause. (i.e. if a = true, then a or b is true regardless of what b is because true or true is true, and true or false is also true.)
NOTE: Since Python expressions are evaluated from left to right, short-circuiting will only happen from left to right.
a = false b = input() c = input() !(a and b) or c #will evaluate to false regardless of user input
Due to short-circuiting, we can show that the expression will be false regardless of the input. First, the parenthesized expression (a and b) will short-circuit to false because false and b = false. Then the whole expression will short-circuit to true because !false or c = true or c = true.
Short-circuiting is useful for increasing efficiency because it avoids unnecessary execution of operations. It is also useful for handling possible errors. The following example will illustrate this.
a = input("Enter a number: ") if (a > 0 and 100 % a == 0): print "100 is divisible by ", a
Since a is determined by the user, the user could enter 0, and the expression 100 % a would result in a DivisionError if a equaled 0. This is avoided, however, by evaluating a > 0 first since the entire expression will short-circuit to false if a is not positive.
This video illustrates examples of short-circuit evaluation. Video Length: 5:24