Python bitwise operators evaluate and manipulate integer values at the individual binary bit level (base-2). Python provides six bitwise operators: Bitwise AND (&), Bitwise OR (|), Bitwise XOR (^), Bitwise NOT / Inversion (~), Bitwise Left Shift (<<), and Bitwise Right Shift (>>).
Arbitrary Precision & Two's Complement: Python integers have unlimited precision. Negative integers are represented conceptually as an infinite sequence of leading 1 bits in two's complement arithmetic, guaranteeing the core relationship ~x == -x - 1.
Each operator evaluates integer operands bit-by-bit from lowest to highest significance:
| Operator | Name | Syntax | Truth / Operation Logic | Mathematical Analogy | Example (a=12, b=5) |
|---|---|---|---|---|---|
& |
Bitwise AND | a & b |
1 only if both bits are 1; else 0. |
Intersection of set bits | 12 & 5 ⇒ 4 (0b0100) |
| |
Bitwise OR | a | b |
1 if either or both bits are 1; else 0. |
Union of set bits | 12 | 5 ⇒ 13 (0b1101) |
^ |
Bitwise XOR | a ^ b |
1 if bits differ; 0 if identical. |
Symmetric difference | 12 ^ 5 ⇒ 9 (0b1001) |
~ |
Bitwise NOT | ~a |
Inverts all bits: 0 ⇔ 1. |
-(a + 1) (Two's complement) |
~12 ⇒ -13 |
<< |
Left Shift | a << n |
Shifts bits left by n places; vacated right filled with 0. |
a × 2n |
12 << 2 ⇒ 48 |
>> |
Right Shift | a >> n |
Shifts bits right by n places; dropped bits discarded. |
a // 2n (Floor division) |
12 >> 2 ⇒ 3 |
To inspect bitwise results, convert between decimal and binary representations using bin(), int(), and formatted string literals:
# 1. Decimal to binary representation with prefix '0b'
val = 120
print(bin(val)) # '0b1111000'
print(bin(val)[2:]) # '1111000' (slice off prefix)
# 2. Binary string back to integer (base 2)
num = int('1111000', 2)
print(num) # 120
# 3. Formatted zero-padded byte representation (8-bit)
print(f"{val:08b}") # '01111000'
# 4. Binary literal notation
flag = 0b00001100 # 12 in decimal
print(flag) # 12
Output:
0b1111000
1111000
120
01111000
12
The bitwise AND operator (&) returns 1 only if both corresponding operand bits are 1. It is widely used for bitmasking to extract or clear specific bits.
| Bit A | Bit B | A & B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
a, b = 12, 15 # 12: 00001100, 15: 00001111
res = a & b
print(f"12 & 15 = {res} (binary: {res:08b})")
# Check if a number is even or odd: test least significant bit
def is_even(n):
return (n & 1) == 0
print("42 is even:", is_even(42))
print("17 is even:", is_even(17))
Output:
12 & 15 = 12 (binary: 00001100)
42 is even: True
17 is even: False
The bitwise OR operator (|) returns 1 if at least one corresponding bit is 1. It is the standard tool for setting flags and combining multiple configuration states.
| Bit A | Bit B | A | B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
a, b = 34, 12 # 34: 00100010, 12: 00001100
res = a | b
print(f"34 | 12 = {res} (binary: {res:08b})")
# Combining configuration flags
READ = 0b001 # 1
WRITE = 0b010 # 2
perms = READ | WRITE
print(f"Combined flags: {perms} (binary: {perms:03b})")
Output:
34 | 12 = 46 (binary: 00101110)
Combined flags: 3 (binary: 011)
The bitwise XOR operator (^) returns 1 when the two operand bits are different, and 0 when they are identical. XOR satisfies x ^ x == 0 and x ^ 0 == x.
| Bit A | Bit B | A ^ B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
a, b = 12, 15 # 12: 00001100, 15: 00001111
res = a ^ b
print(f"12 ^ 15 = {res} (binary: {res:08b})")
# Swapping variables without temporary storage
x, y = 105, 230
x ^= y; y ^= x; x ^= y
print(f"Swapped: x={x}, y={y}")
# Find unique non-duplicate number among pairs
nums = [4, 1, 2, 1, 2]
unique = 0
for n in nums:
unique ^= n
print("Unique element:", unique)
Output:
12 ^ 15 = 3 (binary: 00000011)
Swapped: x=230, y=105
Unique element: 4
The bitwise NOT operator (~) is a unary operator that inverts every bit. In Python's arbitrary-precision two's complement system, inverting integer x follows the rule:
~x = -(x + 1)
~15 == -16~4 == -5~0 == -1~(-22) == 21
print("~15 =", ~15)
print("~4 =", ~4)
print("~-22 =", ~-22)
print("~0 =", ~0)
# Emulate fixed 8-bit unsigned NOT using bitmask & 0xFF
val = 0b00001111 # 15
inv_8bit = ~val & 0xFF
print(f"8-bit unsigned NOT: {inv_8bit} (binary: {inv_8bit:08b})")
Output:
~15 = -16
~4 = -5
~-22 = 21
~0 = -1
8-bit unsigned NOT: 240 (binary: 11110000)
Shift operators move bits left or right, offering fast multiplication and division by powers of 2:
<<)Shifts bits left by n places; vacated right bits filled with 0. Multiplies by 2n:
x << n == x × 2n
print(14 << 1) # 28 (14 * 2)
print(14 << 2) # 56 (14 * 4)
print(5 << 4) # 80 (5 * 16)
>>)Shifts bits right by n places; dropped bits discarded. Floor divides by 2n:
x >> n == x // 2n
print(14 >> 1) # 7 (14 // 2)
print(14 >> 2) # 3 (14 // 4)
print(90 >> 3) # 11 (90 // 8)
Below are essential bit manipulation patterns used in algorithms, systems programming, and graphics:
# 1. Check if integer is a power of 2
def is_power_of_two(n):
return n > 0 and (n & (n - 1)) == 0
print("64 is power of 2:", is_power_of_two(64)) # True
print("50 is power of 2:", is_power_of_two(50)) # False
# 2. Set, clear, and toggle bit k (0-indexed)
num = 0b00001000 # 8
k = 2
set_k = num | (1 << k) # Set bit 2 -> 12 (00001100)
clear_3 = set_k & ~(1 << 3) # Clear bit 3 -> 4 (00000100)
toggle_2 = clear_3 ^ (1 << 2) # Toggle bit 2 -> 0 (00000000)
print(f"Set: {set_k}, Clear: {clear_3}, Toggle: {toggle_2}")
# 3. 24-bit RGB Color Packing & Extraction
def pack_rgb(r, g, b):
return (r << 16) | (g << 8) | b
def unpack_rgb(hex_val):
return (hex_val >> 16) & 0xFF, (hex_val >> 8) & 0xFF, hex_val & 0xFF
color = pack_rgb(255, 128, 64)
print(f"Packed hex: 0x{color:06X}")
print("Unpacked:", unpack_rgb(color))
Output:
64 is power of 2: True
50 is power of 2: False
Set: 12, Clear: 4, Toggle: 0
Packed hex: 0xFF8040
Unpacked: (255, 128, 64)
Unix filesystem permissions (e.g. chmod 755 or rwxr-xr-x) use bitwise operations to manage Read (4 / 0b100), Write (2 / 0b010), and Execute (1 / 0b001) flags. The production engine below implements grant, revoke, check, toggle, and formatting with unit assertions:
class PermissionManager:
READ = 0b100 # 4
WRITE = 0b010 # 2
EXECUTE = 0b001 # 1
def __init__(self, initial=0):
self.perms = initial
def grant(self, flag):
# Sets permission flag using Bitwise OR (|)
self.perms |= flag
def revoke(self, flag):
# Clears permission flag using Bitwise AND with inverted mask (& ~)
self.perms &= ~flag
def has_permission(self, flag):
# Tests permission using Bitwise AND (&)
return (self.perms & flag) == flag
def toggle(self, flag):
# Toggles permission using Bitwise XOR (^)
self.perms ^= flag
def to_rwx(self):
# Formats permission as rwx string
r = 'r' if self.has_permission(self.READ) else '-'
w = 'w' if self.has_permission(self.WRITE) else '-'
x = 'x' if self.has_permission(self.EXECUTE) else '-'
return f"{r}{w}{x}"
# Unit Assertions and Verification
pm = PermissionManager()
assert pm.perms == 0
assert pm.to_rwx() == "---"
pm.grant(PermissionManager.READ | PermissionManager.WRITE)
assert pm.perms == 6 # 0b110
assert pm.has_permission(PermissionManager.READ) is True
assert pm.has_permission(PermissionManager.WRITE) is True
assert pm.has_permission(PermissionManager.EXECUTE) is False
assert pm.to_rwx() == "rw-"
pm.grant(PermissionManager.EXECUTE)
assert pm.perms == 7 # 0b111
assert pm.to_rwx() == "rwx"
pm.revoke(PermissionManager.WRITE)
assert pm.perms == 5 # 0b101
assert pm.has_permission(PermissionManager.WRITE) is False
assert pm.to_rwx() == "r-x"
pm.toggle(PermissionManager.READ)
assert pm.to_rwx() == "--x"
pm.toggle(PermissionManager.READ)
assert pm.to_rwx() == "r-x"
print("Final permissions:", pm.to_rwx(), f"(value: {pm.perms})")
print("All bitwise permission unit assertions passed successfully!")
Open in Google Colab View on GitHub
Run all bitwise operator examples interactively, test truth tables, evaluate two's complement equations, explore color packing, and execute permission bitmask operations in Google Colab.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.