Reputation: 11
I'm not quite sure why mypy is returning the Signature of "foo" is incompatible with supertype "Base"
error here. The return types and the argument types seem to match up.
from typing import NoReturn, Union
class Base():
def foo(self, *args: str) -> Union[NoReturn, str]:
raise NotImplementedError
class A(Base):
def foo(self, x: str) -> str:
return x
Any help is greatly appreciated, thank you!
EDIT
I changed up A.foo
to this:
def foo(self, *args: str) -> str:
x = args[0]
return x
Now the mypy error disappeared. However, with this implementation, wouldn't the same issue occur where if there's a NoReturn
in Base
, the overridden function can only return str
?
Upvotes: 1
Views: 2705
Reputation: 10075
Without your EDIT, you have the issue described by @Skam: https://stackoverflow.com/a/55071593/369009
With the EDIT, everything is fine. Think about this code:
bs: Base = A() # bs is of type Base
return_value = bs.foo('test') # Return value is of type `Union[NoReturn, str]`
When calling bs.foo
, we expet the return value to be either a NoReturn
or a str
. A
always returns a str
, but this is fine, since a str
is also part of the Union[NoReturn, str]
, so this is always valid. Anyone calling foo
on the base class has to handle both return types, and A
just happens to always return only a str
and never a NoReturn
.
Only if it were the other way around it would be an issue:
Assuming A
would return the Union
and Base
would return a str
, then callers of Base.foo
might suddendly get a NoReturn
when they expected only a str
.
Upvotes: 1
Reputation: 7808
The difference is a little subtle. So I'll explain what each does
def foo(self, *args: str) -> Union[NoReturn, str]:
foo
is an instance method of the class Base
that takes a variable amount of string arguments and returns either NoReturn
or a str
.
def foo(self, x: str) -> str:
foo
is an instance method of the class A
that overrides the definition of foo
in the Base
class. It takes a single str
argument and returns a single str
What this means is I could call the Base
version like foo('bar', 'baz')
but the same call in A
would throw an error.
Similarly, I can have no return in Base
while the overridden function call only returns str
The issue with this here is that the function has different behavior and type but the same name, which is misleading.
Upvotes: 1