Python’s bitwise OR operator x | y
performs logical OR on each bit position on the binary representations of integers x
and y
. Each output bit evaluates to 1 if and only if at least one of the two input bits at the same position are 1. For example, the integer expression 4 | 3
is translated to the binary operation 0100 | 0011
which results in 0111
because for the last three positions at least one bit is 1.
As you go over the article, you can watch my explainer video here:
In this example, you apply the bitwise OR operator to two integers 32 and 16:
>>> 32 | 16 48
The expression 32 | 16
operates on the bit representations "010000"
(decimal 32) and "001000"
(decimal 16) and performs bitwise OR. Each "1"
position propagates remains in the result "110000"
(decimal 48):
First Operand x | 1 | 0 | 0 | 0 | 0 | 0 |
Second Operand y | 0 | 1 | 0 | 0 | 0 | 0 |
x | y | 1 | 1 | 0 | 0 | 0 | 0 |
Similarly, let’s have a look at a slightly modified example to showcase the bitwise OR operator:
>>> 31 | 15 31
You can see this in the following visualization:
First Operand x | 1 | 1 | 1 | 1 | 1 |
Second Operand y | 0 | 1 | 1 | 1 | 1 |
x | y | 1 | 1 | 1 | 1 | 1 |
The decimal representation of the bit sequence "11111"
is 31.
Python Bitwise | Operator Example
Here’s the result of the bitwise OR operator x | y
when applied to a couple of example integer operands x
and y
:
x (int) | y (int) | x (binary) | y (binary) | x | y (binary) | x | y (int) |
---|---|---|---|---|---|
0 | 1 | 0 | 1 | 1 | 1 |
0 | 3 | 00 | 11 | 11 | 3 |
3 | 5 | 0011 | 0101 | 0111 | 7 |
33 | 129 | 000100001 | 010000001 | 010100001 | 161 |
15 | 7 | 01111 | 00111 | 01111 | 15 |
14 | 7 | 01110 | 00111 | 01111 | 15 |
You can see those examples in the following Python script:
>>> 0 | 1 1 >>> 0 | 3 3 >>> 3 | 5 7 >>> 33 | 129 161 >>> 15 | 7 15 >>> 14 | 7 15
Next, you’ll learn how to use the operator on negative integers. But first, you need to understand how negative integers are represented in the first place. This will boost your computer science skills, so keep reading! ?β?
Representing Negative Integers in Binaries
Python uses so-called complementary binaries to represent negative integers. The first bit of a complementary binary is the sign (0: positive, 1: negative). All remaining bits encode the number. You write a negative number -x as the bit pattern for (x-1) and flip all bits from 1 to 0 and from 0 to 1 (complement).
Here are two simple examples:
- To represent
x = -1
using 8 bits you first calculate(1-1) = 0
and then flip all bits to calculate"11111111"
. - To represent
x = -10
using 8 bits you first calculate(10-1) = 9
which is"00001001"
in binary format. Then, you complement all bits to determine the negative (complementary) binary"11110110"
.
Let’s use this knowledge in a couple of examples to showcase the working of the bitwise OR operator on negative integers:
Python Bitwise OR | Examples on Negative Integers
Here’s the result of the bitwise OR operator x | y
when applied to example negative integer operands x
and y
:
x (int) | y (int) | x (binary) | y (binary) | x | y (binary) | x | y (int) |
---|---|---|---|---|---|
0 | -1 | 00000000 | 11111111 | 11111111 | -1 |
0 | -3 | 00000000 | 11111101 | 11111101 | -3 |
-3 | -5 | 11111101 | 11111011 | 11111111 | -1 |
You can see those examples in the following script:
>>> 0 | -1 -1 >>> 0 | -3 -3 >>> -3 | -5 -1
Python Bitwise OR versus Logical OR: “or” vs “|”
Python’s “or
” operator performs a logical OR operation that returns True
if at least one of the operands are True
. Python’s “|
” symbol is a bitwise operator that works on the bit representations of the operands and performs a bit by bit operation. So, “or
” tests whether at least one of the operands is logically True
whereas “|
” performs bitwise OR on the operands’ bit representations.
When considering only a single bit, semantically, the operators are the same:
>>> True or False True >>> True | False True
However, the difference becomes apparent if you use integer operands:
>>> 32 or 16 32 >>> 32 | 16 48
The first expression 32 or 16
determines that the integer value 32 results in a Boolean True
, so it returns the first operand 32 as it performs the short-circuiting optimization.
The second expression 32 | 16
operates on the bit representations 10000
(decimal 32) and 01000
(decimal 16) and performs bitwise OR resulting in 11000
(decimal 48):
First Operand x | 1 | 0 | 0 | 0 | 0 | 0 |
Second Operand y | 0 | 1 | 0 | 0 | 0 | 0 |
x | y | 1 | 1 | 0 | 0 | 0 | 0 |
Python Bitwise OR List and Set
To perform a bitwise OR operation on all elements in a given list of integers, import the NumPy library using import numpy as np
and call np.bitwise_or.reduce(my_list)
.
Here’s an example:
import numpy as np my_list = [1, 2, 3, 4, 5] res = np.bitwise_or.reduce(my_list) print(res) # 7
You can see the computation in the following table—the last row being the result of the bitwise OR operation on all elements in the list [1, 2, 3, 4, 5]
that correspond to binaries 0001
, 0010
, 0011
, 0100
, and 0101
.
Pos 0 | Pos 1 | Pos 2 | Pos 3 |
---|---|---|---|
0 | 0 | 0 | 1 |
0 | 0 | 1 | 0 |
0 | 0 | 1 | 1 |
0 | 1 | 0 | 0 |
0 | 1 | 0 | 1 |
0 | 1 | 1 | 1 |
If at least one bit in a column is set, the resulting bit is set as well. The decimal representation of binary 0111
is 7
which is the result of the previous code snippet.
Alternatively, if you want to perform a bitwise OR on all elements in a set, you can use the same idea of importng the NumPy library using import numpy as np
and calling np.bitwise_or.reduce(my_set)
.
import numpy as np my_set = [1, 2, 3, 4, 5] res = np.bitwise_or.reduce(my_set) print(res) # 7
Python Bitwise OR Bool
The Boolean values True
and False
can be semantically represented by a single bit 1
and 0
. Thus, if you apply the bitwise OR operation on two Boolean values using x | y
, the result is the same as if you’d apply the logical OR operation using x or y
. In both cases, the result is True
if and only if at least one of the operands is True
.
Here are the four ways to apply the bitwise OR operator to Boolean values:
>>> True | True True >>> True | False True >>> False | True True >>> False | False False
Compare this to the four ways of applying the logical OR operator to Boolean values:
>>> True or True True >>> True or False True >>> False or True True >>> False or False False
The outputs are exactly the same!
Python Bitwise OR Assignments (Equal)
The equal symbol after the bitwise OR operator (x |= y
) performs bitwise OR assignment operation. It calculates bitwise OR first and assigns the result to the variable x
. The bitwise OR assignment expression x |= y
is syntactic sugar for the semantically identical x = x | y
. The return value of the operator is None
but it updates the first operand with the result of the operation.
Here you can see that the variable x
changes after applying the assignment operator:
>>> x = 1 >>> y = 2 >>> x |= y >>> x 3 >>> y 2
Here’s the semantically identical version of this without the assignment operator:
>>> x = 1 >>> y = 2 >>> x = x | y >>> x 3 >>> y 2
Python Bitwise OR Overloading
You can define your own bitwise OR operator on a custom class by overloading the __or__
dunder method that not only makes x or y
work but also x | y
on your custom objects.
Here’s an example:
class Data: def __init__(self, data): self.data = data def __or__(self, other): return Data(self.data | other.data) x = Data(3) y = Data(4) res = x | y print(res.data) # 7
Note: If you want to define only bitwise OR, you can overload the __ror__(self, other)
method and if you want to define bitwise OR assignment, you can overload the __ior__(self, other)
dunder method.
Bitwise Operators
Bitwise operators perform operations on the binary (bit) representation of integers. The following table gives a short overview of all existing bitwise operators. Note that we also provide the binary representation 100
for the decimal integer 4
, and 101
for the decimal integer 5
as a comment in the right column.
Operator | Name | Description | Example |
---|---|---|---|
x = 4, y = 5 | |||
& | Bitwise AND | Performs logical AND on a bit-by-bit basis | x & y |
| | Bitwise OR | Performs logical OR operation on a bit-by-bit basis | x | y |
~ | Bitwise NOT | Performs logical NOT on a bit-by-bit basis, inverting each bit so that 0 becomes 1 and 1 becomes 0. Same as -x-1 . | ~x |
^ | Bitwise XOR | Performs logical “exclusive or” operation on a bit-by-bit basis | x ^ y |
>> | Bitwise right shift | Shifts binary of left operand to the right by the number of positions specified in right operand | x >> 2 |
<< | Bitwise left shift | Shifts binary of left operand to the left by the number of positions specified in right operand | x << 2 |
Here’s a short overview of the Bitwise operators’ magic methods:
Bitwise Operator | Magic “Dunder” Method |
---|---|
& | __and__(self, other) |
| | __or__(self, other) |
^ | __xor__(self, other) |
~ | __invert__(self) |
<< | __lshift__(self, other) |
>> | __rshift__(self, other) |
Here’s an example of how to accomplish these bitwise operators on a custom class Data
. We marked this respective operator in the code:
class Data: def __init__(self, data): self.data = data def __and__(self, other): return Data(self.data & other.data) def __or__(self, other): return Data(self.data | other.data) def __xor__(self, other): return Data(self.data ^ other.data) def __invert__(self): return Data(~self.data) def __lshift__(self, other): return Data(self.data << other.data) def __rshift__(self, other): return Data(self.data >> other.data) x = 2 y = 3 print('Operands: \n', 'x =', x, '\n', 'y =', y) print() print('Bitwise AND: ', x & y) print('Bitwise OR: ', x | y) print('Bitwise XOR: ', x ^ y) print('Bitwise NOT: ', ~x) print('Bitwise LEFT-SHIFT: ', x << y) print('Bitwise RIGHT-SHIFT: ', x >> y)
The output is:
Operands: x = 2 y = 3 Bitwise AND: 2 Bitwise OR: 3 Bitwise XOR: 1 Bitwise NOT: -3 Bitwise LEFT-SHIFT: 16 Bitwise RIGHT-SHIFT: 0