Lesson Introduction

Welcome to this lesson on Advanced Typing in Python! Today, we'll explore how to make our Python code more robust and readable using advanced typing features. These features help make code clearer, catch errors early, and improve overall quality.

Ready to dive in? Let's go!

Optional Typing

Sometimes, a function might return a value, or it might return nothing (None). In such cases, we use Optional from the typing module. This makes our intentions clear.

Here’s a function that tries to find a string in a list. If it finds the string, it returns it; if not, it returns None.

The return type Optional[str] shows the function could return a str or None.

Union Typing

Sometimes, a value can be more than one type. For example, a function parameter might be an int or a float. We use Union to handle this.

Here's a function that takes a number, which can be either an int or a float, processes it, and returns a float.

Using Union[int, float] makes it clear the function accepts either type.

Tuple Typing

Another useful typing feature is Tuple. Sometimes, a function needs to return multiple values as a single compound value. This can be done using a Tuple from the typing module.

Here's an example where a function returns a pair of values, a str and an int:

The return type Tuple[str, int] makes it clear that the function returns a tuple containing a str and an int.

Data Structures Typing: List

We often use lists and dictionaries to store collections of data. The typing module lets us specify the types of elements in these collections. Let's see how to use List.

We specify that a list contains elements of a particular type using List. Here's how:

The output will be:

This tells us my_strings is a list of str.

Data Structures Typing: Dict

Similarly, we use Dict to specify the types of keys and values in a dictionary.

This shows fruit_prices is a dictionary with str keys and float values.

The output will be:

You might wonder why we use List and Dict from the typing module when we can just use list and dict directly, such as list[int] or dict[str, int]. The typing module's List and Dict were introduced to provide a more consistent and explicit way of specifying types, especially before Python 3.9, where type hinting for built-in generic collections was not available. While it's essential to follow the best practices for the version of Python you're targeting, it’s generally recommended to use the built-in list and dict for typing when using Python 3.9 or later. For older codebases or when maintaining compatibility with older Python versions, stick with List and Dict from the typing module.

Callable Typing

The Callable type in Python's typing module is used to indicate that a particular argument or return type is a function or another object that can be called with (). The syntax for Callable is Callable[[<arg types>], <return type>], where <arg types> is a list of argument types the function accepts, and <return type> is the type it returns.

Here’s an example where a function accepts another function as an argument and calls it:

In this example, Callable[[str], str] indicates that the greeter argument is a function that takes a single str argument and returns a str. This makes the function signature more understandable and ensures type safety.

Using Callable helps clarify that greeter is expected to be callable, enhancing code readability and preventing type-related errors.

Callable Examples

Let's look at a list of examples showing how to annotate various callables:

  • A function that takes no arguments and returns str: Callable[[], str]
  • A function that takes two int arguments and returns a float: Callable[[int, int], float]
  • A function that takes str and int, and returns a bool: Callable[[str, int], bool]
  • A function that takes int and doesn't return anything: Callable[int, None]
  • A function that takes int and returns an optional int: Callable[int, Optional[int]]
  • A function that takes in another function and returns int: Callable[[Callable[[int], bool]], int]
  • A function that no arguments and returns two values (e.g., a str and an int): Callable[[], Tuple[str, int]]

As you can see, there are a lot of various situations. The key point is that describing a complex type annotation involves combining simple typings together into one nested complex type.

Lesson Summary

Today we covered six advanced typing features in Python:

  1. Optional - Used when a function might return a value or None.
  2. Union - Used when a parameter or return type can be more than one type.
  3. Tuple - Used to specify functions returning multiple values.
  4. List - Specifies the type of elements in a list.
  5. Dict - Specifies the types of keys and values in a dictionary.
  6. Callable - Used when a parameter or return type is an object that can be called with ()

Understanding and using these types makes our code clearer and more robust.

Now it's time for hands-on practice! You'll write functions and see how these advanced typing features work in action. This will solidify your understanding and give you practical experience with these concepts. Happy coding!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal