short circuiting – Where are the ampersand and vertical bar characters used in Python?

short circuiting – Where are the ampersand and vertical bar characters used in Python?

The wikipedia page is wrong, Ive corrected it. | and & are not boolean operators, even though they are eager operators, which just means that they are not short circuit operators. As you probably know, heres how the python and and or operators work:

>>> def talk(x):
...     print Evaluating: , bool(x)
...     return x
... 
>>> talk(1 == 1) or talk(2 == 1)   # 2 == 1 is not evaluated
Evaluating:  True
True
>>> talk(1 == 1) and talk(2 == 1)
Evaluating:  True
Evaluating:  False
False
>>> talk(1 == 2) and talk(1 == 3)  # 1 == 3 is not evaluated
Evaluating:  False
False

As far as I know, python has no eager boolean operators, they would have to be explicitly coded, for instance like this:

>>> def eager_or(a, b):
...    return a or b
...
>>> eager_or(talk(1 == 1), talk(2 == 1))
Evaluating:  True
Evaluating:  False
True

Now a and b are automatically evaluated when the function is called, even though or still short circuits.

As for the usage of | and &, when used with numbers, they are binary operators:

>>> bin(0b11110000 & 0b10101010)
0b10100000
>>> bin(0b11110000 | 0b10101010)
0b11111010

Youre most likely to use | this way with python bindings to libraries that uses flags, like wxWidgets:

>>> frame = wx.Frame(title=My Frame, style=wx.MAXIMIZE | wx.STAY_ON_TOP)
>>> bin(wx.MAXIMIZE)
0b10000000000000
>>> bin(wx.STAY_ON_TOP)
0b1000000000000000
>>> bin(wx.MAXIMIZE | wx.STAY_ON_TOP)
0b1010000000000000

When used with sets, they do the intersection and union operations, respectively:

>>> set(abcd) & set(cdef)
set([c, d])
>>> set(abcd) | set(cdef)
set([a, c, b, e, d, f])

Something missing from the other answers here is that & and | dont have any universal meaning in Python; their meaning depends on the operands types, using the magic __and__ and __or__ methods. Since these are methods, the operands are both evaluated (i.e. without short-circuiting) before being passed as arguments.

On bool values they are logical and and logical or:

>>> True & False
False
>>> True | False
True
>>> bool.__and__(True, False)
False
>>> bool.__or__(True, False)
True

On int values they are bitwise and and bitwise or:

>>> bin(0b1100 & 0b1010)
0b1000
>>> bin(0b1100 | 0b1010)
0b1110
>>> bin(int.__and__(0b1100, 0b1010))
0b1000
>>> bin(int.__or__(0b1100, 0b1010))
0b1110

On sets, they are intersection and union:

>>> {1, 2} & {1, 3}
{1}
>>> {1, 2} | {1, 3}
{1, 2, 3}
>>> set.__and__({1, 2}, {1, 3})
{1}
>>> set.__or__({1, 2}, {1, 3})
{1, 2, 3}

A couple of extra notes:

  • The __and__ and __or__ methods are always looked up on the class, not on the instance. So if you assign obj.__and__ = lambda x, y: ... then its still obj.__class__.__and__ thats invoked.
  • The __rand__ and __ror__ methods on the class will take priority, if they are defined.

See the Python language reference for more details.

short circuiting – Where are the ampersand and vertical bar characters used in Python?

It means the left operand and the right operand are always evaluated. & is the bitwise AND operator and | is the bitwise OR operator.

Leave a Reply

Your email address will not be published.