This works fine:
def __add__(self, other: object) -> 'Currency':
if isinstance(other, self.__class__) and isinstance(other, Currency):
return self.__class__(other.amt + self.amt)
return NotImplemented
but this does not:
def __add__(self, other: object) -> 'Currency':
if isinstance(other, Currency) and isinstance(other, self.__class__): # only expression order is flipped
return self.__class__(other.amt + self.amt)
return NotImplemented
throws: error: "object" has no attribute "amt"
Full code to reproduce it locally: https://gist.github.com/pirate/b3ef5a25449285dadc366dd926cebcea
The intention is to check that other is the same class as self (to prevent adding BTC to USD by accident). That check alone should imply that other is a subclass of Currency (since the __add__ method is defined on Currency), but it looks like I have to explicitly make both assertions, and make the Currency assertion after the self.__class__ one in order for mypy to narrow the type correctly.
Correct me if I'm mistaken, but I think there may be two bugs here:
- The order of
isinstance checks shouldn't matter (especially not in an and expression)
- The
isinstance(other, Currency) should not even be necessary, as it's implied that other is a Currency if other.__class__ == self.__class__
This issue discusses a vaguely similar type-narrowing problem, but I'm not sure if it's actually related: #2776
This works fine:
but this does not:
throws:
error: "object" has no attribute "amt"Full code to reproduce it locally: https://gist.github.com/pirate/b3ef5a25449285dadc366dd926cebcea
The intention is to check that
otheris the same class asself(to prevent addingBTCtoUSDby accident). That check alone should imply thatotheris a subclass ofCurrency(since the__add__method is defined onCurrency), but it looks like I have to explicitly make both assertions, and make theCurrencyassertion after theself.__class__one in order for mypy to narrow the type correctly.Correct me if I'm mistaken, but I think there may be two bugs here:
isinstancechecks shouldn't matter (especially not in anandexpression)isinstance(other, Currency)should not even be necessary, as it's implied that other is aCurrencyifother.__class__ == self.__class__This issue discusses a vaguely similar type-narrowing problem, but I'm not sure if it's actually related: #2776