Let us assume that we need a function that accepts two arguments of any type as long as both arguments have the same type. How would you check it statically with mypy?
If we only need the function to accept some finite amount of already known types, it is easy:
from typing import TypeVar, List, Callable
T = TypeVar('T', int, str, List[int], Callable[[], int])
def f(a: T, b: T) -> None:
pass
f(1, 2)
f("1", "2")
f([1], [2])
f(lambda: 1, lambda: 2)
f(1, "2") # mypy will print an error message
For this code, mypy can ensure that the arguments to f
are either two int
s or two str
s or two lists of int
s or two functions of zero arguments that return int
.
But what if we don't know the types in advance? What if we need something similar to let f (a:'t) (b:'t) = ()
from F# and OCaml? Simply writing T = TypeVar('T')
would make things like f(1, "2")
valid, and this is not what we want.
There are two ways to pass parameters in C: Pass by Value, Pass by Reference.
5 Types of Arguments in Python Function Definition: keyword arguments. positional arguments. arbitrary positional arguments. arbitrary keyword arguments.
Hence, we conclude that Python Function Arguments and its three types of arguments to functions. These are- default, keyword, and arbitrary arguments.
Specify a Variable Type There may be times when you want to specify a type on to a variable. This can be done with casting. Python is an object-orientated language, and as such it uses classes to define data types, including its primitive types.
What you're asking for is impossible (see below for explanation). But usually, there's no need in python to require that two arguments have precisely identical type.
In your example, int
, str
, List[int]
, Callable[[], int]
don't have any common methods or attributes (other than what any two object
instances have), so unless you manually check the type with isinstance
, you can't really do anything with your argument that you couldn't do with object
instances. Could you explain your use case?
Mypy type system has subtyping. So when you write f(a, b)
, mypy only checks that types of a
and b
are both subtypes of T
rather than precisely equal to T
.
In addition mypy subtyping system is mostly pre-defined and not under the programmer control, in particular every type is a subtype of object
. (IIUC, in OCaml the programmer needs to say explicitly which types should be in a subtyping relationship, so by default every type constraint is equality constraint. That's why you could do what you wanted in OCaml).
So, when you write
T = TypeVar('T')
f(a: T, b: T) -> None: ...
f(x, y)
you are only telling mypy that the types of x
and y
must be subtypes of some common type T
. And of course, this constraint is always (trivially) satisfied by inferring that T
is object
.
Update
To your question in the comment (is it possible to ensure that type of y
is of subtype of type of x
?), the answer is also no.
Even though mypy
allows a type variable to be bounded from above by a specified type, that bound cannot be another type variable, so this won't work:
T = TypeVar('T')
U = TypeVar('U', bound=T, contravariant=True) # error, T not valid here
f(x: T, y: U) -> None
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With