How to Use Bitwise Operators in Python – Tips, Tricks, and Examples

Python’s bitwise operators work with integer bit patterns. They are useful for masks, compact flags, protocol fields and low-level data transformations, but are not automatically faster or safer than clear arithmetic or specialized libraries. Python integers have arbitrary precision, so negative values and the complement operator can surprise developers expecting a fixed-width unsigned machine type.

This guide explains the six core operations, then shows how to mask to a desired width and when bit manipulation is appropriate. The examples are about predictable integer behavior, not a recommendation to invent a cryptographic algorithm.

Binary representation and bit positions

The lowest bit has value 1, the next has value 2, then 4, 8 and so on. bin() displays a string representation of an integer. Use a fixed-width format when comparing fields from protocols or binary files.

value = 13
print(bin(value))       # 0b1101
print(f"{value:08b}")   # 00001101

AND: keep only shared set bits

The & operator produces 1 only where both operands have a 1 bit. This is useful for extracting a subset of flags from a value.

flags = 0b1101
mask = 0b0101
print(f"{flags & mask:04b}")  # 0101

OR and XOR

OR sets any position present in either input; XOR sets positions where the inputs differ. XOR can toggle bits, but using it as a homemade encryption scheme is unsafe.

x = 0b1001
y = 0b0110
print(bin(x | y))  # 0b1111
print(bin(x ^ y))  # 0b1111

NOT and negative integers

The bitwise complement ~x follows the identity ~x == -x – 1. Python does not automatically truncate the result to 8, 16 or 32 bits. Apply an explicit mask when fixed-width behavior is required.

x = 5
print(~x)         # -6
print((~x) & 0xFF) # 250 as an 8-bit mask

Left shift and right shift

x << n shifts left, multiplying by powers of two for nonnegative integers when no external width constraint applies. x >> n is an arithmetic right shift, including sign behavior for negative integers. Shift counts must be nonnegative.

print(3 << 2)    # 12
print(12 >> 2)   # 3
print(-5 >> 1)   # -3

Store several boolean flags

Named bit constants make permissions or feature indicators readable. Use proper authorization checks instead of treating a local bitmask as an access-control security boundary.

READ = 1 << 0
WRITE = 1 << 1
EXECUTE = 1 << 2
user_flags = READ | WRITE
print(bool(user_flags & WRITE))

Operator precedence and parentheses

Complex expressions can be difficult to read because bitwise and comparison operators have their own precedence levels. Parenthesize the intended calculation and test edge values, especially when a mask participates in a boolean condition.

flags = 0b1010
mask = 0b0010
if (flags & mask) == mask:
    print("bit is set")

Applications, performance and limitations

Common uses include network protocol fields, hardware registers, image channels and combinatorial state representation. Evaluate a tested library for complex binary formats, and avoid unmeasured claims that bitwise code always runs faster. Explicit width and signedness rules are essential when interoperating with C or network protocols.

value = 0b11010110
low_nibble = value & 0x0F
high_nibble = (value >> 4) & 0x0F
print(low_nibble, high_nibble)

Conclusion

Bitwise AND, OR, XOR, NOT and shifts become much easier when you visualize individual positions and state the desired integer width. Use descriptive masks, parentheses and tests; prefer documented cryptographic and serialization libraries rather than ad hoc bit tricks.

  • img