我试着写一个例子,我想在类型检查过程中使用一个冻结的类示例,并将它与一个普通的类交换,以避免支付冻结类的示例化成本。
目标是确保示例在类型检查器中是不可变的,并在运行时使用常规的类。下面是代码片段:
from dataclasses import dataclass
from typing import TYPE_CHECKING
from functools import partial
if TYPE_CHECKING:
frozen = partial(dataclass, frozen=True)
else:
frozen = dataclass
@frozen
class Foo:
x: int
y: int
foo = Foo(1, 2) # mypy complains about the number of arguments
foo.x = 3 # instead, mypy should complain here
字符串
这在运行时可以正常工作,但是运行mypy会引发这个错误。Pyright也会给我同样的错误:
foo.py:49: error: Too many arguments for "Foo" [call-arg]
型
在这个代码片段中,类型检查器可以捕获突变错误:
@dataclass(frozen=True)
class Foo:
x: int
y: int
foo = Foo(1, 2)
foo.x = 3 # mypy correctly catches the error here
型
所以,我猜类型检查器不喜欢我使用frozen = dataclass
或frozen = partial(...)
的别名。我如何正确地注解它,使类型检查器理解它是一个类示例,而不会抱怨不匹配的参数计数?
- 附注:这只是一个练习。我知道打开
dataclass(frozen=True)
要容易得多,在这种情况下我不应该关心性能。我是在阅读Tin Tvrtković关于在编译时冻结attr类示例的blog文章后受到启发而尝试的。*
1条答案
按热度按时间4jb9z9bj1#
使用
@dataclass_transform
和frozen_default = True
:字符串
frozen_default
是在Python 3.12中添加的。但是,由于@dataclass_transform
故意接受所有关键字参数,因此3.11(完全相同)和lower(使用typing_extensions
)就可以了。这适用于mypy和pyright:
型