Python ord(): Getting the Ordinal Value of a Unicode Character

Ordinal values are fun ways to find the numerical representation of characters. These numbers can help translate text between machines, encode data across networks, and maybe even create your own secret language! Python's built-in ord() function makes converting between numbers and characters a breeze!
python ord function overcoded

Python provides a host of built-in utilities for translating between encoded and numerical representations of values, strings, and everything in between. The Python ord function is a built-in utility that, given a single Unicode character, will return its ordinal value.

The term ordinal means countable and in the context of Python’s ord function will return the integer value assigned to a character in the Unicode encoding system. This can be useful when converting between bytes to strings, binary to encoded representations, or sheer hobbyism.

In this article, I will showcase the basics of what the ord function does in Python, why you should care, and some quirky edge cases, and the history behind them.

TL;DR – Use the ord function to get an integer value of a single character.

# Get the ordinal value for the character 'z'
>>> ord('z')
122

Introduction

Ordinal values have been used to map characters to their respective encodings since at least ASCII. Python’s ord function will convert any Unicode character to its numerical representation provided that character is Unicode-compatible. ASCII, for example, maps to the first 127 numbers assigned to the Unicode system. These are the standard English characters, symbols, and integers.

The 0-127 range that maps ASCII characters within the Unicode system corresponds to the ordinal values used in the ASCII system as well. This means ASCII is considered a subset of Unicode. Given ASCII predates the Unicode system it may be appropriate to say Unicode is a superset of ASCII. For this article, I am going to demonstrate the ord function’s utility mostly within the confines of the ASCII ordinal range.

ASCII Examples

For basic usage examples, we’ll take a look at the ASCII characters and how Python’s ord function interprets them.

# Get a string of all ASCII characters
ASCII = "".join(chr(x) for x in range(128))

>>> 	
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Note that ASCII defines some non-printable characters in the first 32 characters and also at the tail-end of the range. See this ASCII table for more info on that. Python’s string library also provides convenient access to only the printable characters:

import string

# The printable ASCII values from the string module
string.printable

>>> 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 	

You might be asking yourself what those 2 funky symbols at the end of the printable ASCII values are—they don’t seem very printable. Here’s where Python’s ord function comes in handy. Let’s use it to find out what those characters are!

# Print the ordinal values of the last two characters
for char in string.printable[-2:]:
    print(char, '-', ord(char))

>>> 
 - 11
 - 12

Using our ASCII lookup table, we note the 11 and 12 values are assigned to the vertical tab (VT) and form feed with new page (NP) characters. Definitely not a revelation worth writing home about but certainly illustrative of the utility of Python’s ord function.

A Note on Unicode

The Unicode system has expanded much since its inception. From the 0-127 range given to ASCII, the system is now in version 13.0. This encompasses everything from international characters, extended character sets, mathematical symbols, and yes—emojis.

For a complete listing of current Unicode symbols check out the official Unicode character code chart page. For now, just know that Unicode allows the possibility of 1,222,998 possible characters, many of which are yet to be reserved. There are currently only 1,114,111 assigned characters. See this post by John D. Cook for more info.

I bore you with Unicode facts because this is the limit of ordinal values of which Python’s ord function is practically useful. In other words—values outside the range of 0-1,114,111 won’t map to anything. This can be displayed via the chr function.

# Maximum Assigned Unicode Value
chr(1114111)
>>> ????

# One value higher
chr(1114111 + 1)

>>> ValueError: chr() arg not in range(0x110000)

Hexadecimal

Integers can become cumbersome for large values or applications such as web use. Hexadecimal values aren’t any easier to remember but offer a more concise representation for many applications making them useful as character representations. Python’s ord function can be applied for hexadecimal interpretation with a little extra syntax—still staying within the bounds of built-in functions. Consider the following:

# Define a variable as the max Unicode value
>>> int('0x110000', 16) - 1
1114111

>>> chr(v)
????

>>> ord(chr(v))
1114111

Here I’ve converted the hexadecimal value 0x11000 (the highest reserved Unicode character) to an integer value (its ordinal value), used the ord operator to print the Unicode character (it’s not actually a character), then used the ord operator to wrap the chr value and re-convert to the integer. Busywork? Yes. Illustrative of the interplay of Unicode, ordinal, and hexadecimal values? Hopefully.

Note: Check out our article on how to convert binary to hexadecimal in Python for some more info on these types of functions.

Final Thoughts

Python’s ord function isn’t something that I often use. More times than not, I fall back to it when debugging display issues. It’s useful in finding which character is causing all one’s encoding nightmares! This article was intended to help introduce the ord function and its basic operations in Python, the basic concept of ordinal values in encoding, and hopefully present a use-case interesting enough to help the reader remember the basics. Python’s ord function provides the low-level utility that continues to make it one of the most popular programming languages for developers of all skill levels.

Zαck West
Full-Stack Software Engineer with 10+ years of experience. Expertise in developing distributed systems, implementing object-oriented models with a focus on semantic clarity, driving development with TDD, enhancing interfaces through thoughtful visual design, and developing deep learning agents.