1
22 and 333/12 or 1

I have encountered the above line of code. The result is 27, but I could not quite understand what does and and or mean in this case. Can somebody explain to me, preferred with examples. Thanks in advance!!

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
sammiwei
  • 3,140
  • 9
  • 41
  • 53
  • Note this trick doesn't work if you want it to result in a value that is False when the condition is True -- `22 and None or 1` would give `1` not `None`. `(None, 1)[22]` does work, so long as it is OK for both the True and False values to be evaluated, as it doesn't short circuit. – agf Mar 21 '12 at 02:16

5 Answers5

10

This is the "and-or trick" -- and and or don't actually return boolean values; instead, they return one of their input arguments. People used to use this for control-flow.

As of python 2.5, it's not necessary anymore, because conditional expressions were introduced.

22 and 333/12 or 1

is equivalent to

333/12 if 22 else 1
Ismail Badawi
  • 36,054
  • 7
  • 85
  • 97
  • 6
    The "`if else`" is far more readable. I'd hope people aren't still resorting to the and/or trick. – Anorov Mar 21 '12 at 01:51
  • I think the inline `if ... else ...` wasn't implemented in older Python versions, so scripts that support them might still use it. – Blender Mar 21 '12 at 01:53
  • @Anorov It's more than readability, see my comment on the question. – agf Mar 21 '12 at 02:18
  • "and-or trick" link is broken. `cond and x or y ` is not a logical equivalent for `x if cond else y`. A correct equivalent is `(cond and [x] or [y])[0]`. – wim Oct 15 '19 at 02:38
6

A and B returns A if A is false, or B otherwise:

>>> 0 and 1
0
>>> False and True
False
>>> True and 'yes'
'yes'
>>> True and ''
''

Similarly, 'A or B' returns A if A is true, or B otherwise:

>>> 0 or 1
1
>>> False or True
True
>>> '' or 'yes'
'yes'
>>> False or ''
''
>>> 'yes' or ''
'yes'
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • And since `and` has a higher precedence in Python than `or`, `22 and 333/27` gets evaluated rather than `333/12 or `. `0 and 333/27 or 1` would return `1`. – Michael Berkowski Mar 21 '12 at 01:44
1

In Python, nonzero numbers are counted as true for the purposes of boolean expressions, and zero is counted as false. So even though both and and or are normally used with the booleans True and False, they can be used with numbers too.

The issue is: what is the value of an expression like 10 and 3, where both of the values evaluate to true? In C, which has similar integer-as-boolean semantics, the value of 10 && 3 is 1, the most commonly used true value. However, in Python the value of this expression is 3, the second half of the and expression. This makes sense because and short-circuits, meaning that 0 and 3 is 0, so and has "take the first value if it's false, the second otherwise" semantics.

What about the expression you posted? By operator precedence, it's the same as

(22 and 333/12) or 1

The value of 22 and 333/12 is 333/12, which is 27. Since the or operator short-circuits, the Python interpreter takes the first true value when evaluating 27 or 1, and gets 27.

Adam Mihalcin
  • 14,242
  • 4
  • 36
  • 52
0

Let's separate this out:

22 and 333/12 or 1
(22 and 333/12) or (1) # Parentheses are nice
(22 and 27) or (1)     # 333/12 = 27 because you are using integers for division
22 and 27              # 22 and 27 is True, as neither of them is False
27                     # Not sure why anything is returned, but the second
                       # value always returned if it is True
Blender
  • 289,723
  • 53
  • 439
  • 496
0

The logical operands and,or will come after division operator in this particular scenario as per the rules of precedence.

First it will calculate 333/12 which is 27 and then it will become 22 and 27 or 1 which is equivalent to 27 as and,or have equal precedences.

22 and 333/12 or 1
22 and 27 or 1
(22 and 27) or 1  OR 22 and (27 or 1)

27 ,27

But in case of Python 3.2 it's computing to 27.75.

>>> 22 and 333/12 or 1
27.75
>>> (22 and 333/12) or 1
27.75
>>> 22 and (333/12 or 1)
27.75
Teja
  • 13,214
  • 36
  • 93
  • 155