Mastering Bitwise Operators in Python: A Visual Guide with Step-by-Step Code Examples.
Have you ever seen symbols like &, |, ^, or ~ in Python and wondered what they actually do? You’re not alone! These are bitwise operators, and they might seem confusing at first, but once you break them down, they’re easier to understand than you think.
Bitwise operators work with binary numbers, which are just 1s and 0s. Every number in Python can be represented as a series of these 1s and 0s in the computer’s memory. When we use bitwise operators, we’re doing operations directly on those 1s and 0s.
In this blog post, I’ll explain what each bitwise operator does in simple terms, and we’ll go through clear Python examples to help you understand them.
By the end, you’ll see how and when to use bitwise operators in your own code. Let’s start by looking at the first one: the AND (&) operator.
&) OperatorImagine you have two numbers, like 12 and 5. When we talk about bitwise operators, we’re working with binary numbers. Binary is just another way to write numbers, using only 1s and 0s. It’s how computers represent everything!
So, to understand how the AND operator (&) works, we need to convert the numbers into binary.
Here’s the breakdown:
Now, we apply the AND operator. The AND operator checks each bit, one by one. It only keeps a 1 if both bits are 1. If either bit is 0, it will return 0.
Let’s look at it in detail:
1100 (This is 12 in binary)
& 0101 (This is 5 in binary)
-------
0100 (This is 4 in binary, which is our result)
1 for both 12 and 5.So, when you compare the two binary numbers bit by bit, the final result is 0100, which equals 4 in decimal.
Let’s take the same example and run it in Python:
a = 12 # 1100 in binary
b = 5 # 0101 in binary
# Using the AND operator
result = a & b
print(result) # This prints 4
When you run this code, it will output 4, just like we calculated.
&) operator compares each bit in two numbers.|) Operator: How It WorksThink of the OR operator as saying, “I’ll keep the bit as 1 if either of the bits is 1.” So, unlike the AND operator, the OR operator is more lenient. If one of the bits is a 1, it keeps it as 1.
Let’s break it down with an example:
Imagine we have 12 and 5 again. In binary:
Now, let’s use the OR operator (|) to compare these two numbers:
1100 (12 in binary)
| 0101 (5 in binary)
-------
1101 (13 in binary)
1 for 12 and 0 for 5, Since at least one of them is 1, the result is 1.1 for both 12 and 5. So the result is 1.0 for both numbers. Since both bits are 0, the result is 0.0 for 12 and 1 for 5. Since at least one of them is 1, the result is 1.So, the final result is 1101, which is 13 in decimal.
Here’s how you can do this in Python:
a = 12 # 1100 in binary
b = 5 # 0101 in binary
# Using the OR operator
result = a | b
print(result) # This prints 13
When you run the code, the output will be 13.
|) operator compares two bits.^) Operator: What It DoesThe XOR (exclusive OR) operator is a bit different from both AND and OR. It works like this:
“I’ll keep the bit as 1 if one of the bits is 1, but not both.”
In other words, if both bits are the same (both 0 or both 1), the result is 0. But if the bits are different (one is 0 and the other is 1), the result is 1.
Let’s break it down using 12 and 5 again:
Now, let’s apply the XOR operator (^):
1100 (12 in binary)
^ 0101 (5 in binary)
-------
1001 (9 in binary)
1 for 12 and 0 for 5. Since they are different, the result is 1.1 for both numbers. Since they are the same, the result is 0.0 for both numbers. Since they are the same, the result is 0.0 for 12 and 1 for 5. Since they are different, the result is 1.So, the final result is 1001, which is 9 in decimal.
Here’s how you can do this in Python:
a = 12 # 1100 in binary
b = 5 # 0101 in binary
# Using the XOR operator
result = a ^ b
print(result) # This prints 9
When you run the code, the output will be 9.
^) operator compares two bits.~) Operator: What It DoesThe NOT operator is a little different from the others we’ve covered. While the AND, OR, and XOR operators work between two numbers, the NOT operator only works on one number.
It’s also called the bitwise NOT operator, and its job is to flip every bit. If a bit is 1, it becomes 0. If it’s 0, it becomes 1.
In simple terms, the NOT operator inverts the bits of the number.
But there’s a catch—Python uses something called two’s complement representation to handle negative numbers. This means the result of the NOT operator isn’t as simple as just flipping the bits, but I’ll explain that.
Let’s break it down with an example.
Let’s take the number 12 and apply the NOT operator on it.
00000000 00000000 00000000 00001100~12):11111111 11111111 11111111 11110011Now, when we convert this result back into decimal, we get -13.
Python uses two’s complement to represent negative numbers. Flipping the bits of a positive number doesn’t just give you the negative version directly. Instead, the result is the negative of the number minus 1.
Let’s see this in Python:
a = 12
# Using the NOT operator
result = ~a
print(result) # This prints -13
When you run this code, the output will be -13.
Here’s a quick breakdown of the steps:
00000000 00000000 00000000 0000110011111111 11111111 11111111 11110011~) operator flips every bit in a number.<< (Left Shift) and >> (Right Shift)The shift operators allow you to move the bits of a number to the left or right. When you shift the bits, you’re essentially multiplying or dividing the number by powers of 2.
There are two types of shift operators:
<<)>>)Let’s go over both one by one.
<<) OperatorThe left shift (<<) operator shifts all the bits in a number to the left. Each shift to the left multiplies the number by 2.
For example, let’s say we have the number 3. In binary, 3 is represented as 0011.
Let’s shift 3 to the left by one position:
00113 << 1), the bits move to the left and a 0 is added on the right: 0110In decimal, 0110 is 6, so 3 << 1 gives us 6.
a = 3
result = a << 1
print(result) # This prints 6
Now, let’s break down the shift:
3 << 1 is 3 * 2 = 6.If you shift to the left again:
>>) OperatorThe right shift (>>) operator does the opposite. It shifts the bits to the right, which divides the number by 2 for each shift.
Let’s take 12 as an example. In binary, 12 is 1100.
Let’s shift 12 to the right by one position:
110012 >> 1), the bits move to the right and a 0 is added on the left: 0110In decimal, 0110 is 6, so 12 >> 1 gives us 6.
a = 12
result = a >> 1
print(result) # This prints 6
Again, here’s what happened:
12 >> 1 is 12 / 2 = 6.If you shift to the right again:
<<): Shifting left by one position multiplies the number by 2.>>): Shifting right by one position divides the number by 2.The shift operators are useful when you want to scale numbers by powers of 2 efficiently.
This is when you work directly with the bits of data. Bits are the smallest unit of data (just a 0 or 1), and sometimes you need to get super specific and manipulate the data at this level.
Let’s say you’re working with a sensor in an embedded system. The sensor might send data in a binary format. For example, the sensor could send a status code where each bit represents a different status:
You want to quickly check these individual statuses by manipulating the bits.
Bitwise Operators make this easy:
&) to check a specific bit in the status code.|) to set a specific bit to 1 (e.g., turn on a warning).^) to toggle a bit (flip it from 0 to 1 or 1 to 0).Let’s assume the sensor status is represented as status_code = 0b010 (which is 2 in decimal).
To check if the second bit (humidity status) is on:
status_code = 0b010
humidity_status = status_code & 0b010 # This will return 0b010, meaning True (humidity is high)
if humidity_status:
print("Humidity is high")
A binary flag is just a fancy name for a bit used to represent a setting or configuration. Imagine you’re building an app or a piece of software where several features can be enabled or disabled.
You might store the status of multiple features in a single number. Each feature gets its own bit, and if the bit is 1, the feature is enabled; if it’s 0, it’s disabled.
Let’s say we have these three settings:
You can store these features in a single integer (let’s say settings = 0b011), where:
settings = 0b011 # Notifications and Dark Mode are enabled
# Turn off Dark Mode (bit 1)
settings &= ~0b010 # Now settings becomes 0b001 (only Notifications are on)
# Check if Notifications are enabled (bit 0)
if settings & 0b001:
print("Notifications are enabled")
This way, you store and check many settings using just a few bits instead of multiple variables.
Sometimes, you’re building applications that need to run super fast — for example, in games, networking (where speed is important), or real-time systems. Bitwise operations can make your code run faster than other methods like if statements or loops.
Why? Because bitwise operators are very efficient for computers to process. They are literally just manipulating bits, and that’s much faster than checking conditions or doing math.
If you need to check multiple flags or states in real-time (like in a game), using bitwise operators is way faster than having multiple if statements.
Imagine you’re building a simple game where a character can be in different states (running, jumping, or idle). Instead of using a bunch of if conditions, you can store these states as bits and quickly check them with bitwise operators.
# States stored as bits
states = 0b011 # Running (bit 1), Jumping (bit 0)
# Check if character is running
if states & 0b010:
print("Character is running")
# Check if character is jumping
if states & 0b001:
print("Character is jumping")
Each check is super fast, and you don’t need to go through a bunch of if statements to figure out what the character is doing.
Bitwise operators are also used in encryption (scrambling data) and compression (reducing the size of data). These operations often work directly with the bits of the data, making them a perfect match.
In encryption algorithms like XOR, data is scrambled by flipping bits. Here’s a simple example of how XOR can be used for encryption:
42), and apply the XOR operator with a key (say, 56).# Encryption example using XOR
original_data = 42
key = 56
# Encrypt data
encrypted_data = original_data ^ key
print(f"Encrypted Data: {encrypted_data}")
# Decrypt data
decrypted_data = encrypted_data ^ key
print(f"Decrypted Data: {decrypted_data}")
This is just a basic concept, but in real encryption, bitwise operations are used to secure data by mixing it up in a complex way.
bin() to See the Binary VersionSometimes it’s hard to understand what a number looks like in binary. Python has a built-in way to help: bin().
Example:
a = 5
print(bin(a)) # Output: '0b101'
The '0b' means “this is a binary number.”
So 5 in binary is 101.
Let’s try another:
b = 3
print(bin(b)) # Output: '0b11'
That’s 3 in binary — 11.
Now if you do a & b:
print(a & b) # Output: 1
print(bin(a & b)) # Output: '0b1'
You can see exactly why the answer is 1.
Binary math:
101 (which is 5)
& 011 (which is 3)
= 001 (which is 1)
Using bin() helps you understand what’s going on.
In Python, when you write something like this:
result = a & b | c
Python might do b | c first, depending on the order of operations.
To avoid confusion, add parentheses:
result = (a & b) | c
Now you’re telling Python:
“First do
a & b, then OR the result withc.”
Simple rule: when using multiple operators together, just use brackets to make it clear what you want.
Let’s say you’re working with flags — like on/off switches inside one number.
Imagine this:
flags = 0b1010 # binary: 1010 (which is 10 in decimal)
Now:
mask = 0b0010 # Only bit 1 is ON
if flags & mask:
print("Bit 1 is ON")
You’re using & to test a specific bit.
flags = flags | 0b0001
Now bit 0 is ON. That’s how you set a bit.
flags = flags & ~0b1000
The ~ flips the bits — so this removes bit 3.
bin() to see the bits clearly.let’s build a small settings system using flags. I’ll walk you through it step by step, and you’ll see how bitwise operations help manage multiple settings using just one number.
Let’s say we have 4 settings (each one can be ON or OFF):
| Setting | Bit Position | Binary |
|---|---|---|
| Notifications ON | bit 0 | 0001 |
| Dark Mode ON | bit 1 | 0010 |
| Location Access ON | bit 2 | 0100 |
| Auto-Update ON | bit 3 | 1000 |
We’ll use a single integer to store all these settings together using bits.
settings = 0b0000 # all bits are OFF
print(bin(settings)) # '0b0'
NOTIFICATIONS = 0b0001
DARK_MODE = 0b0010
settings = settings | NOTIFICATIONS
settings = settings | DARK_MODE
print(bin(settings)) # Output: '0b11'
Now bit 0 and bit 1 are ON → binary is 0011.
LOCATION = 0b0100
if settings & LOCATION:
print("Location access is ON")
else:
print("Location access is OFF")
Since we never turned it ON, the result will be:
Location access is OFF
settings = settings & ~DARK_MODE
print(bin(settings)) # Output: '0b1'
Now only Notifications are ON.
AUTO_UPDATE = 0b1000
settings = settings | AUTO_UPDATE
print(bin(settings)) # Output: '0b1001'
So now, Notifications and Auto-Update are ON.
You just built a mini feature switch system using:
| to turn settings ON& with ~ to turn them OFF& to check if a setting is ONbin() to see what’s happeningThis is how things like game settings, permissions, and device flags are handled in real projects.
| Operator | Name | Python Symbol | Example | Result |
|---|---|---|---|---|
| AND | Bitwise AND | & | 10 & 4 | 0 |
| OR | Bitwise OR | ` | ` | `10 |
| XOR | Bitwise XOR | ^ | 10 ^ 4 | 14 |
| NOT | Bitwise NOT | ~ | ~10 | -11 |
| Left | Left Shift | << | 10 << 2 | 40 |
| Right | Right Shift | >> | 10 >> 2 | 2 |
Bitwise operators might look tricky at first — all those &, |, ^, and ~ symbols can feel like secret codes. But once you understand what they actually do (just flipping or checking bits), it all starts to make sense.
In this post, we looked at:
bin() to see what’s happeningThese tools are especially useful when you’re working with low-level data, settings flags, or anything that needs fast, compact control.
Don’t worry if it doesn’t all click immediately — bitwise operations are something you get better at with a little practice. Try using them in small projects or write a few more examples on your own.
And if you ever get stuck, just use bin() to peek under the hood. The bits won’t lie.
5 & 3 in Python?Correct Answer: B. 1
Explanation:
In binary:5 = 1013 = 011101 & 011 = 001 → which is 1
flags = flags & 0b0100flags = flags | 0b0100flags = flags ^ 0b0100flags = ~flagsCorrect Answer: B. flags = flags | 0b0100
Explanation:
The | (OR) operator turns ON bits. 0b0100 is bit 2.
~ (bitwise NOT) do in Python?Correct Answer: B
Explanation:
The ~ operator flips every bit. In Python, it also includes a two’s complement, so ~5 gives -6.
flags = 0b1101, how do you check if bit 2 is ON?flags & 0b0100flags | 0b0100flags ^ 0b0100~flags & 0b0100Correct Answer: A. flags & 0b0100
Explanation:
Use & to check a specific bit. If the result is not 0, the bit is ON.
Correct Answer: D. 14
Explanation:a = 1010, b = 01001010 ^ 0100 = 1110 → which is 14
Python Official Documentation – Bitwise Operations
A straight-to-the-point section from Python’s official docs. Useful for quick reference on how each operator works.
Bitwise Tricks in Competitive Programming – HackerEarth Blog
Shows how bitwise operators are used in optimization, flag handling, and challenges. A good read if you’re interested in how bitwise logic is used in real-world logic puzzles and programming contests.
Great question! Bitwise operators are handy when you want to store multiple ON/OFF states in just one number. It’s super efficient, especially for things like settings, permissions, or performance-critical tasks. Instead of having four separate True/False variables, you can handle them all with one integer using bits.
Use Python’s built-in bin() function! It converts a number to its binary string, so you can actually see the 0s and 1s. For example:
print(bin(5)) # Output: ‘0b101’
It’s a great way to debug and understand what your bitwise code is doing.
Yes, but be careful. Python represents negative numbers using two’s complement, so the bits might look confusing at first. For example, ~5 gives -6. If you’re doing bit-level work, it’s usually best to stick with non-negative integers unless you’re sure how negatives are handled in binary.
After debugging production systems that process millions of records daily and optimizing research pipelines that…
The landscape of Business Intelligence (BI) is undergoing a fundamental transformation, moving beyond its historical…
The convergence of artificial intelligence and robotics marks a turning point in human history. Machines…
The journey from simple perceptrons to systems that generate images and write code took 70…
In 1973, the British government asked physicist James Lighthill to review progress in artificial intelligence…
Expert systems came before neural networks. They worked by storing knowledge from human experts as…
This website uses cookies.