如何在自定义__setattr__方法后让coc-pyright正常报告reportAttributeAccessIssue问题
如何在自定义__setattr__方法后让coc-pyright正常报告reportAttributeAccessIssue问题
这个问题其实是因为当你自定义__setattr__方法时,pyright会默认认为你希望处理所有属性的赋值操作(包括未预先定义的属性),所以自动关闭了未知属性的访问检查。要同时保留自定义__setattr__和静态检查功能,你可以试试下面几种方案:
方案一:使用__slots__限制允许的属性
如果你的类不需要动态添加属性,直接用__slots__明确列出所有允许的属性。这样即使你自定义了__setattr__,pyright也会严格检查赋值的属性是否在__slots__列表中:
from pydantic import BaseModel class User2(BaseModel): __slots__ = ("name", "age") name: str age: int def __setattr__(self, key, value): super().__setattr__(key, value) user2 = User2(name="Alice", age=1) user2.foo = 1 # coc-pyright会正常报错:Cannot assign to attribute "foo" for class "User2"
方案二:给__setattr__的key参数添加精确的类型注解
通过Literal类型明确指定__setattr__接受的属性名,这样pyright会在静态检查时验证传入的key是否符合要求:
from pydantic import BaseModel from typing import Literal class User2(BaseModel): name: str age: int def __setattr__(self, key: Literal["name", "age"], value): super().__setattr__(key, value) user2 = User2(name="Alice", age=1) user2.foo = 1 # coc-pyright会报错:Argument of type "Literal['foo']" cannot be assigned to parameter "key" of type "Literal['name', 'age']"
这种方式适合属性数量不多的类,如果属性较多,你可以借助typing.get_type_hints来动态生成允许的属性名类型,不过写法会稍微复杂一点。
方案三:结合运行时检查和静态提示
如果你需要更灵活的处理,可以在自定义__setattr__中手动检查属性是否属于模型的预定义字段,同时通过类型注解辅助pyright识别:
from pydantic import BaseModel from typing import Literal class User2(BaseModel): name: str age: int # 动态生成允许的属性名类型 _allowed_attrs = Literal[tuple(model_fields.keys())] def __setattr__(self, key: _allowed_attrs, value): # 运行时额外验证,防止绕过静态检查的情况 if key not in self.model_fields: raise ValueError(f"未知属性:{key}") super().__setattr__(key, value) user2 = User2(name="Alice", age=1) user2.foo = 1 # coc-pyright会报错,同时运行时也会抛出异常
这样既保留了自定义__setattr__的逻辑,又能让pyright正常进行未知属性的检查,还能在运行时提供额外的保障。
备注:内容来源于stack exchange,提问作者user2976130
相关产品推荐
相关产品推荐

