我想让set
参数可选,但仍然允许None
是一个有效值。根据文档,它建议可以使用dataclasses.MISSING
作为默认值来帮助实现这一点。
如上所示,MISSING
值是一个sentinel对象,用于检测用户是否提供了某些参数。使用此sentinel是因为None
是某些具有不同含义的参数的有效值。任何代码都不应直接使用MISSING
值。
但是通过如下方式使用它:
import dataclasses
from dataclasses import dataclass, field
@dataclass
class Var:
get: list
set: list = dataclasses.MISSING
def __post_init__(self):
if self.set is dataclasses.MISSING:
self.set = self.get
print(Var(get=['Title']))
我收到一个错误:
Traceback (most recent call last):
File "main.py", line 31, in <module>
print(Var(get=['Title']))
TypeError: __init__() missing 1 required positional argument: 'set'
2条答案
按热度按时间xtfmy6hx1#
代码不能直接使用MISSING值。
上面这部分在文档中被注意到是有原因的。因此,如果可能的话,我们应该避免在应用程序代码中使用
MISSING
用法(和导入)。在这种情况下,使用MISSING
根本不适用于我们的用例。假设用法(避免直接使用
MISSING
sentinel值,而是使用dataclasses.field(...)
:但是
MISSING
实际用在哪里呢?MISSING
是一个sentinel对象,dataclasses
模块在后台使用它的魔力。您可以查看
dataclasses.field
的源代码,并在那里找到它的明确用法:你会看到像
default
这样的字段声明的默认值是default=MISSING
而不是default=None
。这样做主要是为了确定用户是否真的将default
或default_factory
的值传递给工厂函数fields
。例如,像我们在上面的例子中所做的那样传递field(default=None)
是完全有效的;但是,由于默认值实际上是MISSING
,因此dataclasses
能够检测到已为此参数传递了一个值(值None
)。MISSING
如何声明如果你检查
dataclasses
模块的源代码,或者通过Ctrl
(在Mac上是Command
)+左击代码中任何地方的关键字MISSING
,你可以看到MISSING
实际上是如何声明的:一种可能的解决方案
借助
dataclasses
模块定义MISSING
的方式,理论上您可以定义自己的(空)类,然后示例化该类。然而,我觉得在这种情况下可以避免类示例化。下面是一行代码来创建一个sentinel类/类型:
那么,用法如下:
这可以正确区分在构造函数中省略
set
或指定set
的值(如set=None
)的情况。结果也如预期:
wlsrxk512#
我不知道你是否可以用这种方式使用
dataclasses.MISSING
,所以我会简单地使用一个专用的enum
。因为它是一个enum
,它被保证只与它自己相同,所以它应该给予你想要的用途:显然,这会阻止用户将
set
设置为_field_status.UNSET
,但大概他们不需要这样做。请注意,我有点困惑,为什么
None
是一个有效的值,它被暗示为一个 * 列表 *,但原则是成立的。