When I run mypy over the following code I see several errors:
from typing import Callable, Type
def class_creator(outside_reference: Callable[[str], None]) -> Type[object]:
class SomeClass():
reference: Callable[[str], None]
def __init__(self) -> None:
self.reference = outside_reference
super().__init__()
def __str__(self):
self.reference("SomeClass instance")
return SomeClass
def callback(string: str) -> None:
print("Prepping: " + string)
instance = class_creator(callback)()
print(instance)
Here are the errors:
test.py:9: error: Cannot assign to a method
test.py:9: error: Invalid self argument "SomeClass" to attribute function "reference" with type "Callable[[str], None]"
test.py:9: error: Incompatible types in assignment (expression has type "Callable[[str], None]", variable has type "Callable[[], None]")
Line #9 is self.reference = outside_reference
.
I'm basically positive that I'm just misunderstanding something, but I just can't see where I'm going wrong.
This is the minimal reproducible reference. If I change the types from Callable[[str], None]
to int
(and don't actually call it), then it runs just fine without showing any errors. It's only when I switch to Callable
that it starts showing these errors.
What should my annotations be here?
Until the issue in https://github.com/python/mypy/issues/708 is fixed, one clean way to work around this is to make the callable attribute optional, and wrap it in a method with an assert:
from typing import Any, Callable, Optional
class SomeClass:
_reference: Optional[Callable[[], Any]]
def reference(self) -> Any:
assert self._reference is not None
return self._reference()
def __init__(self, reference):
self.reference = reference
c = SomeClass(lambda: 42)
print(c.reference())
$ mypy test.py
Success: no issues found in 1 source file
A similar but shorter workaround is to annotate the member with a Union
type, duplicating the Callable
type:
from typing import Callable, Union
class SomeClass:
reference: Union[Callable[[], int], Callable[[], int]]
def __init__(self, reference: Callable[[], int]):
self.reference = reference
c = SomeClass(lambda: 42)
print(c.reference())
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