Strings & Text
What is a String?
A string is a sequence of characters — letters, digits, spaces, symbols, or even emojis — wrapped in quotes. Strings are one of the most used data types in any programming language, because almost everything you show to a user is text.
In Python, strings are immutable — once created, you can't change individual characters. Instead, you create a new string from the original. This makes strings safe to pass around without fear of accidental changes.
# Three ways to create strings single = 'Hello, Python!' # single quotes double = "Hello, Python!" # double quotes (same result) triple = """This string spans multiple lines.""" # triple quotes = multi-line print(single) print(triple) # Strings can hold any characters mixed = "Python 3.12 🐍" digits = "12345" # this is TEXT, not a number empty = "" # empty string — valid! space = " " # one space — also a string print(len(mixed)) # 13 (len counts characters) print(len(empty)) # 0
Indexing & Slicing
Every character in a string has a position number called an index. Python indexes start at 0 (not 1!). You can also count from the end using negative indexes — -1 is always the last character.
lang = "Python" # Positive indexing print(lang[0]) # P — first character print(lang[1]) # y print(lang[5]) # n — last character # Negative indexing print(lang[-1]) # n — last character print(lang[-6]) # P — first character # IndexError — going out of bounds # print(lang[10]) → IndexError: string index out of range
Slicing — Extract a Portion
Slicing lets you extract a substring using the syntax string[start:stop:step]. The start is inclusive, the stop is exclusive.
text = "BitWithBite" # Basic slice: [start:stop] (stop is excluded) print(text[0:3]) # Bit (chars at 0,1,2) print(text[3:7]) # With print(text[7:]) # Bite (omit stop = go to end) print(text[:3]) # Bit (omit start = from beginning) print(text[:]) # BitWithBite (full copy) # Step: [start:stop:step] print(text[0:11:2]) # BtihBt (every 2nd char) print(text[::-1]) # etiByhtiwtiB (reversed!) # Negative slicing print(text[-4:]) # Bite (last 4 characters) print(text[:-4]) # BitWith (everything except last 4)
[::-1][::-1] is a classic Python one-liner for reversing any string (or list). It means: start at the end, go back to the beginning, step -1 (backwards). This is commonly asked in coding interviews!Essential String Methods
Python strings come with 50+ built-in methods. You call them with dot notation: string.method(). Here are the most important ones you'll use daily.
name = " fatima malik " # Clean up user input clean = name.strip().title() print(clean) # Fatima Malik # Chaining methods email = " USER@Gmail.COM " print(email.strip().lower()) # user@gmail.com # split + join csv_row = "Ali,20,Karachi,Python" fields = csv_row.split(",") print(fields) # ['Ali', '20', 'Karachi', 'Python'] print(" | ".join(fields)) # Ali | 20 | Karachi | Python # Validate input code = "BWB2025" print(code.startswith("BWB")) # True print(code.endswith("2025")) # True # replace sentence = "I love Java. Java is great." print(sentence.replace("Java", "Python")) # I love Python. Python is great.
"hello".upper() doesn't change "hello" — it returns a brand-new string "HELLO". If you want to keep the result, you must assign it: name = name.upper(). This is the immutability of strings in action.f-Strings — Modern String Formatting
An f-string (formatted string literal) is the modern, clean way to embed variables and expressions directly inside a string. Prefix the string with f and put variables inside {curly braces}.
f-strings were introduced in Python 3.6 and are now the recommended way to format strings — faster and more readable than older methods like % formatting or .format().
name = "Sara" age = 21 gpa = 3.85 # Basic f-string print(f"Name: {name}") # Name: Sara print(f"{name} is {age} years old.") # Sara is 21 years old. # Expressions inside braces print(f"Birth year: {2025 - age}") # Birth year: 2004 print(f"CGPA: {gpa * 100 / 4}%") # CGPA: 96.25% # Format numbers — decimal places print(f"GPA: {gpa:.1f}") # GPA: 3.9 (1 decimal) print(f"GPA: {gpa:.4f}") # GPA: 3.8500 (4 decimals) # Call methods inside f-strings print(f"Hello, {name.upper()}!") # Hello, SARA! # Multi-line f-strings card = f""" Student Card ──────────── Name: {name} Age : {age} GPA : {gpa:.2f} ────────────""" print(card)
"Hello " + name (concatenation) or "Hello %s" % name (%-formatting) or "Hello {}".format(name). All work, but f-strings are cleaner, faster, and the modern standard. Use them exclusively.Escape Characters
Some characters can't be typed directly inside a string — like a newline, a tab, or a backslash. You use an escape sequence: a backslash \ followed by a special character.
| Escape | Meaning | Example | Output |
|---|---|---|---|
\n | Newline — move to next line | "Hi\nWorld" | Hi World |
\t | Tab — horizontal indent | "Name:\tAli" | Name: Ali |
\\ | Literal backslash | "C:\\Users" | C:\Users |
\' | Single quote inside single-quoted string | 'it\'s' | it's |
\" | Double quote inside double-quoted string | "say \"hi\"" | say "hi" |
\r | Carriage return | Rare in modern use | — |
# \n — newline print("Line 1\nLine 2\nLine 3") # Line 1 # Line 2 # Line 3 # \t — tab for alignment print("Name:\tAli") print("Score:\t99") # Windows file paths — use \\ or r"raw string" path1 = "C:\\Users\\Fatima\\Documents" path2 = r"C:\Users\Fatima\Documents" # raw string — same result print(path1) print(path2) # Quotes inside strings print('Python\'s syntax is clean') # Python's syntax is clean print("She said \"hello!\"") # She said "hello!" # Or just mix quote types (easier): print("Python's syntax is clean") # no escape needed
String Operations
Python supports several powerful operators that work directly on strings.
+"Hello" + " " + "World" → "Hello World". Both sides must be strings.*"ha" * 3 → "hahaha". Great for separators like "-" * 40.in"py" in "python" → True. Checks if substring exists. Case-sensitive!len()len("Python") → 6. Works on any sequence — strings, lists, tuples.# Concatenation first = "Bit" last = "WithBite" full = first + last print(full) # BitWithBite # Repetition — great for dividers print("=" * 30) # ============================== print("ha" * 5) # hahahahaha # Membership test print("Bite" in full) # True print("java" in full) # False print("bite" in full) # False ← case-sensitive! print("bite" in full.lower()) # True ← convert to handle case # Length print(len(full)) # 11 print(len("")) # 0 — empty string # Practical: validate minimum password length password = "mysecret" if len(password) >= 8: print("Password is strong enough") else: print("Password too short!")
+"Score: " + 95 will throw a TypeError. You must convert: "Score: " + str(95). This is why f-strings are usually better — f"Score: {95}" handles the conversion for you automatically."Python"[1] return?"hello world".upper() return?"banana"[::-1] return?"py" in "Python" return?1. Takes a
full_name like " sara khan " and cleans it using .strip().title()2. Generates a username by taking the first 4 characters of the cleaned first name, lowercased
3. Counts how many times the letter
"a" appears in the full name (case-insensitive)4. Checks if the name ends with
"Khan" using a string method5. Prints a formatted bio card using an f-string with the name, username, letter count, and the Khan check result
💡 Show hints
- Use
.strip().title()to clean the name - Use slicing
first_name[:4].lower()for the username - Use
.lower().count("a")for case-insensitive count - Use
.endswith("Khan")to check surname - Use a triple-quote f-string for the multi-line card
# ── Username & Bio Generator ───────────────── raw_name = " sara khan " full_name = raw_name.strip().title() # "Sara Khan" first_name = full_name.split()[0] # "Sara" username = first_name[:4].lower() # "sara" a_count = full_name.lower().count("a") # 3 is_khan = full_name.endswith("Khan") # True bio = f""" ╔══════════════════════╗ User Profile Name : {full_name} Username : @{username} Letter a : {a_count} times Is Khan : {is_khan} ╚══════════════════════╝""" print(bio)