Python Bitwise OR: How to Use It in Your Code
Learn how Python's bitwise OR operator combines integer bits, how to use it for flag combinations, and what pitfalls to avoid.
The | operator performs a bitwise OR on integers. It compares corresponding bit positions of two numbers and returns a new integer where each bit is set if either operand has that bit set. This is a fundamental tool for low-level data manipulation, and it also appears in higher-level code when you need to combine flags or build masks.
How Bitwise OR Works on Integers
In Python, integers have arbitrary precision, so bitwise operations work on the binary representation of the number. For each bit position, the result bit is 1 if at least one of the operands has a 1 at that position; otherwise it is 0.
a = 0b1100 # 12 b = 0b1010 # 10 result = a | b # 0b1110 = 14
The binary columns are 8, 4, 2, and 1. a has bits 8 and 4, b has bits 8 and 2, so the result has bits 8, 4, and 2, which is 14. This operation is often used to set specific bits without affecting others. For example, if you have a value and want to force a particular bit to 1, you OR it with a mask that has that bit set.
Using Bitwise OR for Flag Combinations
A common pattern is to define a set of boolean options as powers of two and combine them using bitwise OR. This allows multiple options to be stored in a single integer and passed around efficiently.
READ = 1 WRITE = 2 EXECUTE = 4 permissions = READ | WRITE # 3
Each flag occupies a distinct bit, so the combination is unique. To test whether a flag is present, you use the bitwise AND operator, which is the natural counterpart.
if permissions & READ: print("Read allowed")
This pattern is widely used in standard library modules like re (regular expression flags) and os (open mode flags), and it is also common in third-party libraries.
Bitwise OR vs Logical OR
The logical or operator returns a boolean or one of the operands, depending on truthiness. The bitwise | returns a combined value: an integer for integer operands, or the result of another type's __or__ method. Mixing them up is a frequent source of bugs.
a = 1 b = 2 print(a or b) # 1 (truthy value) print(a | b) # 3 (bitwise combination)
The logical or short-circuits and returns the first truthy operand, while bitwise OR evaluates both operands and combines their bits. Use logical or for control flow, and bitwise | for bit-level manipulation.
In-Place OR: The |= Operator
Python provides the augmented assignment operator |= which performs a bitwise OR and assigns the result back to the variable. This is convenient when you want to accumulate flags or set bits iteratively.
permissions = 0 permissions |= READ permissions |= WRITE
This is equivalent to permissions = permissions | READ. It can make the intent clearer when building a value step by step, especially in loops or conditional logic.
Performance and Readability Considerations
Bitwise operations are extremely fast because they operate directly on the binary representation. However, in Python, the overhead of function calls and object creation often dominates for small integers, so micro-optimizing with bitwise OR instead of a list of booleans rarely yields meaningful gains. The real benefit is readability and compactness when you need to represent a fixed set of flags.
When deciding between a bitmask and a set of booleans, consider the tradeoffs. A bitmask is more compact and can be passed to C extensions or used in network protocols. A set of booleans is easier to debug and less error-prone for large numbers of options. For more than a few dozen flags, a set or a dictionary may be clearer.
Common Pitfalls and Edge Cases
Bitwise OR on negative numbers uses two's complement representation in Python, which can produce surprising results if you are not careful. For example:
-1 | 0 # -1
Because -1 is all bits set in two's complement, ORing with anything yields -1. This is often unintended when you expect a non-negative result.
Another edge case is operator precedence. Bitwise OR binds more tightly than comparison operators and logical and, but less tightly than shifts. This can be unintuitive, so use parentheses when mixing bitwise operations with arithmetic or comparisons.
# Without parentheses, this is parsed as (a | b) == c if a | b == c: pass
Finally, remember that bitwise OR works on integers, but Python also allows it for other types that define __or__, such as set objects. For sets, | performs a union, which is a different concept.