Reputation: 1848
Greatings, consider the following code.
from abc import ABC, abstractmethod
class Interface(ABC):
@abstractmethod
def method(self) -> None:
pass
class A(Interface):
def method(self) -> None:
pass
class B(Interface):
def method(self) -> None:
pass
mapping = {'A': A, 'B': B}
# does NOT pass mypy checks
def create_map(param: str) -> Interface:
if param in mapping:
return mapping[param]()
else:
raise NotImplementedError()
# passes mypy checks
def create_if(param: str) -> Interface:
if param == 'A':
return A()
elif param == 'B':
return B()
else:
raise NotImplementedError()
For some reason, create_if
passes all mypy
type checking, but create_map
does not. The reveal_type
for both functions is 'def (param: builtins.str) -> test.Interface'
.
The error I get is the same as if I were trying to instantiate an abstract class directly, which is weird considering this reference for mypy.
error: Cannot instantiate abstract class 'Interface' with abstract attribute 'method'
Also, if I make mapping = {'A': A}
(i.e. remove 'B': B
) now create_map
also passes.
Can someone shed some light on this?
Upvotes: 5
Views: 4718
Reputation: 1848
Apparently all I was missing was the type annotation for the mapping.
mapping: Mapping[str, Type[Interface]] = {'A': A, 'B': B}
Thanks @jonafato
Credit to mypy issues 1843 and 3048 for showing this syntax.
Upvotes: 15