使用 dataclasses.MISSING 作为带有 Python 数据类的可选参数值?
Using dataclasses.MISSING as optional parameter value with a Python dataclass?
我想使 set
参数可选,但仍允许 None
为有效值。基于 the documentation,它建议 dataclasses.MISSING
可以使用默认值来帮助完成此操作。
As shown above, the MISSING
value is a sentinel object used to detect
if some parameters are provided by the user. This sentinel is used
because None
is a valid value for some parameters with a distinct
meaning. No code should directly use the MISSING
value.
但是通过如下使用:
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'
不知道这样能不能用dataclasses.MISSING
,所以干脆用专用的enum
。因为它是一个enum
,它保证只和它自己一样,所以它应该给你想要的东西:
from dataclasses import dataclass
from enum import Enum
_field_status = Enum("FieldStatus", "UNSET")
@dataclass
class Var:
get: list
set: list = _field_status.UNSET
def __post_init__(self):
if self.set is _field_status.UNSET:
self.set = self.get
print(Var(get = [7]))
print(Var(get=[7], set=[8]))
print(Var(get=[7], set=None))
显然这会阻止用户将 set
设置为 _field_status.UNSET
,但大概他们不需要这样做。
请注意,我有点困惑为什么 None
是暗示为 list 的某些内容的有效值,但原则是成立的。
No code should directly use the MISSING value.
上述部分在文档中注明是有原因的。因此,我们应该尽可能避免在我们的应用程序代码中使用 MISSING
用法(和导入)。在这种情况下,使用 MISSING
根本不适用于我们的用例。
假定的用法(通过避免直接使用 MISSING
标记值,而是使用 dataclasses.field(...)
:
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Var:
get: list[str]
set: Optional[list[str]] = field(default=None)
print(Var(get=['Title']))
# Var(get=['Title'], set=None)
但是MISSING
实际用在哪里呢?
MISSING
是 dataclasses
模块在幕后使用的哨兵对象,因为它很神奇。
您可以检查 dataclasses.field
的源代码并在那里找到它的明确用法:
def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
hash=None, compare=True, metadata=None):
您会看到 default
等字段的声明默认值是 default=MISSING
而不是 default=None
。这样做主要是为了识别用户是否实际将 default
或 default_factory
的值传递给工厂函数 fields
。例如,像我们在上面的例子中所做的那样传递 field(default=None)
是完全有效的;但是,由于默认值实际上是 MISSING
,因此 dataclasses
能够检测到已为该参数传递了一个值(None
的值)。
我想使 set
参数可选,但仍允许 None
为有效值。基于 the documentation,它建议 dataclasses.MISSING
可以使用默认值来帮助完成此操作。
As shown above, the
MISSING
value is a sentinel object used to detect if some parameters are provided by the user. This sentinel is used becauseNone
is a valid value for some parameters with a distinct meaning. No code should directly use theMISSING
value.
但是通过如下使用:
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'
不知道这样能不能用dataclasses.MISSING
,所以干脆用专用的enum
。因为它是一个enum
,它保证只和它自己一样,所以它应该给你想要的东西:
from dataclasses import dataclass
from enum import Enum
_field_status = Enum("FieldStatus", "UNSET")
@dataclass
class Var:
get: list
set: list = _field_status.UNSET
def __post_init__(self):
if self.set is _field_status.UNSET:
self.set = self.get
print(Var(get = [7]))
print(Var(get=[7], set=[8]))
print(Var(get=[7], set=None))
显然这会阻止用户将 set
设置为 _field_status.UNSET
,但大概他们不需要这样做。
请注意,我有点困惑为什么 None
是暗示为 list 的某些内容的有效值,但原则是成立的。
No code should directly use the MISSING value.
上述部分在文档中注明是有原因的。因此,我们应该尽可能避免在我们的应用程序代码中使用 MISSING
用法(和导入)。在这种情况下,使用 MISSING
根本不适用于我们的用例。
假定的用法(通过避免直接使用 MISSING
标记值,而是使用 dataclasses.field(...)
:
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Var:
get: list[str]
set: Optional[list[str]] = field(default=None)
print(Var(get=['Title']))
# Var(get=['Title'], set=None)
但是MISSING
实际用在哪里呢?
MISSING
是 dataclasses
模块在幕后使用的哨兵对象,因为它很神奇。
您可以检查 dataclasses.field
的源代码并在那里找到它的明确用法:
def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
hash=None, compare=True, metadata=None):
您会看到 default
等字段的声明默认值是 default=MISSING
而不是 default=None
。这样做主要是为了识别用户是否实际将 default
或 default_factory
的值传递给工厂函数 fields
。例如,像我们在上面的例子中所做的那样传递 field(default=None)
是完全有效的;但是,由于默认值实际上是 MISSING
,因此 dataclasses
能够检测到已为该参数传递了一个值(None
的值)。