如何为Mixin添加类型提示以声明属性存在(Pyright环境)
解决Pyright对Mixin类属性/方法的类型检查报错
场景1:依赖实例属性的Mixin
示例代码:
from lib import stringlib class NiceNameMixin: @property def nice_first_name(self): return stringlib.clean_name(self.first_name) @property def nice_last_name(self): return stringlib.clean_name(self.last_name)
Pyright报错:
Cannot access member "first_name" for type "NiceNameMixin" Member "first_name" is unknown.
替代# type: ignore的解决方案
方案1:用Protocol声明依赖属性
定义一个Protocol来描述Mixin需要的属性,然后给self指定该Protocol类型,明确告知类型检查器:使用此Mixin的类必须具备这些属性。
from typing import Protocol from lib import stringlib class HasName(Protocol): first_name: str last_name: str class NiceNameMixin: @property def nice_first_name(self: HasName): return stringlib.clean_name(self.first_name) @property def nice_last_name(self: HasName): return stringlib.clean_name(self.last_name)
方案2:用抽象基类(ABC)强制实现属性
如果需要在运行时也确保属性存在,可以用ABC定义抽象属性,强制子类必须实现:
from abc import ABC, abstractproperty from lib import stringlib class HasName(ABC): @abstractproperty def first_name(self) -> str: pass @abstractproperty def last_name(self) -> str: pass class NiceNameMixin(HasName): @property def nice_first_name(self): return stringlib.clean_name(self.first_name) @property def nice_last_name(self): return stringlib.clean_name(self.last_name)
场景2:依赖类属性的Mixin
补充示例代码:
from rest_framework import serializers class UtilsMixin: @classproperty def model_class(cls: serializers.ModelSerializer): # Type of parameter Cls must be a supertype of its class "UtilsMixin" return cls.Meta.model # Cannot access member "Meta" for type "ModelSerializer" Member "Meta" is unknown
解决方案
用Protocol定义类级别的依赖,结合TypeVar实现类型约束:
from typing import Protocol, TypeVar from rest_framework import serializers T = TypeVar('T', bound='HasModelMeta') class HasModelMeta(Protocol): class Meta: model: type class UtilsMixin: @classproperty def model_class(cls: Type[T]) -> type: return cls.Meta.model
也可以结合类型断言消除报错,同时保留运行时检查:
from typing import Type, TypeVar from rest_framework import serializers ModelSerializerSubclass = TypeVar('ModelSerializerSubclass', bound=serializers.ModelSerializer) class UtilsMixin: @classproperty def model_class(cls: Type[ModelSerializerSubclass]) -> type: assert hasattr(cls, 'Meta') and hasattr(cls.Meta, 'model'), "该Mixin要求类必须定义Meta.model" return cls.Meta.model
内容的提问来源于stack exchange,提问作者run_the_race
相关产品推荐
相关产品推荐

