Bitwise operators treat integers as sequences of binary bits rather than as whole numeric values: & (AND) and | (OR) combine bits position by position, ^ (XOR) sets a bit only when its operands differ, ~ flips every bit, and << / >> shift bits left or right, which for positive integers is equivalent to multiplying or dividing by a power of two. They're most common in low-level code — flags, masks, binary protocols — rather than everyday application logic.
1Understanding Bitwise Operators
Bitwise operators treat integers as sequences of binary bits rather than as whole numeric values: & (AND) and | (OR) combine bits position by position, ^ (XOR) sets a bit only when its operands differ, ~ flips every bit, and << / >> shift bits left or right, which for positive integers is equivalent to multiplying or dividing by a power of two. They're most common in low-level code — flags, masks, binary protocols — rather than everyday application logic.
Left-shifting a positive integer is a fast, idiomatic way to multiply it by a power of two, and it's often used to define bit-flag constants readably, so each flag occupies its own distinct bit.
print(5 & 3)
print(5 | 2)
print(5 ^ 1)
print(~5)2Practical Example
Here is a real-world application of Bitwise Operators showing how it is used in production Python code.
READ = 1 << 0
WRITE = 1 << 1
EXECUTE = 1 << 2
permissions = READ | WRITE
print(permissions)
print(bool(permissions & WRITE))3Best Practices
Follow these guidelines when working with Bitwise Operators:
1. Use bitwise operators for flags, masks, and binary protocol parsing, not as a substitute for the logical and/or operators, which work on truthiness rather than bits
2. Prefer named constants defined with shifts over magic numbers when defining a set of flag values
3. Reach for a number's built-in bit-length method or the bin() function instead of manual bit-shifting loops when you just need to inspect its binary representation
Tip: Left-shifting a positive integer is a fast, idiomatic way to multiply it by a power of two, and it's often used to define bit-flag constants readably, so each flag occupies its own distinct bit.
print(5 & 3)
print(5 | 2)
print(5 ^ 1)
print(~5)