from typing import Protocol
class MyObj:
def my_method(self, name: str):
pass
class Proto(Protocol):
def __call__(self, obj: MyObj, name: str):
pass
def my_fn(obj: MyObj, name: str):
pass
def caller(fn: Proto):
fn(MyObj(), 'some name')
caller(my_fn) # passes type check
caller(MyObj.my_method) # fails type check
I'm using mypy 0.971 for type checking. I have trouble understanding why the second call is illegal according to mypy. Is it in fact incorrect according to Python static typing rules?
Interestingly, if I remove the "name" parameter from all the signatures, the type check passes:
from typing import Protocol
class MyObj:
def my_method(self):
pass
class Proto(Protocol):
def __call__(self, obj: MyObj):
pass
def my_fn(obj: MyObj):
pass
def caller(fn: Proto):
fn(MyObj())
caller(my_fn) # passes
caller(MyObj.my_method) # passes
EDIT:
As per @Wombatz explanation, if I modify the protocol to be:
class Proto(Protocol):
def __call__(self, obj: MyObj, /, name: str):
pass
it works, since now the name of the first parameter does not matter since it's required to be called with a positional argument.
The problem is that the Protocol is more restrictive than you think.
class Proto(Protocol):
def __call__(self, obj: MyObj, name: str) -> None:
pass
def incompatible(what: MyObj, name: str) -> None:
pass
The function incompatible
is also not compatible with the protocol, because the protocol requires a callable where the first argument is a MyObj
and its name is obj
and the second argument is a str
and its name is name
.
So in theory, the protocol could be used like this:
def caller(p: Proto) -> None:
p(obj=MyObj(), name="Hello")
This works for my_func
but fails for the method, because the name of the first parameter of the method is self
and not obj
. So mypy is correct here!
You can define your protocol differently to only require a callable with two positional arguments of type MyObj
and str
class Proto(Protocol):
def __call__(self, obj: MyObj, name: str, /) -> None:
pass
Now you cannot use named parameters and thus the method and my incompatible
function are compatible with the protocol.
Interestingly, if I remove the "name" parameter from all the signatures, the type check passes.
I cannot reproduce that. It should fail and it does
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments