Tuple[Callable, Any, ...]

Posted on Mon, 29 Jan 2018 in Python

Type hints could help you a lot with a big Python project. However, they sometimes require code refactoring. I wrote about it last year in this article, but I have found a good example for this only now.

Look at this code:

def process(workflow_step):
    func = step[0]
    args = step[1:]
    return func(*args)

What can we get from this piece of code? That workflow_step is a sequence witch first element is a Callable object and the other items, if any, are its arguments. Let's assume that workflow_step is a Tuple. The problem is that the type (Tuple) -> Any for this function is utterly uninformative. Can I call process with an empty tuple? Is (1, 2, 3) OK?

(Tuple[Callable, Any, ...]) -> Any is much better. However, it is not valid. Typing library doesn't allow such syntax. For simple cases, one of the options is to use Union[Tuple[Callable], Tuple[Callable, Any]] or something similar. In any other cases there is the only one option: rewrite this piece of code.

There are plenty of options how to do it, for example, using NamedTuple.

class WorkflowStep(NamedTuple):
    callable  # type: Callable
    args  # type: Tuple

 def process(workflow_step):
    # type: (WorkflowStep) -> Any
    return step.callable(args. args)

Maybe this is not the best piece of code you've ever seen. But no doubts it is much more structured and readable than it was before.

Got a question? Hit me on Twitter: avkorablev