Strings are one of the most fundamental data types in Python. From storing a username to printing a message on screen, nearly every real-world Python program relies on them. This tutorial walks through everything you need to get started — creating strings, accessing individual characters, slicing ranges, joining strings together, applying built-in methods, and formatting output with f-strings.
Python represents text as a sequence of characters. That sequence can be a single letter, a word, a sentence, or thousands of lines — the behavior is consistent regardless of length. Understanding how Python stores and manipulates strings gives you a foundation that carries into nearly every other topic in the language.
What Is a String in Python?
A string is a sequence of characters enclosed in quotes. Python accepts single quotes, double quotes, or triple quotes. All three produce the same kind of object — the choice is a matter of convenience and readability.
greeting = 'Hello, world!'
name = "Kandi"
paragraph = """This spans
multiple lines."""
print(type(greeting)) # <class 'str'>
Triple-quoted strings are useful when a string must span multiple lines, or when it contains both single and double quotes. They are frequently used for docstrings — the documentation blocks placed at the top of functions and classes.
Python strings are immutable. Once created, the characters inside a string cannot be changed in place. Methods that appear to modify a string actually return a brand new string object. The original remains untouched.
Escape characters
Some characters carry special meaning inside a string. A backslash introduces an escape sequence, telling Python to interpret the next character differently rather than as a literal character.
print("Line one\nLine two") # \n = newline
print("col1\tcol2") # \t = tab
print("She said \"hello\"") # \" = literal double quote
print("C:\\Users\\kandi") # \\ = literal backslash
A raw string, prefixed with r, tells Python to treat backslashes as literal characters rather than escape sequences. This is commonly used when writing regular expressions or Windows file paths.
path = r"C:\Users\kandi\documents"
print(path) # C:\Users\kandi\documents
Indexing: Accessing Individual Characters
Python stores each character in a string at a numbered position called an index. Indexing starts at zero, so the first character is always at position 0, not 1. This zero-based convention is common across many programming languages.
To retrieve a character, place its index inside square brackets immediately after the variable name. Python also supports negative indexing: -1 always refers to the last character, -2 to the one before it, and so on. This allows you to count from the end of a string without knowing its length.
language = "Python"
print(language[0]) # P — first character
print(language[2]) # t — third character
print(language[-1]) # n — last character
print(language[-2]) # o — second-to-last
The built-in len() function returns the total number of characters in a string. This is useful for calculating valid index ranges and for looping over each character.
word = "Python"
print(len(word)) # 6
# Loop through every character
for char in word:
print(char)
Attempting to access an index that does not exist — for example language[10] on a six-character string — raises an IndexError. Always verify the length of a string before using a hardcoded index on unknown input.
Build the correct Python expression to retrieve the last character of a string called word using negative indexing:
Slicing: Extracting Substrings
Slicing lets you extract a portion of a string by specifying a start and stop index separated by a colon: string[start:stop]. The character at the start index is included. The character at the stop index is excluded — the slice runs up to, but not including, that position.
text = "PythonCodeCrack"
print(text[0:6]) # Python — characters 0 through 5
print(text[6:10]) # Code — characters 6 through 9
print(text[10:]) # Crack — from index 10 to the end
print(text[:6]) # Python — from the beginning to index 5
print(text[-5:]) # Crack — last five characters
Omitting the start value defaults to 0 (the beginning of the string). Omitting the stop value defaults to the end of the string. Both can be omitted at once to produce a copy of the entire string: text[:].
Step slicing
A third value, the step, controls how many positions to advance between each selected character. The full syntax is string[start:stop:step]. A step of 2 selects every other character. A step of -1 reverses the string — a common technique in Python.
alphabet = "abcdefghij"
print(alphabet[0:10:2]) # acegi — every second character
print(alphabet[::-1]) # jihgfedcba — reversed
Slicing versus indexing at a glance
- Returns
- A single character (a string of length 1)
- Use when
- You need exactly one character at a known position
- Returns
- A new string containing the selected range of characters
- Use when
- You need a substring — a word, prefix, suffix, or any range
- Returns
- A new string with characters selected at the given step interval
- Use when
- Reversing a string, sampling every Nth character, or traversing backward
Concatenation and Repetition
Two strings can be joined end-to-end using the + operator. This is called concatenation. The result is a new string — neither of the original strings is modified.
first = "Python"
second = "CodeCrack"
combined = first + " " + second
print(combined) # Python CodeCrack
The * operator repeats a string a given number of times. This is known as repetition and is occasionally useful for building separators or test data.
separator = "-" * 30
print(separator) # ------------------------------
print("ha" * 3) # hahaha
Python does not automatically convert numbers to strings. Trying to concatenate a string and an integer with + raises a TypeError. Wrap the number in str() first: "Score: " + str(42).
Joining a list of strings efficiently
When you need to combine many strings from a list, using + in a loop is inefficient because it creates a new string object on every iteration. The str.join() method handles this in a single pass and is the preferred approach.
words = ["Python", "is", "easy", "to", "learn"]
sentence = " ".join(words)
print(sentence) # Python is easy to learn
csv_line = ",".join(["Alice", "30", "Engineer"])
print(csv_line) # Alice,30,Engineer
Built-In String Methods
Python includes a large set of built-in methods that operate on strings. Because strings are immutable, each method returns a new string rather than changing the original. The examples below cover the methods you will encounter most often as a beginner.
"Strings are objects with a rich set of methods." — Python documentation
s = " Hello, Python World! "
# Case methods
print(s.upper()) # " HELLO, PYTHON WORLD! "
print(s.lower()) # " hello, python world! "
print(s.title()) # " Hello, Python World! "
print(s.swapcase()) # " hELLO, pYTHON wORLD! "
# Whitespace
print(s.strip()) # "Hello, Python World!"
print(s.lstrip()) # "Hello, Python World! "
print(s.rstrip()) # " Hello, Python World!"
# Search and replace
print(s.strip().replace("Python", "Beginner"))
# "Hello, Beginner World!"
# Finding
print(s.find("Python")) # 9 — index of first match, -1 if not found
print("Python" in s) # True
# Splitting
words = s.strip().split(", ")
print(words) # ['Hello', 'Python World!']
# Testing
print("12345".isdigit()) # True
print("hello".isalpha()) # True
print("hello world".isalpha()) # False — space is not alpha
Methods can be chained together. Each call returns a new string, which becomes the target of the next method call. Keep chains readable — three or four methods on one line is often the practical limit before clarity suffers.
user_input = " [email protected] "
clean = user_input.strip().lower()
print(clean) # [email protected]
This function is supposed to return the first word of a sentence in uppercase. One line contains a bug. Click the line you think is wrong, then hit check.
first.Upper() to first.upper(). Python method names are case-sensitive. The built-in string method is .upper() (all lowercase). .Upper() does not exist and raises an AttributeError.
How to Format Strings in Python
Python provides several approaches to embedding variable values inside a string. The three primary methods are f-strings (formatted string literals), the str.format() method, and the older % operator. F-strings, introduced in Python 3.6, are the current recommended approach for their speed and readability.
-
Use an f-string for simple variable embedding
Prefix the string literal with
fand place the variable or expression directly inside curly braces. Python evaluates the expression at runtime and inserts the result. This is the simplest and most readable option for the majority of situations. -
Control number formatting inside f-strings
Add a format specification after a colon inside the curly braces. For example,
{price:.2f}formats thepricevariable to two decimal places.{count:04d}pads an integer with leading zeros to a width of four digits. -
Use str.format() when targeting Python versions below 3.6
Call
.format()on a string that contains{}or named{placeholder}markers. Pass the values to insert as arguments to the method. This approach is compatible with Python 2 and earlier Python 3 releases, but f-strings are preferred in modern code. -
Embed expressions, not just variables
The curly brace syntax inside f-strings accepts any valid Python expression — arithmetic, function calls, conditionals, and more. For example,
f"Result: {2 ** 10}"produces"Result: 1024"without needing a separate variable assignment. -
Use raw f-strings when combining formatting with backslashes
When a formatted string must also contain literal backslashes, combine the
fandrprefixes:rf"...". This avoids unintended escape sequence processing while still allowing variable embedding through curly braces. -
Avoid concatenating with + when formatting multiple values
Mixing
+concatenation withstr()conversions to build output strings is verbose and easy to misread. An f-string that references several variables in one literal is almost always clearer and faster.
# f-string (Python 3.6+) — recommended
name = "Kandi"
score = 97.5
print(f"Name: {name}, Score: {score:.1f}%")
# Name: Kandi, Score: 97.5%
# Expressions inside f-strings
width = 80
print(f"{'Centered Title':^{width}}") # center-aligns text
# str.format() — compatible with older Python
print("Name: {}, Score: {:.1f}%".format(name, score))
# % operator — legacy, avoid in new code
print("Name: %s, Score: %.1f%%" % (name, score))
Python Strings: Key Points
- A string is an immutable sequence of characters. Modifying a string always produces a new string object — the original is never altered.
- Indexing uses zero-based integers. The first character is at index 0 and the last is at index
-1. Accessing an out-of-range index raises anIndexError. - Slicing with
[start:stop:step]extracts a substring. The stop index is always excluded from the result. Omitting start or stop defaults to the beginning or end of the string respectively. - The
+operator concatenates strings, the*operator repeats them, andstr.join()is the efficient choice when combining many strings from a list. - Built-in methods such as
.upper(),.strip(),.replace(), and.split()return new strings and can be chained together. - F-strings are the modern standard for string formatting in Python 3.6 and later. They are faster than
str.format()and significantly more readable than%formatting.
With these fundamentals in place, you can handle the vast majority of text manipulation tasks you will encounter as a beginner. From here, the natural next step is to explore regular expressions for pattern matching, or to look at how strings interact with file I/O when reading and writing text files.
Frequently Asked Questions
A string in Python is a sequence of characters enclosed in single quotes, double quotes, or triple quotes. Strings are immutable, meaning their content cannot be changed after creation, but you can create new strings derived from existing ones.
There is no functional difference. Python treats 'hello' and "hello" as identical string objects. The choice is a matter of style or convenience — double quotes are useful when the string itself contains an apostrophe, and single quotes work well when the string contains double quotes.
No. Python strings are immutable. Once a string is created, its individual characters cannot be changed in place. Methods that appear to modify a string actually return a new string object, leaving the original unchanged.
Use the built-in len() function, passing the string as the argument. For example, len('Python') returns 6. The result is the total number of characters including spaces and punctuation.
String indexing in Python starts at 0. The first character is at index 0, the second at index 1, and so on. Python also supports negative indexing, where -1 refers to the last character, -2 to the second-to-last, and so on.
You can combine strings using the + operator, which is called concatenation. For example, 'Hello' + ' World' produces 'Hello World'. For joining many strings from a list, the str.join() method is more efficient.
An f-string, short for formatted string literal, is a string prefixed with the letter f that allows you to embed Python expressions directly inside curly braces. For example, f'Hello, {name}!' replaces {name} with the value of the variable name at runtime. F-strings were introduced in Python 3.6.
Use the in keyword. For example, 'py' in 'python' returns True. This is case-sensitive, so 'Py' in 'python' returns False. You can also use the str.find() method, which returns the index of the first match or -1 if not found.