How to Capitalize a String in Python: Upper(), Capitalize(), And More

How to Capitalize a String in Python Featured Image

Today, we’ll be looking at how to capitalize a string in Python. There are a few built-in functions for this problem, but we can also roll our own solution.

In short, the capitalize() method exists for this purpose. That said, if you need something a bit different than what this method provides (e.g. only capitalizing the first letter), then you might need to roll your own solution.

That said, if you’re looking for a bit more of a description, keep reading.

Table of Contents

Video Summary

Like many of the articles in this series, I like to provide a nice video summary for folks who prefer that method of learning. Often the most up to date information can be found in the article, but you’ll still find everything you’ll need in the video above.

Problem Description

When it comes to manipulating strings, a common task that we might want to do is capitalize a string (i.e. convert the first character from lowercase to uppercase). Unfortunately, strings are pretty complex because they can support a huge variety of symbols from letters and numbers to punctuation. Also, let’s not forget that strings can support emojis and characters from languages other than English. Hell, even whitespace has to be encoded somehow.

This complexity brings about a lot of challenges when it comes to string manipulation. As a result, today’s task of capitalization is going to require a few assumptions.

First, when we capitalize a string, we’re only going to concern ourselves with the first character of the string. In other words, we’re not going to try to deal with capitalizing multiple words in a sentence or anything like that.

Second, when we work with strings, the only characters we’re going to concern ourselves with are uppercase and lowercase letters in English. Specifically, these sets of characters:

lowercase = "abcdefghijklmnopqrstuvwxyz"
uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

As we’ll see in the solutions below, Python has a function that can perform capitalization for us, but it doesn’t quite adhere to these rules. That said, I’ll share it for the sake of completeness.

Solutions

As always, I like to kick off the list of solutions with a few brute force solutions. Don’t worry! We’ll get to the functions that are already built into Python. Feel free to jump ahead as needed.

Capitalize a String Using ASCII Values

While Python has a capitalize functionality built into the string class, the traditional way to do this would be to leverage the underlying numerical values of each character. If you aren’t already aware, characters are actually integers, and we can access those values using the ord() function:

>>> ord('s')
115

Now unfortunately, strings are pretty ugly to work with in this state because not every character can be “capitalized.” In other words, what’s the capital version of the number “2” or the symbol “&”?

As a result, there’s a very small range of values we should be concerned about: all the lowercase letters. Fortunately, their numerical values are all adjacent and in alphabetical order:

>>> ord('a')
97
>>> ord('b')
98
>>> ord('y')
121
>>> ord('z')
122

In other words, we can determine if a character is lowercase by checking if its numerical value is between 97 and 122:

if 97 <= ord(character) <= 122: # do something

Then, it’s a matter of mapping the result back to the set of uppercase letters. To do this, we can take advantage of the fact that all of the numerical values of the uppercase letters are also adjacent and in alphabetical order:

>>> ord('A')
65
>>> ord('B')
66
>>> ord('Y')
89
>>> ord('Z')
90
>>> 'a' - 'z'

In this case, the range begins at 65 and ends at 90. As a result, we should be able to subtract the distance between these sets (i.e. 97 – 65 = 32) to map the lowercase letters into the uppercase domain:

if 97 <= ord(character) <= 122:
  shift = ord(character) - 32 

Once we have the character in the proper domain, it’s a matter of using the chr() function to convert the integer to the appropriate character:

if 97 <= ord(character) <= 122:
  shift = ord(character) - 32 
  uppercase = chr(shift)

Now, this will form the core logic of our homemade capitalize function. All that’s left is to extract the first character of the input string, run it through our logic, and return the updated string.

def capitalize(string):
  character = string[0]
  if 97 <= ord(character) <= 122:
    shift = ord(character) - 32 
    uppercase = chr(shift)
    return uppercase + string[1:]
  return string

As we can see, the updated string was constructed from the uppercase character and a slice of the string excluding the first character. If the first character is not a lowercase letter, we return the original string as-is.

Now that we have a capitalize function, here’s what it looks like in action:

>>> capitalize("hello world")
'Hello world'
>>> capitalize("Hello world")
'Hello world'

Of course, there are definitely better ways to get this done!

Capitalize a String Using Alphabet Strings

On the off chance that you didn’t know about the numeric values for characters, no worries! There’s another way to roll our own capitalize function. All we have to do is create a pair of strings, one for lowercase letters and another for uppercase letters:

lowercase = "abcdefghijklmnopqrstuvwxyz"
uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

Now, instead of checking if the first character of the string is in the range of lowercase letters, we can check if it is contained in the lowercase string:

if character in lowercase: # do something

Personally, I like how this reads but to each their own. Anyway, the next step is to map the lowercase character to the uppercase domain. To do that, we need to find the index of the lowercase character in the lowercase string (careful not to get an IndexError):

if character in lowercase:
  i = lowercase.index(character)

One quick optimization we can make is to use the find() method instead. That way, we can check if the character is in the set of lowercase characters and get its index at the same time:

i = lowercase.find(character)

If the return value is -1, we know that the letter is not lowercase. In that case, we can return the original string. Otherwise, we can build our capitalized strings.

To do that, we can take the index we got using find() and plug it into the uppercase string. The result should be the uppercase version of our letter. Then, we rinse and repeat the slice code from above:

i = lowercase.find(character)
uppercase[i] + string[1:]

With all the logic out of the way, all that’s left is to put together the function:

def capitalize(string):
  lowercase = "abcdefghijklmnopqrstuvwxyz"
  uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  character = string[0]
  i = lowercase.find(character)
  return string if i == -1 else uppercase[i] + string[1:]

To limit indentation, we use a ternary operator in the return statement. That said, it’s perfectly acceptable to explicitly write out the if statements.

Regardless, here’s what this function looks like in action:

>>> capitalize("hello world")
'Hello world'
>>> capitalize("Hello world")
'Hello world'

Again, this isn’t the best way to go about capitalizing a string. That said, if you needed to roll your own string manipulation function, both of the functions up to this point might serve as a good start.

Capitalize a String Using Built-in Upper Method

In Python, there are two core capitalization methods: upper() and capitalize(). Neither of these methods really gives us the simplified behavior provided in the problem description, but the upper() method can be used to give us what we want.

Typically, the upper() method is used to uppercase every character in a string:

>>> string = "how now brown cow"
>>> string.upper()
'HOW NOW BROWN COW'

That said, it’s pretty easy to use the same style of slice code from before to implement a capitalize function:

def capitalize(string):
  character = string[0]
  return character.upper() + string[1:]

In other words, we can grab the first character, call upper() on it, and concatenate it with the rest of the original string. In this case, upper() is basically providing all of the lowercase checking logic from our previous solutions—albeit in a more sophisticated way to handle all cased characters.

Naturally, here’s what that looks like in action:

>>> capitalize("hello world")
'Hello world'
>>> capitalize("Hello world")
'Hello world'

Up next, we’ll take a look at the capitalize() method.

Capitalize a String Using Built-in Capitalize Method

Finally, Python comes equipped with the capitalize() method right out of the box. Unfortunately, it doesn’t quite adhere to our requirements because it does a bit more than just capitalize the first character of a string. In addition, it converts all other characters to lowercase. Likewise, it likely handles characters beyond the set we’ve defined. That said, I figured I’d share it for completeness.

Since the capitalize() method works out of the box, there’s not much we need to do but call it. Of course, since it’s a method, it works a bit differently than the functions we’ve defined above. In particular, this method has to be called on an existing instance of a string:

>>> "hello world".capitalize()
'Hello world'
>>> "Hello world".capitalize()
'Hello world'

Also, it’s probably worth demonstrating a string or two with capital letters throughout:

>>> "Hello WoRlD".capitalize()
'Hello world'

Notice how the capitalize method takes care of characters that are capitalized throughout. This is not the behavior of the functions we created previously. That said, if you don’t mind, this is probably the method for you.

Performance

With the solutions out of the way, let’s talk performance. In my experience, the methods provided by Python are almost always significantly faster than anything we can write ourselves. That said, it’s worth taking a look at how our custom solutions fair.

To do that, we’ll be using the timeit package. If you want to learn more about this package and how it’s used, check out my article on performance testing. Otherwise, let’s start by storing our solutions in strings.

setup = """
input = "test string"

def capitalize_ascii(string):
  character = string[0]
  if 97 <= ord(character) <= 122:
    shift = ord(character) - 32 
    uppercase = chr(shift)
    return uppercase + string[1:]
  return string

def capitalize_alphabet(string):
  lowercase = "abcdefghijklmnopqrstuvwxyz"
  uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  character = string[0]
  i = lowercase.find(character)
  return string if i == -1 else uppercase[i] + string[1:]

def capitalize_upper(string):
  character = string[0]
  return character.upper() + string[1:]
"""

capitalize_by_hand = """
captalize_ascii(input)
"""

capitalize_by_mapping = """
capitalize_alphabet(input)
"""

capitalize_with_upper = """
capitalize_upper(input)
"""

capitalize = """
input.capitalize()
"""

Alright, that was a bit long, but we’re now ready to begin testing. Here’s what that looks like:

>>> import timeit
>>> min(timeit.repeat(setup=setup, stmt=capitalize_by_hand))
0.30442010000001574
>>> min(timeit.repeat(setup=setup, stmt=capitalize_by_mapping))
0.34245180000004893
>>> min(timeit.repeat(setup=setup, stmt=capitalize_with_upper))
0.21950409999999465
>>> min(timeit.repeat(setup=setup, stmt=capitalize))
0.11746000000005097

For the sake of completeness, I like to run these sort of tests with larger strings despite all of our solutions running in constant time. In this case, I updated input as follows:

input = "abc" * 100

Despite our solutions running in constant time, the built-in capitalize() certainly does not. Here’s the consequence:

>>> min(timeit.repeat(setup=setup, stmt=capitalize_by_hand))
0.33476870000004055
>>> min(timeit.repeat(setup=setup, stmt=capitalize_by_mapping))
0.36098470000001726
>>> 
>>> min(timeit.repeat(setup=setup, stmt=capitalize_with_upper))
0.2651783000000023
>>> min(timeit.repeat(setup=setup, stmt=capitalize))
1.7041871000000128

Despite how much faster the built-in method is for small strings, it doesn’t scale too well. Of course, that makes sense, right? It’s changing all the characters in the string, so it probably runs in linear time. In general, however, all solutions seem to be pretty fast, so take your pick!

More recently, I’ve been visualizing the testing you’ve seen above through the How to Python repoOpens in a new tab.. Here’s the same sort of findings visualized:

Comparing Python Capitalization Function Performance

With that said, let’s move on to the challenge.

Challenge

For today’s challenge, I had a really fun idea that I might turn into a series. Given how different the capitalize() method is from our solutions, I wonder how hard it would be to duplicate some of the behavior. For example, could you write your own version of the capitalize method that follows the method description?

Return a copy of the string with its first character capitalized and the rest lowercased.

Source: Python DocumentationOpens in a new tab.

As always, I’ll kick things off with a solution of my own:

If you’d like to share a solution, feel free to use #RenegadePythonOpens in a new tab. on Twitter, and I’ll give it a share!

A Little Recap

Welp, that’s it for today! As always, here’s the list of solutions in one convenient place:

# A capitalize function leveraging character values
def capitalize_ascii(string):
  character = string[0]
  if 97 <= ord(character) <= 122:
    shift = ord(character) - 32 
    uppercase = chr(shift)
    return uppercase + string[1:]
  return string

# A capitalize function leveraging alphabet strings
def capitalize_alphabet(string):
  lowercase = "abcdefghijklmnopqrstuvwxyz"
  uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  character = string[0]
  i = lowercase.find(character)
  return string if i == -1 else uppercase[i] + string[1:]

# A capitalize function leveraging the upper method
def capitalize_upper(string):
  character = string[0]
  return character.upper() + string[1:]

# The built-in capitalize method
str.capitalize()

Otherwise, thanks again for checking out the site. If you’d like to become part of the community, check out my list of ways to grow the site. There you’ll find links to Patreon and Discord.

In addition, you can support the site by checking out these related articles:

Likewise, here are a few python resources from the folks at Amazon (#ad):

Once again, thanks for stopping by. I hope this article was helpful!

How to Python (42 Articles)—Series Navigation

The How to Python tutorial series strays from the usual in-depth coding articles by exploring byte-sized problems in Python. In this series, students will dive into unique topics such as How to Invert a Dictionary, How to Sum Elements of Two Lists, and How to Check if a File Exists.

Each problem is explored from the naive approach to the ideal solution. Occasionally, there’ll be some just-for-fun solutions too. At the end of every article, you’ll find a recap full of code snippets for your own use. Don’t be afraid to take what you need!

If you’re not sure where to start, I recommend checking out our list of Python Code Snippets for Everyday Problems. In addition, you can find some of the snippets in a Jupyter notebook format on GitHubOpens in a new tab.,

If you have a problem of your own, feel free to ask. Someone else probably has the same problem. Enjoy How to Python!

Jeremy Grifski

Jeremy grew up in a small town where he enjoyed playing soccer and video games, practicing taekwondo, and trading Pokémon cards. Once out of the nest, he pursued a Bachelors in Computer Engineering with a minor in Game Design. After college, he spent about two years writing software for a major engineering company. Then, he earned a master's in Computer Science and Engineering. Today, he pursues a PhD in Engineering Education in order to ultimately land a teaching gig. In his spare time, Jeremy enjoys spending time with his wife and kid, playing Overwatch 2, Lethal Company, and Baldur's Gate 3, reading manga, watching Penguins hockey, and traveling the world.

Recent Code Posts