Programming tips for everyone

# Python Range of Letters To produce a range of letters (characters) in Python, you have to write a custom function that:

1. Takes start and end characters as input.
2. Converts start and end to numbers using ord() function.
3. Generates a range of numbers between start and end.
4. Converts the numbers back to characters.
5. Yields the characters.

Here is the code:

```# Character range function
def range_char(start, stop):
return (chr(n) for n in range(ord(start), ord(stop) + 1))

# Example run
for character in range_char("a", "g"):
print(character)```

Output:

```a
b
c
d
e
f
g```

This is the quick answer. Feel free to use this code in your project.

However, to understand how it works, let’s build this function from scratch step by step.

## How Does Range of Characters Function Work in Python

Let’s take a look at how the above code works. We are going to build the above function piece by piece by going through the key principles that make it work.

To follow along, you should be an intermediate/advanced Python programmer. For beginners, I recommend skipping the generator part at the end.

### The ord() Function in Python

In Python, each Unicode character, such as “a”, “b”, or “c” is an integer under the hood.

For example, here is the Unicode table for the English alphabet.

In Python, you can check the integer value of any character using the built-in ord() function.

For instance, let’s check Unicode values for “a”, “b”, and “c”:

```ord("a") # 97
ord("b") # 98
ord("c") # 99```

As you can see, this returns the same values that are present in the Unicode table above.

### The chr() Function in Python

In Python, you can turn (some) integers into characters.

This is natural because as you learned, each character is a number under the hood.

In Python, there is a built-in chr() function. This converts an integer to a corresponding character value.

For instance, let’s turn numbers 110, 111, and 112 into characters:

```print(chr(110))
print(chr(111))
print(chr(112))```

Output:

```n
o
p```

Now you understand how to convert a character into an integer, and an integer back to a character.

This brings us to a key point related to the range of characters in Python: A range of characters is actually generated using a range of numbers. It is possible only because we know how to convert characters to integers and vice versa.

For example, you can create a range of characters using the built-in range() function and the ord() function:

```for number in range(ord("a"), ord("h")):
print(number)```

Output:

```97
98
99
100
101
102
103```

If you want to convert these numbers back to characters, call the chr() function on the numeric values:

```for number in range(ord("a"), ord("h")):
print(chr(number))```

Output:

```a
b
c
d
e
f
g```

### Inclusive Range

Now you already have a naive implementation for a range of characters in Python.

But in the above example, the range ends at “g” even though it should end at “h”. This is due to the exclusive nature of the range() function, that is, the last value is not included in the range.

To fix this, add 1 to the end of the range. In other words, extend the range by one to include the “last” value.

For example, let’s create a range of characters from “a” to “h” such that the “h” is included:

```for number in range(ord("a"), ord("h") + 1):
print(chr(number))```

Output:

```a
b
c
d
e
f
g
h```

### Convert the For Loop into a Function

Now you have a simple for loop that prints characters from “a” to “h”.

But you obviously want to be more general.

Let’s use the logic from the previous example to create a function that returns a range of characters as a list. Instead of hard-coding the strings “a” and “h”, let’s make the function accept general inputs start and stop:

```def range_char_list(start, stop):
result = []
for number in range(ord(start), ord(stop) + 1):
result.append(chr(number))
return result```

Now let’s call this function to create a list of characters between “a” and “l”:

```a_to_l = range_char_list("a", "l")
print(a_to_l)```

Output:

`['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']`

And there is your naive implementation for the character range function.

Meanwhile, this approach already meets your demand, let’s take it a step further by using generators.

### Generator Approach

So far you have implemented an inclusive character range as a function that returns a list of characters.

However, this function stores all the characters into a list in memory. But do we really need to store them?

Nope.

The characters are independent of one another. That is, the value of “a” does not depend on the value of “b” or any other character in the range.

This means you may use a generator instead of a function to generate the range. In other words, you do not store the entire sequence of characters. Instead, you generate them one at a time with a generator function.

If you are unfamiliar with generators, feel free to check this article.

In short, a generator function does not return values. Instead, it gives you an iterator object that yields values one at a time without storing them. This saves memory when the sequence of items is big in size. The best part of generators is they allow a loop-like syntax. This makes it look as if the generator stored the values even if it does not.

Let’s convert the range of characters function into a generator:

```def range_char(start, stop):
for number in range(ord(start), ord(stop) + 1):
yield(chr(number))```

This generator yields the characters one at a time.

As mentioned, you can use this generator in a for loop just like you would do with any other iterable in Python.

```for character in range_char("a", "h"):
print(character)```

Output:

```a
b
c
d
e
f
g
h```

Cool, we are almost there!

### Generator Expression

To complete the implementation of the range of characters, let’s make a small final tweak into the function.

Similar to list comprehensions, Python generators support generator comprehensions (known as generator expressions). This allows you to compress the implementation of a generator into a one-liner shorthand.

The general syntax for a generator expression is:

`( operate(value) for value in sequence if condition )`

This expression is equivalent to calling this generator:

```def generate():
for value in sequence:
if condition:
yield operate(value)```

As you can see, you save some lines of code and do not need to use the yield statement at all. Sometimes this can make the code more readable and improve the code quality.

Let’s apply this knowledge to our generator that generates the range of characters.

This turns the existing generator:

```def range_char(start, stop):
for number in range(ord(start), ord(stop) + 1):
yield(chr(number))```

Into a shorthand version of it:

```def range_char(start, stop):
return (chr(n) for n in range(ord(start), ord(stop) + 1))```

Do not let the return statement confuse you here. This function still returns an iterator that yields the characters in the range one at a time.

If the generator part sounds Gibberish to you, please familiarize yourself with generators. It takes a while to wrap your head around them.

Also, keep in mind this last part is optional. It is up to a debate whether the shorthand actually improved the code quality or not.

Anyway, this is a necessary step to make the example complete.

## Conclusion

Today you learned how to produce a range of letters in Python.

• You started with a hard-coded range of characters using a for loop.
• Then you created an inclusive range of characters that includes the last character.
• Then you wrote a function that returns a range of characters as a list.
• Finally, you turned this function into a memory-friendly generator.

To recap the idea behind the range of characters in Python:

• Express characters as integers.
• Create a range of integers.
• Convert the range of integers back to characters.