在类型注解中忽略某个字段
如果我有一个叫做pydantic的类,像这样:
from typing import Annotated, get_origin
from pydantic import BaseModel
class IgnorableBaseModel(BaseModel):
_ignored: ClassVar[dict[str, Any]] = {}
def __getattr__(self, attr):
"""do something with _ignored, else fallback to default"""
def __init_subclass__(cls, **kwargs) -> None:
del_keys = []
for key, annotation in cls.__annotations__.items():
if key.startswith("_"): # exclude protected/private attributes
continue
if get_origin(annotation) is Annotated:
if get_args(annotation)[1] == "ignore me"
cls._ignored[key] = cls.__annotations__[key]
del_keys.append(key)
for key in del_keys:
del cls.__annotations__[key]
class MyClass(IgnorableBaseModel):
name: Annotated[str, "ignore me"] # ignore this
x: int
我在这个类里用的一个变量是在__init__
方法里定义的,然后通过__getattr__
来访问,所以我不能给它设置一个值。请问有没有办法让mypy忽略这个问题,或者我是不是每次都得像这样重写初始化参数:
class MyClass(IgnorableBaseModel):
name: Annotated[str, "ignore me"]
x: int
def __init__(self, x: int):
self.x = x
如果能有一个注释可以加上,告诉mypy这个变量在初始化时不需要就好了。
这里的“ignore me”是用来表示我不想看到这个错误的:
Missing named argument "name" for "MyClass"Mypycall-arg
为了提供一些背景信息,我正在尝试制作一个Python的领域特定语言(DSL),所以能够对一些属性进行类型提示,但实际上不需要给它们赋值,这样会很有帮助。
1 个回答
1
如果你想让 name
这个属性在 __init__
方法中被定义,而不需要在创建对象时传入它的值,可以使用 Field
的 init
参数。
from typing import Annotated
from pydantic import BaseModel, Field
class MyClass(BaseModel):
name: Annotated[str, Field(init=False)]
x: int
这也可以写成
class MyClass(BaseModel):
name: str = Field(init=False)
x: int
这样生成的 __init__
方法只会期待一个 x
的参数,至于 MyClass
的实例中的 name
属性怎么定义,就得靠我们自己来处理了。我们可以使用默认值、默认工厂,或者自己定义一个 __init__
方法,或者使用 Pydantic 提供的其他技巧。