Union designed specifically for this situation. It creates a new type, which can be any of the types you specify:
from typing import Union, List def my_function(list_arg: Union[List[str], List[int]]) -> None: ...
If you use it often, create an alias like:
MyList = Union[List[str], List[int]] def my_function(list_arg: MyList) -> None: ...
I would not recommend using a generic function as the @ user6269244 answer, unless you need it for some specific reason. Although T = TypeVar('T', int, str) will work in the simple case, it will be more restrictive.
For example, suppose you have something like this:
def apply_my_function(list_of_lists: List[MyList]) -> None:
You do not have chioce in this code: you need Union ( List[List[T]] will not allow you to store both the int list and the str list, because T cannot switch between str and int in the same expression).
But since you are using Union in the code that calls my_function , you will also need to use Union in the signature of my_function itself.
In addition, generics increase the complexity of types, and at some point you will encounter limitations of the type system. Therefore, it is better to reserve generics for cases when you really need them, for example, if you want the return type my_function depend on the type of the argument:
T = TypeVar("T", int, str)