61

In the Wikipedia page describing short-circuit evaluation, & and | are listed as eager operators in Python. What does this mean and when are they used in the language?

Yktula
  • 14,179
  • 14
  • 48
  • 71

4 Answers4

81

The wikipedia page is wrong, I've 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, here's 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'

You're 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'])
Lauritz V. Thaulow
  • 49,139
  • 12
  • 73
  • 92
  • 18
    They're also used in `pandas` for complex query strings on data frames, such as `df[ (df['Age'] > 40) & (df['Weight'] < 100)]`. – cod3monk3y Jan 12 '15 at 01:21
  • @cod3monk3y I just saw this usage in NumPy too and was confused at first, but I guess there's no other simple way to combine boolean arrays for indexing. – endolith Jul 07 '16 at 00:42
  • 1
    You're absolutely right but chose a bad example ;) Python treats `bool` class values as integers in bitwise operations (`0 == False` and `1 == True` are both true) so your example will work with `&` and `|` acting like eager logical operators. – Nuno André Jul 30 '16 at 18:00
  • 1
    `&` and `|` do indeed work with `True` and `False`, and not just implicitly because they're 0 and 1: for example, `True | False` is `True`, not 1. – kaya3 Mar 07 '20 at 17:35
  • Since [python 3.9](https://docs.python.org/3.9/library/stdtypes.html#dict) `|` is now finally used for union of dictionaries as well: `{'a': 1, 'b': 2} | {'c': 3, 'b': 4}` becomes `{'a': 1, 'b': 4, 'c': 3}`. Sadly other set operators have yet to be added to dict as of yet. – wihlke Nov 28 '21 at 14:02
31

Something missing from the other answers here is that & and | don't 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 it's still obj.__class__.__and__ that's invoked.
  • The __rand__ and __ror__ methods on the class will take priority, if they are defined.

See the Python language reference for more details.

kaya3
  • 47,440
  • 4
  • 68
  • 97
10

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

icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • so does eager mean they don't use short-circuit evaluation like the logical operators? –  Jun 27 '11 at 05:37
  • @Keoki Zee: yes. Eager is the opposite of [lazy](https://secure.wikimedia.org/wikipedia/en/wiki/Lazy_evaluation). – Fred Foo Jun 27 '11 at 05:39
  • 2
    @Keoki - Yes, they don't short-circuit. If you think of them as arithmetic operators like `+` or `-`, instead of boolean operators, then you'll realise that talking about "short-circuiting" doesn't really make sense. – detly Jun 27 '11 at 05:40
5

& ----> Used to AND bitwise i.e. bit by bit

similarly,

| ---> used to OR bitwise

Whenevr you find any python problem, try to use python.org, its helpful

Stuti
  • 1,620
  • 1
  • 16
  • 33
  • 3
    @down voter : Please write the comment for your down voting, Is this wrong – Stuti Jun 27 '11 at 05:44
  • 4
    not a helpful comment. have you tried looking for documentation using keywords '&' and '|'? Also, you didn't answer the question: "What does this mean and when are they used in the language?" – warvariuc Jun 27 '11 at 05:51
  • 2
    @warvariuc, whats hard about reading the documentation? Go to docs.python.org, click on 'General Index', this gives you choices 'Symbols', '_', 'A', 'B', etc. Click on Symbols and you'll find '&' right near the top (but admittedly not '|'). Click on the '&' entry and it tells you all about both. Failing that, interactive prompt and type `help('&')` or `help('|')` for a useful table of operators. – Duncan Jun 27 '11 at 07:50
  • if you edit your answer i will be able to cancel my down-vote. what about adding these hints how to find the help on these operators? – warvariuc Jun 27 '11 at 08:09
  • 2
    i downvoted you because in my opinion you didn't answer the question "What does this mean", but i guess the topic starter didn't use the right word (should he have used "these"?). – warvariuc Jun 27 '11 at 08:11
  • 5
    I tried python.org first and was unable to find "|". This is due to my own ignorance. As evidenced by my own experience, by the time someone posts asking what "|" is I think that it is reasonable to assume that they might not know how to find '|' in the documentation. "Look in the documentation" is not an answer, but "Look in the documentation: http://docs.python.org/2/library/stdtypes.html#index-19" is. – Eric Kightley Aug 02 '13 at 14:37