What is it? #
A string is a sequence of characters. Every character has a position, starting at 0 for the first one. That numbering trips people up for about a week and then becomes second nature.
Strings are immutable, which means you cannot change one after it is created. name[0] = "R" is an error. Every operation that looks like it edits a string actually builds a new one and hands it back, leaving the original untouched.
Python gives strings a large set of built-in methods — .strip(), .lower(), .split(), .replace() and friends. You do not need a library for ordinary text work.
Because strings are sequences, they also support slicing: asking for a range of positions in one go. Slicing is used constantly, and once you know the pattern it applies to lists too.
Think of it like this #
Think of a string as a row of numbered lockers, each holding one character. You can read any locker by its number, and you can ask for lockers 3 through 7 as a group. What you cannot do is swap the contents of locker 3 — that row is sealed. If you want a different row, you build a new one.
Simple example #
Someone types their email into a form as " [email protected] ". Before you store it you want the spaces gone, everything lowercase, and the part before the @ on its own. That is three method calls and one split.
Code #
raw = " [email protected] "
email = raw.strip().lower()
print(email) # [email protected]
username, domain = email.split("@")
print(username, "|", domain) # priya.sharma | example.com
# Indexing and slicing
print(email[0]) # p
print(email[-1]) # m (last character)
print(email[:5]) # priya
print(email[-4:]) # .com
# Useful checks
print(email.endswith(".com")) # True
print("@" in email) # True
print(email.replace(".", "_", 1)) # [email protected]
# Strings are immutable
original = "hello"
shouted = original.upper()
print(original, shouted) # hello HELLO
How it works #
raw.strip() returns a new string with whitespace removed from both ends, and .lower() returns another new string in lowercase. Chaining them works because each method hands back a string that the next method can act on.
email.split("@") cuts the string wherever it finds @ and returns a list of the pieces. Because an email has exactly one @, the list has two items, and username, domain = ... unpacks them into two names in one line.
email[0] reads position 0. email[-1] counts backwards from the end, so -1 is the last character. Negative indexing saves you from writing len(email) - 1 everywhere.
email[:5] is a slice: start at the beginning, stop before position 5. The end is always exclusive, which is why [:5] gives you exactly five characters. email[-4:] means "from four before the end, to the end".
.endswith() and the in operator return booleans, so they slot straight into an if. .replace(".", "_", 1) replaces only the first occurrence because of the 1.
The last block is the immutability point made concrete: original is unchanged after .upper(), because .upper() built a new string instead of editing the old one.
Real-world use #
Text cleaning is a constant task in real software. Emails get normalised before they are compared, usernames get trimmed so a trailing space does not create a duplicate account, file names get sanitised before they hit disk, and log lines get split on a delimiter to extract a field.
Slicing shows up whenever you need part of an identifier: the first two letters of a country code, the last four digits of a card, the extension at the end of a file name.
The immutability rule has a performance consequence worth knowing early. Building a large string by repeatedly doing text = text + line creates a fresh copy every time. Collect the pieces in a list and call "".join(pieces) once instead — that is the idiom you will see in production code.
Common mistakes #
- Expecting
.strip()to change the original string. It returns a new one — you have to assign the result. - Reading
s[5]on a shorter string and hitting an IndexError. Slices are forgiving, single indexes are not. - Using
.strip("abc")and expecting it to remove the word "abc". It removes any of those characters from the ends, in any order. - Comparing user text without normalising first.
"Priya" == "priya"is False, which is why you lowercase before comparing. - Building big strings with
+=inside a loop. Use a list and"".join().
Practice #
Take the string " 2026-09-22 | ERROR | payment failed for order 8891 ". Strip it, split it on "|", strip each piece, and print the date, the level and the message on separate lines. Then print just the order number using a slice.