Sitemap

Python Strings: Everything You Can Do With Text

7 min read5 days ago

--

Slicing, cleaning, searching, splitting and formatting. Plus the one rule that explains most string bugs.

Press enter or click to view image in full size

Hey again!

Time to settle a debt.

For three posts now, I’ve been sneaking things like .strip(), .title() and .split() into the mini projects and moving on as if they were obvious. In the contact book, the playlist matcher, even the to-do list. Some of you probably copied them, saw that they worked, and quietly wondered what they actually do.

Today we fix that properly.

Text is everywhere in real programs. Usernames, emails, search boxes, file names, messages, web pages. If you can work with strings confidently, a huge number of everyday problems suddenly become easy.

What You’ll Master Today

By the end of this post, you’ll be able to:

  • Slice and index strings (you already know how, you just don’t know it yet)
  • Understand why string methods “don’t work” the first time
  • Clean messy text with strip(), lower() and friends
  • Search inside text with in, find(), count() and replace()
  • Break text apart with split() and glue it back with join()
  • Format numbers and tables neatly with f-strings
  • Build a Text Analyzer

Prerequisites: Everything so far, especially Lists, Loops and Dictionaries.

Part 1: A String Is Just a Sequence

Here’s some good news. You already know most of this.

A string is a sequence of characters, and it behaves a lot like a list. Indexing, negative indexing, slicing, len() and in all work exactly the way they did in the lists post:

word = "Python"

print(word[0])
print(word[-1])
print(word[0:3])
print(word[::-1])
print(len(word))
print("th" in word)

# Output:
# P
# n
# Pyt
# nohtyP
# 6
# True

And you can loop over a string, one character at a time:

for letter in "Hi!":
print(letter)

# Output:
# H
# i
# !

Part 2: The One Rule — Strings Never Change

This is the rule I mentioned in the subtitle. Strings are immutable, just like tuples:

word = "Python"
word[0] = "J"

# TypeError: 'str' object does not support item assignment

Now here’s where beginners get stuck. Look at this:

name = "ajay"
name.upper()
print(name)

# Output:
# ajay

Wait, why is it still lowercase?

Because .upper() can't change the original string. Strings never change. Instead, it returns a new string, and here we threw that new string away.

To keep the result, save it:

name = "ajay"
name = name.upper()
print(name)

# Output:
# AJAY

Burn this into your memory: string methods give you a new string. They never change the old one. Once this clicks, a whole category of “why isn’t my code working?” bugs disappears.

Part 3: Changing Case and Cleaning Up

text = "hello WORLD"

print(text.upper())
print(text.lower())
print(text.title())
print(text.capitalize())

# Output:
# HELLO WORLD
# hello world
# Hello World
# Hello world

lower() is the one you'll use most. It's how you compare text without caring about capitals:

answer = "YES"

if answer.lower() == "yes":
print("Great, let's go!")

# Output:
# Great, let's go!

Removing extra spaces

When people type into a form, they add spaces by accident all the time. strip() removes spaces (and newlines) from both ends:

raw = "   priya@example.com   "

print(f"[{raw}]")
print(f"[{raw.strip()}]")
print(f"[{raw.lstrip()}]")
print(f"[{raw.rstrip()}]")

# Output:
# [ priya@example.com ]
# [priya@example.com]
# [priya@example.com ]
# [ priya@example.com]

I put brackets around the text so you can actually see the spaces. lstrip() cleans only the left side, rstrip() only the right.

Get Ajay Narayan’s stories in your inbox

Join Medium for free to get updates from this writer.

And because each method returns a string, you can chain them. That’s exactly what we did in the contact book:

name = "   aLIce   "
print(name.strip().title())

# Output:
# Alice

Read it left to right: take the name, strip the spaces, then make it title case.

Part 4: Searching Inside Text

email = "priya@example.com"

print("@" in email)
print(email.find("@"))
print(email.find("#"))
print(email.count("e"))
print(email.startswith("priya"))
print(email.endswith(".com"))

# Output:
# True
# 5
# -1
# 2
# True
# True
  • in answers yes or no
  • find() tells you where something is (its index), or -1 if it isn't there
  • count() counts how many times something appears
  • startswith() and endswith() check the beginning and the end

Replacing text

message = "I love Java. Java is great."
new_message = message.replace("Java", "Python")

print(new_message)
print(message)

# Output:
# I love Python. Python is great.
# I love Java. Java is great.

Notice the original message didn't change. Same rule as before: you get a new string back.

Checking what’s inside

These are perfect for validating user input:

print("2026".isdigit())
print("12a".isdigit())
print("Ajay".isalpha())
print("Ajay Narayan".isalpha())

# Output:
# True
# False
# True
# False

That last one is False because a space is not a letter. Small detail, but it will save you one day.

Part 5: Split and Join

split() breaks a string into a list. By default, it splits on spaces:

sentence = "Python is really fun"
words = sentence.split()

print(words)
print(len(words))

# Output:
# ['Python', 'is', 'really', 'fun']
# 4

You can split on anything you like. This is how the playlist matcher read comma-separated songs:

data = "apple,banana,cherry"
fruits = data.split(",")

print(fruits)

# Output:
# ['apple', 'banana', 'cherry']

join() does the opposite. It glues a list of strings back together, with whatever separator you choose:

fruits = ["apple", "banana", "cherry"]

print(", ".join(fruits))
print(" -> ".join(fruits))

# Output:
# apple, banana, cherry
# apple -> banana -> cherry

The syntax looks backwards at first: the separator comes first, then .join(), then the list. Think of it as "use this glue to join these pieces."

Part 6: f-Strings, Properly

You’ve been using f-strings since the variables post. Here’s what else they can do.

Formatting numbers

price = 1234.5
score = 0.875

print(f"{price:.2f}")
print(f"{price:,.2f}")
print(f"{score:.1%}")

# Output:
# 1234.50
# 1,234.50
# 87.5%
  • .2f means "two decimal places"
  • , adds thousands separators
  • .1% turns 0.875 into a percentage with one decimal place

Lining things up

You can give a value a fixed width and choose how to align it. < means left, > means right:

items = [("Coffee", 120), ("Sandwich", 85.5), ("Juice", 60)]

for name, price in items:
print(f"{name:<10}{price:>8.2f}")

# Output:
# Coffee 120.00
# Sandwich 85.50
# Juice 60.00

{name:<10} means "put the name in a space 10 characters wide, aligned left". {price:>8.2f} means "8 characters wide, aligned right, two decimals". Suddenly your terminal output looks like a proper receipt.

Special characters

A backslash inside a string starts a special character:

print("Line one\nLine two")
print("Name:\tAjay")
print("She said \"hello\"")

# Output:
# Line one
# Line two
# Name: Ajay
# She said "hello"

\n is a new line, \t is a tab, and \" lets you put a double quote inside a double-quoted string.

Real-World: Username Checker

Let’s combine a few of these into something you’d find in an actual sign-up form:

def check_username(username):
username = username.strip()
if len(username) < 4:
return "Too short (minimum 4 characters)"
if not username.isalnum():
return "Only letters and numbers allowed"
if username[0].isdigit():
return "Can't start with a number"
return "Looks good!"

print(check_username(" ajay123 "))
print(check_username("aj"))
print(check_username("ajay_n"))
print(check_username("7ajay"))

# Output:
# Looks good!
# Too short (minimum 4 characters)
# Only letters and numbers allowed
# Can't start with a number

isalnum() is new: it checks that every character is a letter or a number. The underscore in "ajay_n" isn't either, so it fails.

Mini Project: Text Analyzer

Paste in any paragraph and get a little report about it. This one uses strings, lists, loops, a dictionary and a function that returns a tuple. Basically, the whole series so far.

def clean_words(text):
words = []
for word in text.lower().split():
word = word.strip(".,!?;:\"'")
if word:
words.append(word)
return words

def most_common(words):
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
best_word, best_count = "", 0
for word, count in counts.items():
if count > best_count:
best_word, best_count = word, count
return best_word, best_count

def main():
print("=" * 40)
print("TEXT ANALYZER")
print("=" * 40)

text = input("Paste some text: ")
words = clean_words(text)
sentences = text.count(".") + text.count("!") + text.count("?")
word, times = most_common(words)
longest = max(words, key=len) if words else ""

print()
print(f"{'Characters:':<16}{len(text):>6}")
print(f"{'Words:':<16}{len(words):>6}")
print(f"{'Sentences:':<16}{sentences:>6}")
print(f"{'Longest word:':<16}{longest:>6}")
print(f"Most used word: '{word}' ({times} times)")

main()

# Example run:
# Paste some text: Python is fun. Python is powerful! Is it hard? No.
#
# Characters: 50
# Words: 10
# Sentences: 4
# Longest word: powerful
# Most used word: 'is' (3 times)

A few things worth noticing:

  • word.strip(".,!?;:\"'") is strip() with an argument. Instead of spaces, it removes any of those punctuation marks from the ends of each word, so "fun." becomes "fun".
  • .lower() before counting means "Is" and "is" count as the same word. That's why "is" wins with 3.
  • max(words, key=len) is a handy shortcut: "give me the item with the biggest length." The if words else "" part just protects us if someone presses Enter without typing anything.

Practice Challenges

Beginner Level

  1. Shout It: Ask for the user’s name and print it in uppercase, reversed, and with its length.
  2. Initials: Ask for a full name like "ajay narayan" and print the initials: A.N.

Intermediate Level

  1. Palindrome Checker: Ask for a word and say whether it’s the same forwards and backwards ("Level" should count, so think about capitals).
  2. Vowel Remover: Ask for a sentence and print it with all the vowels removed. Try it with a loop, then try it with replace().

Advanced Level

  1. Text Analyzer 2.0: Upgrade the mini project to print the top 3 most used words, and to ignore boring words like “the”, “a”, “is” and “and”. (Hint: a set of stop words, and sorted() with key=.)

Before You Go

If strings finally make sense, hit that 👏 clap button.

Run the Text Analyzer on the opening paragraph of your favourite book and tell me in the comments what the most used word was. I’m curious whether it’s always “the”.

Coming up next: Error handling. What happens when someone types “abc” into a program expecting a number? Right now, it crashes. Next time, you’ll learn how to catch errors and keep your program running. Hit Follow so you don’t miss it.

See you in the next post! 🐍

Enjoying this series? Share it with a friend learning Python. Let’s all grow faster, together.

Check out the series so far:

--

--

Ajay Narayan
Ajay Narayan

Written by Ajay Narayan

Just a Python enthusiast sharing what I learn and discover along the way.