Search code examples
pythonternary-operatoridiomsor-operatorand-operator

Python what do 'and/or' mean in expression, and what does `(not i%2)` test?


I am learning python list comprehension and saw a usage and I couldn't find explanation in official document.

>>>[(not i%2)*'a' or str(i) for i in range(10)]
>>>['a', '1', 'a', '3', 'a', '5', 'a', '7', 'a', '9']

I am trying to abstract this usage in this way:

[statement1 or statement2 for i in range(10)]

and if statement1 is evaluated as false, then use statement 2, am I right?

I also discover that if I run the following command:

>>> [(not i%2)*'a' and str(i) for i in range(10)]

The output would be:

>>> ['0', '', '2', '', '4', '', '6', '', '8', '']

How should I understand these?


Solution

  • That's right. The weird part is the first expression:

    (not i%2)*'a'

    If i is odd, then this evaluates to 'a'; if even, it's False. This is a blatant abuse (a.k.a. expert trick) of boolean definition in Python.

    If you imagine True as 1 and False as 0, it makes sense. If the product is 0, the or operator takes it as False.

    This also takes advantage of expression short-circuiting: if the left element of the or is True, then the right one isn't evaluated at all, and that left element becomes the expression's value.

    Similarly, in your later example, the and short-circuit works the other way: if the left element is False, then it becomes the result; otherwise, the right element becomes the result.