Boolean operators vs Bitwise operators
Here are a couple of guidelines:
- Boolean operators are usually used on boolean values but bitwise operators are usually used on integer values.
- Boolean operators are short-circuiting but bitwise operators are not short-circuiting.
The short-circuiting behaviour is useful in expressions like this:
if x is not None and x.foo == 42:
# ...
This would not work correctly with the bitwise &
operator because both sides would always be evaluated, giving AttributeError: 'NoneType' object has no attribute 'foo'
. When you use the boolean and
operator the second expression is not evaluated when the first is False. Similarly or
does not evaluate the second argument if the first is True.
In theory, and
and or
come straight from boolean logic (and therefore operate on two booleans to produce a boolean), while &
and |
apply the boolean and/or to the individual bits of integers. There are a lot lot of questions here on how the latter work exactly.
Here are practical differences that potentially affect your results:
and
andor
short-circuiting, e.g.True or sys.exit(1)
will not exit, because for a certain value of the first operand (True or ...
,False and ...
), the second one wouldn't change the result so does not need to be evaluated. But|
and&
don't short-circuit -True | sys.exit(1)
throws you outta the REPL.&
and|
are regular operators and can be overloaded, whileand
andor
are forged into the language (although the special method for coercion to boolean may have side effects).- This also applies to some other languages with operator overloading
and
andor
return the value of an operand instead ofTrue
orFalse
. This doesn't change the meaning of boolean expressions in conditions -1 or True
is1
, but1
is true, too. But it was once used to emulate a conditional operator (cond ? true_val : false_val
in C syntax,true_val if cond else false_val
in Python). For&
and|
, the result type depends on how the operands overload the respective special methods (True & False
isFalse
,99 & 7
is3
, for sets it's unions/intersection...).- This also applies to some other languages like Ruby, Perl and Javascript
But even when e.g. a_boolean & another_boolean
would work identically, the right solution is using and
- simply because and
and or
are associated with boolean expression and condition while &
and |
stand for bit twiddling.
Here's a further difference, which had me puzzled for a while just now: because &
(and other bitwise operators) have a higher precedence than and
(and other boolean operators) the following expressions evaluate to different values:
0 < 1 & 0 < 2
versus
0 < 1 and 0 < 2
To wit, the first yields False
as it is equivalent to 0 < (1 & 0) < 2
, hence 0 < 0 < 2
, hence 0 < 0 and 0 < 2
.