Python Bitwise Operators: AND, OR, XOR, NOT, & Shifts

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.

Master Reference Table: The 6 Bitwise Operators 🔝

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

Binary Foundations: bin(), int(), and Formatting 🔝

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

Bitwise AND (&) — Masking and Filtering 🔝

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 ABit BA & B
000
010
100
111
Bitwise AND operator diagram
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

Bitwise OR (|) — Combining and Setting Flags 🔝

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 ABit BA | B
000
011
101
111
Bitwise OR operator diagram
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)

Bitwise XOR (^) — Toggling and Parity 🔝

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 ABit BA ^ B
000
011
101
110
Bitwise XOR operator diagram
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

Bitwise NOT (~) — Inversion and Two's Complement 🔝

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:

Core Mathematical Formula: ~x = -(x + 1)
  • ~15 == -16
  • ~4 == -5
  • ~0 == -1
  • ~(-22) == 21
Bitwise complement operator diagram
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)

Bitwise Shifts (<< and >>) — Arithmetic Scaling 🔝

Shift operators move bits left or right, offering fast multiplication and division by powers of 2:

Left Shift Operator (<<)

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)
Bitwise left shift operator diagram

Right Shift Operator (>>)

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)
Bitwise right shift operator diagram

Practical Bitwise Recipes & Performance Hacks 🔝

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)

Hands-on Exercise: Unix Permission Bitmask Engine 🔝

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:

Python Exercise: Permission Bitmask Engine with Self-Checking 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!")

Practice in Google Colab & GitHub 🔝

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.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer