How to annotate the type of a list of functions with different output type in Python

57 views Asked by At

The following try_parse method takes as input a value of type T and a series of functions with input type T. The functions do not necessarily have to have the same output type, e.g., it could be int, float, MyCustomClass etc. How would I appropriately annotate the function type in this code?

T = TypeVar("T")
U = TypeVar("U")

def try_parse(value: T, *parse_functions: Callable[[T], U]) -> U:
    for parse_function in parse_functions:
        try:
            return parse_function(value)
        except ValueError:
            pass
    raise ValueError(f"Cannot parse {value} with any of {parse_functions}")
1

There are 1 answers

3
Robert Long On

One way to annotate your try_parse method, assuming you want to keep the code flexible but still benefit from type checking to some extent, is to type parse_functions as a sequence of callables where each callable takes an input of type T and returns a value of type Any. This approach sacrifices some type specificity for flexibility:

from typing import TypeVar, Callable, Any

T = TypeVar("T")

def try_parse(value: T, *parse_functions: Callable[[T], Any]) -> Any:
    for parse_function in parse_functions:
        try:
            return parse_function(value)
        except ValueError:
            pass
    raise ValueError(f"Cannot parse {value} with any of {parse_functions}")

Any is used for the return type of parse_functions and the return type of try_parse itself, indicating that the function can return any type, which aligns with your requirement that parse_functions could have varying output types. While this approach reduces the benefits of static type checking by introducing Any, it reflects the dynamic nature of your try_parse function more accurately.

If you're working in a context where you can guarantee that all functions in parse_functions will return the same type, or if you're okay with enforcing that constraint, you could stick with the original annotation using U as the return type. However, based on your description, it seems like using Any is closer to your intention for this function.