Python中classproperty的正确类型标注方式探究
问题原因分析
你遇到的Never类型报错,本质是泛型参数推导失败:
当你在Test类内部使用@classproperty装饰器时,Test类还处于定义过程中,mypy无法提前确定类的完整类型,因此错误地将泛型参数C推导为Never(代表不可能存在的类型),导致期望的函数参数类型变成Callable[[type[Never]], Any],与你的Callable[[Test], Any]不匹配。
另外你的装饰器实现还有一个小问题:__get__方法的_obj参数类型应该允许为None——当直接通过类(而非实例)访问属性时,_obj的值就是None,而非类实例。
正确的类型标注实现
下面是修正后的classproperty装饰器,既解决类型推导问题,也符合Python的属性访问规则:
from typing import Callable, TypeVar, Generic, Optional, Any # 绑定到类类型的泛型变量 ClassType = TypeVar('ClassType', bound=type) # 属性返回值的泛型变量 ReturnType = TypeVar('ReturnType') class classproperty(Generic[ReturnType]): def __init__(self, func: Callable[[ClassType], ReturnType]): self.func = func def __get__(self, _obj: Optional[Any], owner: ClassType) -> ReturnType: return self.func(owner)
使用示例
此时再用mypy检查你的测试代码,就能正常通过:
class Test: @classproperty def my_property(cls): return 1
如果需要更精确的类型标注,可以显式指定cls的类型:
class Test: @classproperty def my_property(cls: type[Test]) -> int: return 1
内容的提问来源于stack exchange,提问作者aidangallagher4
相关产品推荐
相关产品推荐

