Python Diaries 📚: The Hidden Powers Begin

Neha PatelNeha Patel
17 min read

Hey you👋 Yes, you🫵

💡
You’ve probably seen a bunch of Python tutorials, right?

Ever felt like Python tutorials are either too boring or too basic?

You follow along, write a few lines of code, but deep down you’re still wondering…

“Wait. Why does this actually work?”
“What’s going on behind the scenes 🧐?”

Well, welcome to the series that answers all of that and more.

We’re not here to just write Python…
We’re here to actually understand it. Deeply, Clearly and One “aha!” moment at a time.

This isn’t your usual tutorial playlist.

This is a story-driven, real-talk Python web series packed with concepts, mind-bending insights, fun vibes and the kind of smooth explanations that make your brain go:

“Wait… ohhh, now I get it!🥳”

We're not rushing. We're not skipping.
We’re decoding Python from the inside out like peeling back the curtain and finally seeing what’s going on backstage.

So whether you’re just starting out or you’ve written Python for a while and still feel like something’s missing you're in the right place.

We’ve got:

  • 🔍 Deep dives

  • 🎯 Real-world clarity

  • 🧠 Tricky edge cases

And we’re starting this journey with Episode 1: Operators Unleashed
Because trust me once you get how operators work under the hood, the rest of Python starts making a whole lot more sense.

Episode 1 – Operators Unleashed🔓

Hey Python Fam🖖,

Welcome to the very first episode of this Python-packed series –
Where each part feels less like a tutorial… and more like your favorite Netflix binge 👀🍿

If you're here, I already know one thing about you. You're someone who’s not just writing Python code…
You actually wanna understand what’s happening behind the scenes, right?

Alright, get ready because... Today we’re cracking open a topic that most Python learners either skip… or totally misunderstand. but it’s actually the core of how Python thinks, behaves, and makes decisions.
And trust me once you get this, your whole Python perspective is gonna level up.

We’re talking about the hidden superpowers of:

  • Arithmetic

  • 🤝 Comparison

  • 🧠 Logical

  • 📝 Assignment

  • ⚙️ Bitwise

  • 🔍 Membership

  • 🪞 Identity

All those tiny symbols like ==, is, &, or not in that seem innocent… but can change everything when used right!

💡
What do you think these lines are really doing?
print(2 + 3)        # 5  
print("2" + "3")    # "23"  
print([2] + [3])    # [2, 3]

Same operator, different results. Why?
Is ‘+’ secretly changing its job depending on the data?

This is called operator overloading. where the same symbol pulls off completely different stunts depending on who it’s hanging out with.

One minute it's doing math, next minute it's gluing strings together, and the next it's stitching lists like a Python tailor. Pretty unexpected, right?

But don’t worry! we’ll break them down with real examples, tricky edge cases, and even memory-level clarity
so by the end of this episode, you won’t just use operators……
You’ll understand their vibe.

So, grab your chai, coffee, or energy drink and let’s dive into the world of operators.

Let’s Talk About Operators:

💡
“Operators…. they’re just symbols, right?” you thought.

But no my dear friend! you were about to realize they were much more than that.

Operators are like action heroes in your code. They're like action verbs for your variables. They tell python what to do with your variables.

Operators perform actions on your data. From adding numbers to comparing values, from checking conditions to manipulating strings.

There are many types of operators, but don’t stress. Let’s take them one by one with real-life example.

1. Arithmetic Operators:

These are your basic math buddies. We’ve all used these before, right? From the time you were figuring out how much pizza to order for a party to calculating your grades.

In python we have basic arithmetic operators like:

Operator(Symbol)MeaningExampleOutput
+Addition5 + 510
-Subtraction5 - 23
*Multiplication5 * 315
/Division10 / 25.0
//Floor Division10 // 33
%Modulus10 % 31
**Power2 ** 38

Example:

a = 10
b = 3
print(a + b) # 13
print(a // b) # 3
print(a % b) # 1

It’s like ordering food. If you order 10 pizzas and share with 3 friends, the // operator tells how many full pizzas each gets. The % operator says how many are left over.

2. Comparison Operators:

They check what's True and what's False. These are the judges of your code. They compare two values and return True or False. Perfect for when you want to know if one value is bigger than another or if two values are equal.

Example:

x = 20
y = 15

print("Is x equal to y?", x == y)      # False
print("Is x not equal to y?", x != y)  # True
print("Is x greater than y?", x > y)   # True
print("Is x less than y?", x < y)      # False

These are the decision-makers. They’ll help you figure out if things are equal, bigger, or smaller. Think of them like comparing the prices of two phones. Which one’s the better deal?

3. Logical Operators:

When you have multiple conditions and you want to check if both are true or either is true, you use logical operators.

OperatorMeaningExampleOutput
andBoth true(5 > 2 and 3 < 4)True
orAny one true(5 < 2 or 3 < 4)True
notOppositenot(5 > 2)False

Example:

x = 5
y = 10

print(x < 10 and y > 5)  # True, because both conditions are true
print(x < 5 or y > 5)    # True, because at least one condition is true
print(not (x < 10))      # False, because x < 10 is true, and not reverses it

this think like that,

"If I have money and the cafe is open then I’m going out for coffee."

“If you have enough time or the task is easy, you’ll finish it today.”

4. Assignment Operators:

These are like putting values into variables with a twist.

OperatorMeaningExampleOutput
\=Assign valuex = 55
+=Add and assignx = 5, x += 38
-=Subtract and assignx = 10, x -= 46
*=Multiply and assignx = 6, x *= 212
/=Divide and assignx = 9, x /= 33.0
//=Floor divide and assignx = 9, x //= 24
%=Modulus and assignx = 10, x %= 31
**=Power and assignx = 2, x **= 38

Example:

x = 5
x -= 3   # same as x = x - 3
print(x)  # 2

Assignment operators help make your code shorter and cleaner. Instead of writing x = x + 1, you can simply write x += 1. Small things, big difference!

5. Bitwise Operators:

These are a bit more advanced and work on the binary level (0s and 1s).They compare or modify numbers bit by bit, which means they perform operations on the individual 0s and 1s that make up the number in binary form.
Super useful for performance-based stuff.

Bitwise operators might seem tricky at first, but don’t worry flocks. we’ll go through each one step by step with simple examples and see how they work behind the scenes in binary.

  • Bitwise AND (&):

    Returns 1 only if both bits are 1, otherwise returns 0.

    Example:

      a = 5     # binary: 0101
      b = 3     # binary: 0011
    
      result = a & b
      print(result)  # Output: 1
    

    Binary Breakdown:

         0101   (5)
      &  0011   (3)
      =  0001    1
    

    Only the last bit is 1 in both numbers, so the result is 1.

  • Bitwise OR (|):

    Returns 1 if at least one bit is 1, otherwise returns 0.

    Example:

      a = 5     # binary: 0101
      b = 3     # binary: 0011
    
      result = a | b
      print(result)  # Output: 7
    

    Binary Breakdown:

         0101   (5)
      |  0011   (3)
      =  0111    7
    

    Any bit that is 1 in either number becomes 1 in the result.

Bitwise XOR (^):

  • Returns 1 if the bits are different, otherwise returns 0

    Example:

      a = 5     # binary: 0101
      b = 3     # binary: 0011
    
      result = a ^ b
      print(result)  # Output: 6
    

    Binary Breakdown:

         0101   (5)
      ^  0011   (3)
      =  0110    6
    

Only the bits that are different become 1.

  • Bitwise NOT (~):

Bitwise NOT flips every bit in the binary representation of a number. But because Python uses signed integers with two's complement, flipping bits also changes the sign of the number.

How ~a Works Internally

Let’s take a = 5 and evaluate ~5.

a = 5
print(~a)  # Output: -6

Looks confusing at first, right?

💡
Why would flipping the bits of a positive number give us a negative one?

Let’s first explore with formula,

~a = - (a + 1)

~5 = - (5 + 1) = -6

Simple, right? But let’s go deeper to understand why it works this way in binary.

Step 1: Convert 5 to Binary (8 bits):

We assume 8-bit representation for easy understanding:

5 → 00000101

Step 2: Apply Bitwise NOT (~) → Flip All Bits

We flip every 0 to 1 and every 1 to 0:

~00000101 → 11111010

So, after flipping, we get:

11111010
💡
Looks like a big number? Actually, it’s a negative number! Why?

In Python, integers are stored using two’s complement when dealing with negatives. That means:

If the leftmost bit is 1, the number is negative, and we need to decode it using two’s complement method.

So let's do that now.

Step 3: Decode 11111010 using Two’s Complement

1. Flip all bits (1’s complement):

11111010 → 00000101

2. Add 1:

00000101 + 1 = 00000110

3. Add minus sign:

Result = -6

So, the result of ~5 is -6.

Bitwise NOT (~) on Negative Numbers:

Let’s say:

a = -5
print(~a)  # Output: 4
💡
Wait, what? ~(-5) gives 4? Let’s see how!

Let’s first explore with formula,

~a = - (a + 1)

~(-5) = - (-5 + 1) = -(-4) = 4

Simple, right? But let’s go deeper to understand why it works this way in binary.

Step 1 : Represent -5 in Binary (8 bits)

To understand bitwise operations on negative numbers, we use two’s complement.

First, write positive 5 in binary:

5 → 00000101

Now:

To get -5, we use two’s complement:

  • Flip all bits (1’s complement):
00000101 → 11111010
  • Add 1:
11111010 + 1 = 11111011

So, -5 in binary (8-bit) = 11111011

Step 2 : Apply Bitwise NOT (~)

Now flip all bits of 11111011:

~11111011 → 00000100

That equals 4 in decimal.

~(-5) = 4
  • Bitwise Left Shift (<<):

    Let’s take a simple example first:

a = 5
print(a << 1)  # Output: 10
💡
Looks like it doubled the number — but why?

Let’s explore step-by-step.

The left shift operator a << b shifts the binary bits of a to the left by b positions, and empty spots get filled with zeros on the right

Example: 5 << 1

Step 1: Convert 5 to Binary (8-bit)

5 → 00000101

Step 2: Left Shift by 1

We shift every bit 1 place to the left, and add a 0 at the end

00000101 << 1 → 00001010

So 00001010 is the result after shifting.

Step 3: Convert Back to Decimal

00001010 → 10

Final Answer:

5 << 1 = 10
💡
It Like Multiplying by 2🤔?

here’s each left shift multiplies the number by 2

ExpressionResultMeaning
5 << 1105 * 2
5 << 2205 * 2 * 2
5 << 3405 * 2 * 2 * 2

So in general:

a << b is equal to a * (2^b)

  • Bitwise Right Shift (>>):

    Let’s take a basic example:

a = 10
print(a >> 1)  # Output: 5
💡
Looks like it divided the number by 2 ? but what's really happening?

Let’s walk through it.

The right shift operator a >> b shifts the bits of a to the right by b positions, and discards the rightmost bits, filling in with zeros from the left.

Example: 10 >> 1

Step 1: Convert 10 to Binary (8-bit)

1000001010

Step 2: Right Shift by 1

Shift all bits 1 position to the right, and add 0 from the left:

00001010 >> 100000101

We just lost the last bit (the rightmost 0), and a 0 came in from the left.

Step 3: Convert Back to Decimal

000001015

Final Answer:

10 >> 1 = 5
💡
Think of it Like Dividing by 2

Each right shift divides the number by 2 (ignoring the remainder):

ExpressionResultMeaning
10 >> 1510 // 2
10 >> 2520 // 4
10 >> 3530 // 8

So in general:

a >> b is equal to a // (2^b)

  • Membership Operators:

    Python provides two membership operators:

    | Operator | Description | | --- | --- | | in | Returns True if a value exists in the given object | | not in | Returns True if a value does not exist |

    These are used to check presence, especially in collections like list, tuple, set, dict, string, etc.

    Let’s Begin with a Simple Example

fruits = ['apple', 'banana', 'mango']

print('apple' in fruits)     # True
print('grape' not in fruits) # True
💡
"Seems easy, but there's a twist."

Let’s explore how it works internally, and how behavior differs based on data types.

These are iterable containers. Python checks each element one by one*.*

colors = ['red', 'green', 'blue']
print('green' in colors)  # True

Internally, Python runs a loop and checks each element with == to match the value.

Set is Faster

s = {'a', 'b', 'c'}
print('b' in s)  # True

Why faster?

Because set uses hashing. constant time lookup instead of looping. Prefer set when you need fast membership checks in large data!

Membership in Dictionaries

Now this part often confuses beginners.

person = {'Name': 'Neha', 'Gender': 'Female'}
print('Name' in person)   # True
print('Neha' in person)  # False

Why is 'Neha' not in the dictionary?

Because in only checks keys, not values.

If you want to check in values:

print('Neha' in person.values())  # True

Similarly, for keys:

print('Name' in person.keys())     # True

Tricky Cases: Nested Structures

Sometimes things get tricky with nested lists or dicts.

nested = [1, [2, 3], 4]
print(2 in nested)        # False
print([2, 3] in nested)   # True

Why?

Because 2 is inside a nested list, not directly in the outer list.

Final Recap: Membership Operator Behaviors

Data Typein checksFast?
list, tupleLinear search (==)Slow for big data
set, dictHash-based lookupFast
dictChecks keys by defaultFast
stringChecks substringModerate

Identity Operators

Python provides two identity operators:

OperatorDescription
isReturns True if two variables point to the same object in memory
is notReturns True if two variables point to different objects in memory

These are not the same as == and !=, which check for value equality.

Let’s Begin Simple

a = 5
b = 5
print(a is b)  # True, both point to the same object (small int interning)

You might think:

💡
“They look equal, so why use is?”

Because is checks if both variables are literally pointing to the same memory address, not just if their values are the same.

💡
Why is Sometimes Returns True, Sometimes False?

Here comes the twist.
It depends on mutability and Python’s internal optimizations.

Immutable Data Types

Immutable means can’t be changed after creation. These include:

  • int

  • float

  • str

  • bool

  • tuple (but with a condition — we’ll explain)

Example: Integers

a = 100
b = 100
print(a is b)  # True

But watch this:

a = 257
b = 257
print(a is b)  # False

Why this difference?

Because Python caches integers from -5 to 256. Any number in this range points to the same object in memory for efficiency.

Strings

a = "hello"
b = "hello"
print(a is b)  # True (due to interning)

But:

a = "hello world!"
b = "hello world!"
print(a is b)  # Might be False in some environments

Python automatically interns some strings (especially short ones or ones that look like identifiers). But it’s not guaranteed for all strings.

Mutable Data Types

Mutable means can be changed in-place. These include:

  • list

  • dict

  • set

Even if two variables hold the same data, they are different objects.

a = [1, 2, 3]
b = [1, 2, 3]
print(a is b)  # False
print(a == b)  # True

Why?

Because Python creates a new object each time you create a list, dictionary, or set — even if values are the same.

Let’s explore more...

Tuples — The Sneaky Immutable

Tuples are immutable, yes. But reuse depends on what they contain.

Case 1: Tuples with only immutables

a = (1, 2, 3)
b = (1, 2, 3)
print(a is b)# Could be True or False depending on the Python implementation

In this Python may reuse memory depending on the Python implementation.in some small tuple cases that might be true

Case 2: Tuples with mutables inside

a = ([1, 2], 3)
b = ([1, 2], 3)
print(a is b)  # Always False

Python does not reuse this tuple because it contains mutable objects inside.

Identity with Functions and Objects

def func(): pass

print(func is func)  # True

x = func
print(x is func)     # True

Even classes or functions are objects in Python — and is checks if they are the same reference.

Practical Use Case of is

x = None
if x is None:
    print("x is not set yet")

Pythonic way to check for None.
Avoid doing x == None.

Recap : Which Types Are Reused / New?

Data TypeImmutable?Reused with is?
int (-5 to 256)YesYes
int (others)YesNo (new object)
str (short/simple)YesYes (often)
str (complex)YesNo (usually)
listNoNo
tuple (all immutables)YesMaybe
tuple (with mutables)YesNo
dict, setNoNo
None, True, FalseYesAlways same object

Alright fam, if you’ve made it this far give yourself a virtual high-five 🙌.

That was quite a ride through the land of Python Operators. From the straightforward to the totally “wait, what?” moments, we cracked open every corner of what Python operators really do. not just how to use them, but why they work the way they do.

And if you’ve made it this far. you're not just coding Python anymore... you're starting to think in Python🧠.
Pretty cool, right?

But hey — don’t close the tab just yet!

We’ve only scratched the surface of what Python hides in plain sight. we’re diving into a topic that looks simple on the outside… but hides tons of power and gotchas inside: Strings.

Yeah, that thing you thought was just text inside quotes?
Turns out, it’s got its own rules… quirks… and even memory tricks that can surprise you!

So grab a cup of chai or coffee ☕, stretch a bit, and when you’re ready

🔥 Episode 2: Strings in Python – Not Just Text, But Pure Magic is waiting for you.

Trust me, you don’t wanna miss it.
Let’s keep leveling up one line of code at a time.

See you there, Python fam! 🐍💚

21
Subscribe to my newsletter

Read articles from Neha Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Neha Patel
Neha Patel