Nearly every Python program works with text in one form or another. Whether you are printing a welcome message, reading a file, or parsing data from the web, you are working with Python's str type. This tutorial walks through every foundational skill you need to create, read, format, and transform textual data in Python, starting from zero assumptions about your experience level.
Text processing is one of the first things you encounter when learning Python, and it is also one of the things you will use throughout your entire career with the language. The str type is built directly into Python's core, meaning you do not need to import anything to start working with strings. Understanding how strings behave, how to access individual characters, and how to transform text with built-in methods gives you a strong foundation for everything that comes next.
What Is Textual Data in Python?
Textual data in Python is handled with str objects. A string is an immutable sequence of Unicode code points, which is a formal way of saying it is a fixed series of characters that can represent virtually any written language, symbol, or emoji. Once created, the characters inside a string cannot be changed in place. Every operation that appears to modify a string returns a new str object instead.
You create a string by wrapping characters in quotes. Python accepts single quotes, double quotes, and triple quotes:
Python does not have a separate character type. When you index a string, you get another string of length 1. The expression 'hello'[0] returns the string 'h', not a distinct char value.
Prefix a string with r to create a raw string that treats backslashes as literal characters. This is especially useful for Windows file paths and regular expressions.
# Single quotes
greeting = 'Hello, world!'
# Double quotes — identical result
greeting = "Hello, world!"
# Triple quotes — for multi-line text
paragraph = """This string
spans multiple
lines."""
# Check the type
print(type(greeting)) # <class 'str'>
"Textual data in Python is handled with str objects." — Python Software Foundation, Built-in Types Documentation
Build a valid f-string that greets a user by name:
Indexing, Slicing, and Navigating Strings
Because a string is a sequence, you can access individual characters by their position using square brackets. Python uses zero-based indexing, which means the first character sits at index 0:
language = "Python"
print(language[0]) # 'P' — first character
print(language[3]) # 'h' — fourth character
print(language[-1]) # 'n' — last character
print(language[-2]) # 'o' — second to last
Negative indexes count backward from the end of the string. This is a convenient way to grab the last character without needing to know the string's length.
Slicing
Slicing extracts a substring by specifying a start index, a stop index, and an optional step. The start is inclusive and the stop is exclusive:
language = "Python"
print(language[0:3]) # 'Pyt' — index 0, 1, 2
print(language[2:]) # 'thon' — index 2 to end
print(language[:4]) # 'Pyth' — start to index 3
print(language[::2]) # 'Pto' — every other character
print(language[::-1]) # 'nohtyP' — reversed string
The len() function returns the total number of characters in a string, and the in keyword tests whether a substring exists within a larger string:
language = "Python"
print(len(language)) # 6
print("Py" in language) # True
print("java" in language) # False
- Returns
- A string of length 1 at the given position
- Example
- "Python"[0] returns 'P'
- Returns
- A new string from start up to (but not including) stop
- Example
- "Python"[0:3] returns 'Pyt'
- Returns
- An integer representing total number of characters
- Example
- len("Python") returns 6
This code tries to extract the first three characters from a string. One line has an off-by-one error. Can you find it?
language[1:4] to language[0:3] (or simply language[:3]). Because Python uses zero-based indexing, the first character is at index 0. Starting the slice at 1 skips the first character and gives you 'yth' instead of 'Pyt'.
Essential String Methods and Formatting
The str type comes with dozens of built-in methods. You do not need to memorize them all, but a handful appear in nearly every project. The methods below all return new strings because, as covered earlier, strings are immutable.
text = " Hello, Python World! "
# Case transformations
print(text.upper()) # ' HELLO, PYTHON WORLD! '
print(text.lower()) # ' hello, python world! '
print(text.title()) # ' Hello, Python World! '
# Whitespace removal
print(text.strip()) # 'Hello, Python World!'
# Search and replace
print(text.find("Python")) # 9
print(text.replace("World", "Learner"))
# Splitting and joining
words = "apple,banana,cherry".split(",")
print(words) # ['apple', 'banana', 'cherry']
print(" - ".join(words)) # 'apple - banana - cherry'
# Boolean checks
print("hello".isalpha()) # True
print("12345".isdigit()) # True
F-String Formatting
F-strings, introduced in Python 3.6, are the preferred way to embed variables and expressions inside a string. You prefix the string with the letter f and place any Python expression inside curly braces:
name = "Alice"
age = 30
# Basic interpolation
print(f"My name is {name} and I am {age} years old.")
# Expressions inside braces
print(f"Next year I will be {age + 1}.")
# Method calls
print(f"Name in uppercase: {name.upper()}")
# Format specifiers for numbers
price = 49.995
print(f"Total: ${price:.2f}") # 'Total: $49.99'
F-strings evaluate their expressions at runtime, which means you can include function calls, arithmetic, conditional expressions, and even list comprehensions inside the braces. This makes them far more readable than older formatting methods like % formatting or str.format().
String Concatenation
You can combine strings using the + operator or by placing string literals next to each other. For building strings from many parts, str.join() is more efficient than repeated concatenation:
# + operator
full_name = "Jane" + " " + "Doe"
# str.join() — preferred for many pieces
parts = ["2026", "04", "02"]
date_string = "-".join(parts)
print(date_string) # '2026-04-02'
Converting Between Strings and Other Types
Python does not automatically convert between strings and numbers. If you try to concatenate a string with an integer using +, Python raises a TypeError. You need to convert explicitly using str(), int(), or float():
age = 30
# This raises TypeError:
# print("I am " + age + " years old")
# Convert int to string with str()
print("I am " + str(age) + " years old")
# Or use an f-string, which handles conversion for you
print(f"I am {age} years old")
# Convert string to int
user_input = "42"
number = int(user_input)
print(number + 8) # 50
# Convert string to float
price = float("19.99")
print(price * 2) # 39.98
The input() function always returns a string, even when the user types a number. This is one of the first places beginners run into type conversion issues:
# input() always returns a string
response = input("Enter your age: ")
print(type(response)) # <class 'str'>
# Convert before doing math
age = int(response)
print(f"Next year you will be {age + 1}")
Passing a non-numeric string like "hello" to int() raises a ValueError. Always validate user input before converting, or wrap the conversion in a try/except block.
Iterating Over a String
Because strings are sequences, you can loop through them character by character using a for loop. This is useful for counting specific characters, filtering text, or building new strings from existing ones:
message = "Hello, Python!"
# Loop through each character
for char in message:
print(char, end=" ")
# H e l l o , P y t h o n !
# Count vowels in a string
vowels = "aeiouAEIOU"
count = 0
for char in message:
if char in vowels:
count += 1
print(f"\nVowel count: {count}") # 3
# Use enumerate() to get both index and character
for i, char in enumerate(message):
if char == "P":
print(f"Found 'P' at index {i}") # Found 'P' at index 7
When you need both the position and the character during iteration, use enumerate() instead of manually tracking an index variable. It produces cleaner, more readable code.
How to Create and Format Strings in Python
Follow these three steps to go from raw text to a fully formatted string you can print, log, or store.
-
Assign text to a variable using quotes
Create a string variable by assigning text enclosed in single or double quotes. For example:
greeting = 'Hello, world!'. Both single and double quotes produce the samestrobject. Use triple quotes for text that spans multiple lines. -
Embed values using an f-string
Prefix your string with the letter
fand place any variable or expression inside curly braces. For example:message = f'Hello, {name}!'. F-strings evaluate expressions at runtime and support method calls, arithmetic, and formatting specifiers inside the braces. -
Transform text with string methods
Call built-in methods on your string to transform it. Use
.upper()for uppercase,.lower()for lowercase,.strip()to remove whitespace,.replace(old, new)to swap substrings, and.split(separator)to break a string into a list. Remember that every method returns a new string because strings are immutable.
"There is also no mutable string type." — Python Software Foundation, Built-in Types Documentation
Python Learning Summary Points
- Python represents all textual data with the
strtype, an immutable sequence of Unicode code points that you create using single, double, or triple quotes. - Zero-based indexing and slicing (
string[start:stop:step]) let you access individual characters and extract substrings without modifying the original string. - Built-in methods like
.upper(),.strip(),.replace(),.split(), and.join()cover the vast majority of everyday text transformations, and f-strings provide a concise, readable way to embed dynamic values. - Python requires explicit type conversion between strings and numbers using
str(),int(), andfloat(), and theinput()function always returns a string regardless of what the user types. - Strings are iterable sequences, so a
forloop can walk through them character by character, andenumerate()adds an index when you need the position of each character.
With these fundamentals in place, you have everything you need to handle textual data in Python confidently. From here, you can explore regular expressions for pattern matching, the textwrap module for paragraph formatting, or the string module for constants like string.ascii_letters and string.digits. Every one of these tools builds on the same str type you have just learned.
Frequently Asked Questions
Textual data in Python is handled with the str type. A string is an immutable sequence of Unicode code points that represents text such as names, messages, file contents, or any other human-readable characters.
You create a string by enclosing characters in single quotes ('hello'), double quotes ("hello"), or triple quotes ('''hello''' or """hello""") for multi-line text. All three produce a str object.
Immutable means a string cannot be changed after it is created. Operations like .upper() or .replace() return a new string rather than modifying the original. To update a variable, you must reassign it to the new string.
Python uses zero-based indexing, so the first character is at index 0, the second at index 1, and so on. Negative indexes count from the end: -1 is the last character, -2 is the second to last.
F-strings (formatted string literals) are strings prefixed with f or F that allow you to embed Python expressions directly inside curly braces. They were introduced in Python 3.6 and are the preferred way to format strings because they are concise and readable.
There is no functional difference between single quotes and double quotes in Python. Both produce identical str objects. The choice is a matter of convenience, for example using double quotes when your string contains an apostrophe.
Escape characters use a backslash followed by a special character to represent things that are hard to type directly, such as newlines (\n), tabs (\t), or literal backslashes (\\). A raw string prefixed with r disables escape processing.
No. Python does not have a separate character type. Indexing a string returns another string of length 1. The expression 'hello'[0] returns the string 'h', not a distinct char type.
The str type represents decoded Unicode text for human-readable content. The bytes type represents raw binary data, including encoded text. You convert between them using .encode() on a str and .decode() on a bytes object, specifying an encoding like UTF-8.
Slicing extracts a portion of a string using the syntax string[start:stop:step]. The start index is inclusive and the stop index is exclusive. Omitting start defaults to 0, and omitting stop defaults to the end of the string.
Python does not implicitly convert between types. The + operator cannot join a str and an int because Python cannot guess whether you want text concatenation or arithmetic. Convert the number to a string first with str(), or use an f-string which handles the conversion automatically.
The input() function reads raw text from the keyboard and has no way to know whether the user intended to type a number, a date, or a name. It returns everything as a string, leaving the conversion decision to the programmer. Use int() or float() to convert the result when you need a numeric value.
Use a for loop: for char in my_string: iterates over each character one at a time. If you also need the index of each character, use for i, char in enumerate(my_string): instead.
Call type(variable) to see the type of any value. For strings it returns <class 'str'>. You can also use isinstance(variable, str) which returns True or False and is generally preferred in conditional checks.