Here's a minimal example I've written:
from __future__ import annotations
from typing import Protocol
from typing_extensions import Self
class Cat(Protocol):
def add(self, other: Self) -> Self:
...
def sub(self, other: Self) -> Self:
...
class FancyCat(Cat):
def __init__(self, value: int):
self._value = value
def add(self, other: Self) -> Self:
return FancyCat(self._value + other._value)
def sub(self, other: Self) -> Self:
return FancyCat(self._value - other._value)
fc = FancyCat(3)
fc2 = FancyCat(4)
fc.add(fc2)
If I try to type check it, I get
$ mypy t.py
t.py:19: error: Incompatible return value type (got "FancyCat", expected "Self") [return-value]
t.py:22: error: Incompatible return value type (got "FancyCat", expected "Self") [return-value]
Found 2 errors in 1 file (checked 1 source file)
I'm so confused - isn't Self FancyCat in this case?
How can I satisfy mypy here?
Your code does not guarantee that Self will be returned. For example, child classes will still return FancyCat, therefore Self annotation is invalid.
To get rid of errors, you can either:
a) make sure it's always self.__class__ returned, which IS actual Self
def add(self, other: Self) -> Self:
return self.__class__(self._value + other._value)
b) type with what you are actually returning, FancyCat
def sub(self, other: Self) -> FancyCat:
return FancyCat(self._value - other._value)
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