我使用PyCharm 2023.2.3(社区版)进行开发。 有一个脚本:
from functools import cached_property
from collections.abc import Callable
from typing import TypeVar, Generic, Any, overload, Union
T = TypeVar("T")
class result_property(cached_property, Generic[T]):
def __init__(self, func: Callable[[Any], T]) -> None:
super().__init__(func)
def __set_name__(self, owner: type[Any], name: str) -> None:
super().__set_name__(owner, name)
@overload
def __get__(self, instance: None, owner: Union[type[Any], None] = None) -> 'result_property[T]': ...
@overload
def __get__(self, instance: object, owner: Union[type[Any], None] = None) -> T: ...
def __get__(self, instance, owner=None):
return super().__get__(instance, owner)
def func_str(s: str) -> None:
print(s)
class Foo:
@result_property
def prop_int(self) -> int:
return 1
foo = Foo()
func_str(foo.prop_int) # type error is expected here
PyCharm 类型检查器报告它是正确的。但是我除了它在最后一行报告类型错误之外。 如果我对此脚本运行 mypy check,它会报告:
tmp.py:38: error: Argument 1 to "func_str" has incompatible type "int"; expected "str" [arg-type]
Found 1 error in 1 file (checked 1 source file)
为什么 Pycharm 报告没问题?
在这种情况下是否可以以某种方式修改 PyCharm 的脚本来报告类型错误?
我刚刚检查了 PyCharm 2023.2.5,即使在尝试更复杂的类版本时也没有收到任何错误,例如增强
result_property
类中的类型提示以提供 PyCharm 更多信息:
from functools import cached_property
from collections.abc import Callable
from typing import TypeVar, Generic, Any, Union, cast
T = TypeVar("T")
class result_property(cached_property, Generic[T]):
def __init__(self, func: Callable[[Any], T]) -> None:
super().__init__(func)
def __set_name__(self, owner: type[Any], name: str) -> None:
super().__set_name__(owner, name)
def __get__(self, instance: Any, owner: Union[type[Any], None] = None) -> Union[T, 'result_property[T]']:
if instance is None:
return self
result = super().__get__(instance, owner)
return cast(T, result)
def func_str(s: str) -> None:
print(s)
class Foo:
@result_property
def prop_int(self) -> int:
return 1
foo = Foo()
func_str(foo.prop_int) # PyCharm still reports no type error here
鉴于即使在增强类型提示后,PyCharm 仍然不会报告类型错误,我认为 PyCharm 的类型推断系统在处理像您这样的复杂场景(涉及自定义装饰器和泛型)时存在局限性或表现不同。 PyCharm 和
mypy
之间的差异并不罕见,尤其是在更复杂或更细致的打字情况下。
所以此时您的选择是:
使用
mypy
或其他静态类型检查器作为开发工作流程的一部分。在测试或构建过程中将 mypy 作为单独的步骤运行可以帮助捕获这些类型的错误,即使 PyCharm 不能。将此问题作为问题或功能请求报告给 JetBrains 的 PyCharm 问题跟踪器。
作为一种(非理想)解决方法,如果此类型检查问题对您的项目很重要,请考虑调整您的代码结构。有时,简化代码或避免过于复杂的类型结构可以使其与各种类型检查器更加兼容。