Case Conversion

Concepts covered: String Methods

A string carries a set of built-in operations called methods. You call one by putting a dot after the string and then the method name with parentheses, the same way you call a function you defined with def, except the string comes first. name.upper() asks the string in name for a copy of itself with every letter in capitals. The 5 case methods below are the ones you will use most.

Call on "hello World"ResultRule
upper()HELLO WORLDevery letter to capitals
lower()hello worldevery letter to small
capitalize()Hello worldfirst character up, the rest down
title()Hello Worldfirst letter of each word up, the rest down
swapcase()HELLO wORLDeach letter flipped

The original string does not change

A method returns a new string and leaves the one it was called on as it was. If you want the converted text, store the result: shout = name.upper(). Calling name.upper() on a line by itself computes the capitals and throws them away, which is the most common mistake with these methods.

name = "ada"
shout = name.upper()
print(name)
print(shout)
ada
ADA

After the second line runs, name still prints ada and shout prints ADA. To change what name holds, assign back to it: name = name.upper(), the same shape as growing a string with +.

Comparing without caring about case

Text typed by people arrives in whatever case they felt like: Yes, yes, YES. Comparing with == would need a branch per spelling. Lowercasing both sides first collapses them to one spelling, so a single comparison handles them all. The function below returns a boolean, so an if statement can use it directly.

def is_yes(answer):
    """Return True when answer means yes in any casing."""
    return answer.lower() == "yes"

print(is_yes("YES"))
print(is_yes("yes"))
print(is_yes("Yep"))

Output:

True
True
False

Matching keys from 2 systems

The same trick joins records whose keys were typed by different teams. A warehouse table might store OSLO while a partner's export says Oslo. Lowering both before the comparison, or upper-casing both, makes the match succeed without changing either source.

def same_city(a, b):
    """Return True when a and b name the same city, ignoring case."""
    return a.upper() == b.upper()

print(same_city("OSLO", "Oslo"))
print(same_city("Lima", "Lisbon"))

Output:

True
False

Letters only

Only letters have case, so the methods pass every other character through unchanged. title() decides where a word starts by looking for a character that isn't a letter, which gives a surprise on text like 3rd street: the r after the digit is treated as the start of a word and gets capitalized.

print("r2-d2".upper())
print("ORDER #42".lower())
print("3rd street".title())
print("o'neil".title())

Output:

R2-D2
order #42
3Rd Street
O'Neil

What does this program print?

tag = "Draft v2"
tag.upper()
label = tag.lower()
print(tag)
print(label)

Keeping the converted value

To keep a conversion, put the method call on the right of an =. Assigning to a new name keeps both versions, and assigning back to the same name replaces the old text, which is what you want when the original casing has no further use. The program below calls title() twice: once on a line by itself and once in an assignment.

city = "lima"
city.title()
print(city)
city = city.title()
print(city)

Output:

lima
Lima

The first print shows lima because the result of the bare call was discarded. The second shows Lima because city now names the new string. A conversion that appears to do nothing is almost always a call whose result nobody stored.

About this lesson

This section is part of the Strings: Beginner lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.