Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange conversion in Python logic expressions

I noticed a strange behavior of Python 2.7 logic expressions:

>>> 0 and False
0
>>> False and 0
False
>>> 1 and False
False
>>> False and 1
False

and with True in place of False

>>> 0 and True
0
>>> True and 0
0
>>> 1 and True
True
>>> True and 1
1

Are there any rules when Python convert logical statement to integer? Why does it show sometimes 0 insted of False and 1 insted of True?

What is more, why does it return this?

>>>"test" or "test"
'test'
like image 908
Bartłomiej Szałach Avatar asked May 11 '13 11:05

Bartłomiej Szałach


1 Answers

Nothing is being converted; the Python boolean logic operators instead short circuit.

See the boolean operators documentation:

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.

Moreover, numbers that are equal to 0 are considered falsey, as are empty strings and containers. Quoting from the same document:

In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets).

Combining these two behaviours means that for 0 and False, the 0 is considered false and returned before evaluating the False expression. For the expression True and 0, True is evaluated and found to be a true value, so 0 is returned. As far as if and while and other boolean operators are concerned, that result, 0 is considered false as well.

You can use this to provide a default value for example:

foo = bar or 'default'

To really convert a non-boolean value into a boolean, use the bool() type; it uses the same rules as boolean expressions to determine the boolean value of the input:

>>> bool(0)
False
>>> bool(0.0)
False
>>> bool([])
False
>>> bool(True and 0)
False
>>> bool(1)
True

To complete the picture, values that are not considered false in a boolean context are instead considered true, including any custom classes. You can change that by implementing a .__nonzero__() special method on your class. If no such method is defined, .__len__() is consulted as well. With either of these methods you can signal that your type is either numeric and should be considered True if non-zero, or it is a container and should be considered True if not empty (has a length over 0).

like image 143
Martijn Pieters Avatar answered Oct 02 '22 07:10

Martijn Pieters