Creating Strings
A string in Python is a sequence of Unicode characters enclosed in quotes. Python offers four ways to delimit strings, each with its use case.
# Single quotes
name = 'Alice'
# Double quotes (most common)
greeting = "Hello, World!"
# Single quotes containing an apostrophe
message = "It's a beautiful day" # easier than 'It\'s a beautiful day'
# Double quotes containing a quote character
quote = 'She said "Hello!"' # easier than "She said \"Hello!\""
# Triple-quoted strings (single or double) β for multiline
poem = """Roses are red,
Violets are blue,
Python is awesome,
And so are you!"""
haiku = '''An old silent pond
A frog jumps into the pond
Splash! Silence again'''
print(poem)
print("---")
print(haiku)
Strings in Python are immutable β you can read characters by index but you cannot change individual characters. Any operation that appears to "modify" a string actually returns a new string object.
String Indexing
Each character in a string has a numeric position called an index. Python uses zero-based indexing (first character is at index 0) and also supports negative indexing to count from the end.
word = "Python"
# P y t h o n
# 0 1 2 3 4 5 (positive indices)
# -6-5-4-3-2-1 (negative indices)
print(word[0]) # P β first character
print(word[1]) # y
print(word[5]) # n β last character
print(word[-1]) # n β last character (negative index)
print(word[-2]) # o β second to last
print(word[-6]) # P β same as word[0]
# Length of a string
print(len(word)) # 6
# Common pattern: get last character
last = word[len(word) - 1] # same as word[-1]
print(last) # n
# IndexError if index is out of range
# print(word[10]) # IndexError: string index out of range
String Slicing
Slicing extracts a substring from a string. The syntax is string[start:stop:step]. The start index is inclusive, the stop index is exclusive.
text = "Hello, World!"
# 0123456789...
# Basic slicing: [start:stop]
print(text[0:5]) # Hello (indices 0,1,2,3,4)
print(text[7:12]) # World
print(text[7:]) # World! (to end of string)
print(text[:5]) # Hello (from start)
print(text[:]) # Hello, World! (full copy)
# Negative indices in slices
print(text[-6:]) # World! (last 6 characters)
print(text[:-1]) # Hello, World (all but last)
# Step: [start:stop:step]
print(text[::2]) # Hlo ol! (every 2nd character)
print(text[::-1]) # !dlroW ,olleH (REVERSED!)
print(text[::1]) # Hello, World! (no change, step=1)
# Practical examples
filename = "report_2024.pdf"
print(filename[:6]) # report (filename without date)
print(filename[-3:]) # pdf (file extension without dot)
print(filename[-7:-4]) # 2024 (year)
email = "alice@example.com"
at_index = email.index("@")
username = email[:at_index]
domain = email[at_index+1:]
print(username) # alice
print(domain) # example.com
String Methods
Python strings have over 40 built-in methods. Here are the most important ones you'll use daily. Remember: because strings are immutable, all these methods return new strings β they don't modify the original.
Case Methods
text = "hello, World! python IS great."
print(text.upper()) # HELLO, WORLD! PYTHON IS GREAT.
print(text.lower()) # hello, world! python is great.
print(text.title()) # Hello, World! Python Is Great.
print(text.capitalize()) # Hello, world! python is great.
print(text.swapcase()) # HELLO, wORLD! PYTHON is GREAT.
# Case-insensitive comparison
password_input = "PyThOn"
stored_password = "python"
print(password_input.lower() == stored_password) # True
Whitespace Methods: strip, lstrip, rstrip
raw = " Hello, World! "
print(repr(raw.strip())) # 'Hello, World!' β removes both sides
print(repr(raw.lstrip())) # 'Hello, World! ' β removes left only
print(repr(raw.rstrip())) # ' Hello, World!' β removes right only
# Strip specific characters (not just whitespace)
messy = "***Python***"
print(messy.strip("*")) # Python
csv_line = ",,,data,,,"
print(csv_line.strip(",")) # data
# Very common use case: cleaning user input
user_input = " alice@example.com \n"
clean_email = user_input.strip()
print(clean_email) # alice@example.com
Search Methods: find, index, count, startswith, endswith
sentence = "The quick brown fox jumps over the lazy dog"
# find() β returns index of first occurrence, -1 if not found
print(sentence.find("fox")) # 16
print(sentence.find("cat")) # -1 (not found)
# index() β like find() but raises ValueError if not found
print(sentence.index("fox")) # 16
# sentence.index("cat") # ValueError!
# count() β count occurrences
print(sentence.count("the")) # 1 (case-sensitive!)
print(sentence.lower().count("the")) # 2
# startswith() and endswith()
url = "https://example.com"
print(url.startswith("https")) # True
print(url.endswith(".com")) # True
print(url.startswith(("http", "ftp"))) # True β tuple of options!
filename = "data.csv"
if filename.endswith((".csv", ".tsv", ".txt")):
print("It's a text data file")
Replace and Split/Join
# replace(old, new) β replaces all occurrences
text = "I like cats. Cats are great. My cat is named Luna."
print(text.replace("cat", "dog"))
# I like dogs. Cats are great. My dog is named Luna.
# Note: case-sensitive β "Cats" was not replaced
print(text.replace("cat", "dog", 1)) # only replace first occurrence
# split() β splits string into a list
sentence = "apple,banana,cherry,date"
fruits = sentence.split(",")
print(fruits) # ['apple', 'banana', 'cherry', 'date']
words = "Hello World Python".split() # split on whitespace by default
print(words) # ['Hello', 'World', 'Python']
# split with maxsplit
parts = "one:two:three:four".split(":", 2)
print(parts) # ['one', 'two', 'three:four']
# join() β joins a list into a string
words_list = ["Python", "is", "amazing"]
print(" ".join(words_list)) # Python is amazing
print("-".join(words_list)) # Python-is-amazing
print("".join(words_list)) # Pythonisamazing
# Common pattern: clean and rejoin
csv = " apple , banana , cherry "
clean = ", ".join(item.strip() for item in csv.split(","))
print(clean) # apple, banana, cherry
Check Methods: isdigit, isalpha, isspace, in
# Checking string content
print("12345".isdigit()) # True β all digits
print("hello".isalpha()) # True β all letters
print("hello3".isalpha()) # False β contains digit
print("hello3".isalnum()) # True β letters or digits
print(" ".isspace()) # True β all whitespace
print("Hello".istitle()) # True β title case
print("HELLO".isupper()) # True β all uppercase
print("hello".islower()) # True β all lowercase
# Membership test with 'in'
sentence = "The quick brown fox"
print("fox" in sentence) # True
print("cat" in sentence) # False
print("fox" not in sentence) # False
# Practical: validate a username
username = "alice_123"
def is_valid_username(u):
return (len(u) >= 3 and
len(u) <= 20 and
u.replace("_", "").isalnum())
print(is_valid_username("alice_123")) # True
print(is_valid_username("hi")) # False (too short)
print(is_valid_username("bad name!")) # False (invalid chars)
F-Strings (Formatted String Literals)
Introduced in Python 3.6, f-strings are the modern, recommended way to embed expressions inside strings. They are faster than .format() and more readable than concatenation.
name = "Alice"
age = 25
score = 98.765
# Basic f-string
print(f"Hello, {name}!") # Hello, Alice!
print(f"Age: {age}, Score: {score}") # Age: 25, Score: 98.765
# Expressions inside {}
print(f"Next year you'll be {age + 1}") # Next year you'll be 26
print(f"Score * 2 = {score * 2:.1f}") # Score * 2 = 197.5
# Formatting numbers
pi = 3.14159265
print(f"Pi = {pi:.2f}") # Pi = 3.14 (2 decimal places)
print(f"Pi = {pi:.5f}") # Pi = 3.14159
print(f"Number: {12345:,}") # Number: 12,345 (comma separator)
print(f"Hex: {255:#x}") # Hex: 0xff
print(f"Binary: {10:#b}") # Binary: 0b1010
# Alignment and padding
item = "Apple"
price = 1.5
print(f"{item:<15} ${price:>8.2f}") # Apple $ 1.50
print(f"{'Name':^20}") # Name (centered)
# Calling methods inside f-strings
print(f"Upper: {name.upper()}") # Upper: ALICE
print(f"Length: {len(name)}") # Length: 5
# Nested quotes (Python 3.12+ allows same quotes inside)
data = {"key": "value"}
print(f"Value: {data['key']}") # Value: value
# Multi-line f-string
report = (
f"Student: {name}\n"
f"Age: {age}\n"
f"Score: {score:.1f}%"
)
print(report)
The .format() Method
Before f-strings, .format() was the standard way to build formatted strings. You'll see it in older codebases, so understanding it is important.
# Positional arguments
print("Hello, {}!".format("World"))
print("{} + {} = {}".format(3, 4, 7))
# Named arguments (more readable)
print("{name} is {age} years old".format(name="Alice", age=25))
# Reusing arguments
print("{0} loves {1}. {1} is great!".format("Alice", "Python"))
# Format specifiers (same as f-strings)
print("Pi = {:.3f}".format(3.14159))
print("{:>10}".format("right")) # right-aligned in 10 chars
print("{:^10}".format("center")) # centered
Multiline Strings
# Triple-quoted strings preserve newlines and indentation
sql_query = """
SELECT name, age, email
FROM users
WHERE active = 1
ORDER BY name ASC
"""
html_template = """
<div class="card">
<h2>{title}</h2>
<p>{body}</p>
</div>
""".format(title="Hello", body="World")
# Using parentheses for implicit line continuation (no newline in string)
long_message = (
"This is a very long message that has been "
"split across multiple lines in the source code "
"but will appear as one line when printed."
)
print(long_message)
# Backslash for line continuation (less preferred)
another = "Hello " \
"World"
print(another) # Hello World
Escape Characters
| Escape Sequence | Meaning | Example Output |
|---|---|---|
\n | Newline | New line in output |
\t | Tab | Horizontal tab spacing |
\\ | Backslash | \ |
\' | Single quote | ' |
\" | Double quote | " |
\r | Carriage return | Moves cursor to start of line |
\b | Backspace | Moves cursor back one |
\0 | Null character | Null byte |
\uXXXX | Unicode character | β€ β β€ |
\xHH | Hex character | \x41 β A |
print("Name:\tAlice\nAge:\t25")
# Name: Alice
# Age: 25
print("Path: C:\\Users\\Alice")
# Path: C:\Users\Alice
print("Unicode: β€ β
βΊ")
# Unicode: β€ β
βΊ
# Raw strings ignore escape sequences
path = r"C:\Users\Alice\new_folder"
print(path) # C:\Users\Alice\new_folder (not a newline!)
ποΈ Practical Exercise
Write a Python program that processes a user's full name string:
- Store the name
" john michael smith "in a variable. - Strip the whitespace, then capitalize it properly (title case).
- Split it into a list of individual names.
- Print the first name, last name, and middle initial (first letter of middle name + ".") using an f-string.
- Count how many letters are in the full name (excluding spaces).
- Check if the name starts with "John" (case-insensitive).
π₯ Challenge Exercise
Build a simple "string statistics" tool. Given any input string, use string methods to report: total character count, word count (after splitting), unique character count (hint: use set()), count of vowels, whether it is a palindrome (reads same forwards and backwards β ignore case and spaces), and the most common character. Format your output using f-strings with proper alignment so it looks like a neat report.
Interview Questions on Strings
- What does it mean that Python strings are immutable? What are the performance implications?
- What is the difference between
find()andindex()? - How do you reverse a string in Python? Explain two methods.
- What is the difference between
split()with no argument vssplit(" ")? - What are f-strings and when were they introduced? How are they better than
.format()? - How do you check if a substring exists in a string? Give two ways.
- What is a raw string (
r"...") and when would you use it? - How do you efficiently concatenate many strings in Python? (Hint:
join())
π Summary
- Strings can be created with single, double, or triple quotes; triple quotes support multiline text.
- Strings are zero-indexed; negative indices count from the end (
s[-1]is the last character). - Slicing syntax is
s[start:stop:step];s[::-1]reverses a string. - Strings are immutable β all string methods return new strings without modifying the original.
- Key methods:
upper(),lower(),strip(),split(),join(),replace(),find(),startswith(),endswith(). - F-strings (
f"...") are the preferred way to format strings in Python 3.6+. - Escape sequences like
\n,\t,\\add special characters to strings. - Raw strings (
r"...") treat backslashes as literal characters β essential for file paths and regex.
Related Topics
Frequently Asked Questions
Using + in a loop is slow because each concatenation creates a new string. The fastest approach is to collect strings in a list and use "".join(list) at the end. For example: result = "".join(parts). F-strings are also very efficient for a small number of substitutions.
Use s.isdigit() for simple cases. However, isdigit() returns True for Unicode digit characters too and returns False for negative numbers or decimals like "-5" or "3.14". For more robust checking, try wrapping in a try/except around int() or float().
split() with no argument splits on any whitespace (spaces, tabs, newlines) and removes empty strings from the result. split(' ') splits only on a literal space and keeps empty strings when there are consecutive spaces. For example, "a b".split() gives ['a', 'b'] but "a b".split(' ') gives ['a', '', 'b'].
No. Python strings are immutable. s[0] = 'H' raises a TypeError. To "change" a character, you must build a new string: s = 'H' + s[1:]. If you frequently need to modify individual characters, consider using a list of characters and joining at the end: chars = list(s); chars[0] = 'H'; s = ''.join(chars).
== checks if two strings have the same characters (value equality). is checks if two variables point to the exact same object in memory (identity). Due to Python's string interning, "hello" is "hello" may return True, but this is an implementation detail you should never rely on. Always use == to compare string values.