Given this code:
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
class Foo(ABC):
@property
@staticmethod
@abstractmethod
def name() -> str:
pass
class Bar(Foo):
name = "bar"
class Baz(Foo):
name = "baz"
instances = [Bar(), Baz()]
print(instances[0].name)
if TYPE_CHECKING:
reveal_type(instances[0].name)
Ran by the python
interpreter, it prints (as expected):
bar
However, ran by mypy
type checker, it prints (unexpectedly):
main.py:23: note: Revealed type is "def () -> builtins.str"
It looks like the type is wrongly inferred (see playground). Is it possible to fix that somehow?
If possible, I would like to fix it "once and for all" (like in the Foo
class) because I'm accessing .name
in multiple places.
Python 3.11 disallowed wrapping of @property
using class decorators such as @classmethod
and @staticmethod
(see GH#89519).
This means the provided snippet shouldn't be considered as valid Python code, and latest versions of Mypy actually warns about it:
main.py:6: error: Only instance methods can be decorated with @property [misc]
main.py:23: note: Revealed type is "def () -> builtins.str"
Found 1 error in 1 file (checked 1 source file)
The easiest workaround is simply to use an instance method like so:
class Foo(ABC):
@property
@abstractmethod
def name(self) -> str:
pass
See also: GH#13035.