Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to specify a conditional type hint in Python?

Suppose the following code:

from typing import Union


def invert(value: Union[str, int]) -> Union[int, str]:
    if isinstance(value, str):
        return int(value)
    elif isinstance(value, int):
        return str(value)
    else:
        raise ValueError("value must be 'int' or 'str'")

It is easily seen that a str input leads to an int output and vice versa. Is there a way to specify the return type so that it encodes this inverse relationship?

like image 944
Leandro Lima Avatar asked May 29 '17 02:05

Leandro Lima


People also ask

How do you give a hint in Python?

Here's how you can add type hints to our function: Add a colon and a data type after each function parameter. Add an arrow ( -> ) and a data type after the function to specify the return data type.

How do you write a hint class in Python?

In a type hint, if we specify a type (class), then we mark the variable as containing an instance of that type. To specify that a variable instead contains a type, we need to use type[Cls] (or the old syntax typing. Type ).

Does Python check type hints?

Python will always remain a dynamically typed language. However, PEP 484 introduced type hints, which make it possible to also do static type checking of Python code. Unlike how types work in most other statically typed languages, type hints by themselves don't cause Python to enforce types.

Are type hints enforced?

They are used to add types to variables, parameters, function arguments as well as their return values, class attributes, and methods. Adding type hints has no runtime effect: these are only hints and are not enforced on their own. If you worry about them, do remember that the interpreter always ignores them.


1 Answers

There isn't really a natural way to specify a conditional type hint in Python at the moment.

That said, in your particular case, you can use @overload to express what you're trying to do:

from typing import overload, Union

# Body of overloads must be empty

@overload
def invert(value: str) -> int: ...

@overload
def invert(value: int) -> str: ...

# Implementation goes last, without an overload.
# Adding type hints here are optional -- if they
# exist, the function body is checked against the
# provided hints.
def invert(value: Union[int, str]) -> Union[int, str]:
    if isinstance(value, str):
        return int(value)
    elif isinstance(value, int):
        return str(value)
    else:
        raise ValueError("value must be 'int' or 'str'")
like image 54
Michael0x2a Avatar answered Oct 11 '22 18:10

Michael0x2a