Strings in Python
Strings in Python
🔹 String Interning
Python optimizes memory using a technique called string interning.
What is String Interning?
It means Python will reuse immutable strings (especially short strings and identifiers) rather
than creating new copies.
a = "hello"
b = "hello"
print(a is b) # True – both point to the same memory
Python keeps a global pool of common strings to save memory and speed up comparison.
🚫 Strings Are Immutable
Once a string is created, you cannot change it. Any modification results in a new string
object.
s = "cat"
s[0] = "b" # ❌ This raises a TypeError
Why Immutability?
1. Thread safety – Multiple threads can share the same string.
2. Hashability – Strings can be used as keys in dictionaries.
3. Performance – Enables interning and caching.
0 'C' 1000
1 'h' 1001
2 'a' 1002
3 't' 1003
Mutable? ❌ No – immutable
Null terminator? ❌ No
Hashable? ✅ Yes
🔹 1. Indexing
🧠 Theory:
Each character in a string has a position (index).
Indexing allows direct access to any character.
Python supports positive and negative indexing.
Syntax:
s = "python"
print(s[0]) # 'p'
print(s[-1]) # 'n' (last character)
🔍 Memory View:
Think of s = "python" like:
Index Value
0 'p'
1 'y'
2 't'
3 'h'
4 'o'
5 'n'
-1 'n'
-2 'o'
... ...
🔹 2. Slicing
🧠 Theory:
Slicing is like cutting a substring from the original string.
It creates a new string (doesn’t modify the original).
Syntax:
s = "python"
print(s[1:4]) # 'yth' → index 1 to 3
print(s[:3]) # 'pyt' → from 0 to 2
print(s[3:]) # 'hon' → from 3 to end
Structure:
s[start:stop:step]
Examples:
s = "openai"
print(s[::2]) # 'oen'
print(s[::-1]) # 'ianepo' → reversed string
🔹 4. Membership Testing
🧠 Theory:
Uses a linear scan to check if a substring exists.
s = "machine learning"
print("learn" in s) # True
print("data" not in s) # True
🔹 5. String Length
s = "algorithm"
print(len(s)) # 9
Internally, Python does not count each time — it stores the length in metadata.
🔹 6. String Iteration
for ch in "DSA":
print(ch)
You can treat strings like lists — they are iterables.
🔹 7. Immutability Reminder
s = "code"
s[0] = "m" # ❌ Error: strings can't be changed in-place
To "change" a string, you create a new one:
s = "code"
s = "m" + s[1:] # 'mode'
🧵 Summary Table
len(s) Length 6
Imagine you are reading a long book. You're looking for a specific phrase, say:
"The secret door was hidden behind the library."
Now, this book has millions of characters — how would you find that phrase manually?
You'd likely start from the beginning, reading line by line, comparing what you see with the
phrase in your mind. When a few matching words begin to show up, you'd lean in and
compare more carefully.
This is exactly how a naive string search works.
🧠 Real-Life Analogy
You’re checking whether someone is in a long attendance list printed on paper:
Naive search is like reading every name line-by-line and matching letters one by one.
Efficient search (we’ll learn later) is like having the list indexed or alphabetically
sorted — or like having a highlighted pattern in your glasses.
That’s how modern algorithms work — they preprocess data or patterns to skip
unnecessary comparisons.
🧠 Theoretical Definition
Lexicographical order is a way to compare sequences (like strings) based on the order of
their characters from left to right.
Imagine comparing "cat" and "car":
First letter: c == c → go to next
Second letter: a == a → go to next
Third letter: t > r → 'cat' > 'car'
So:
python
CopyEdit
"cat" > "car" # True
Character ASCII
'a' 97
'b' 98
'c' 99
... ...
'A' 65
'B' 66
So:
python
CopyEdit
print("apple" < "banana") # True, because 'a' < 'b'
print("Apple" < "apple") # True, because 'A' < 'a'
🧠 Real-World Analogy
Imagine working in a library, sorting books. You look at the book titles:
If the first letters differ, sort based on that.
If they’re the same, move to the second letter.
Continue until you find a difference.
If no difference and one title ends first, the shorter one comes first.
This is how dictionaries, contact lists, and file names are sorted.
🔍 Important Notes
Comparisons are case-sensitive by default:
python
CopyEdit
"Apple" < "banana" # True because 'A' (65) < 'b' (98)
For case-insensitive sorting, you can convert everything to lowercase first:
python
CopyEdit
sorted(words, key=lambda w: w.lower())
🧠 Mental Model
“Comparing strings is like two kids running a race. They start together. The first one who
takes a different path (i.e., different character) determines who wins. If they run neck and
neck, the shorter one wins because they cross the finish line earlier.”