Ris*_*hiD 4 python python-dataclasses
我想让set参数可选,但仍然允许None为有效值。根据文档,它建议dataclasses.MISSING可以使用默认值来帮助实现这一点。
如上所示,
MISSINGvalue是一个哨兵对象,用于检测用户是否提供了某些参数。使用此标记是因为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']))
Run Code Online (Sandbox Code Playgroud)
我收到错误:
Traceback (most recent call last):
File "main.py", line 31, in <module>
print(Var(get=['Title']))
TypeError: __init__() missing 1 required positional argument: 'set'
Run Code Online (Sandbox Code Playgroud)
任何代码都不应直接使用 MISSING 值。
上面的这部分在文档中注明是有原因的。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)
Run Code Online (Sandbox Code Playgroud)
MISSING实际用在什么地方呢?这MISSING是一个哨兵对象,dataclasses模块在幕后使用它来发挥其魔力。
您可以检查源代码dataclasses.field并在那里找到它的明确用法:
def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
hash=None, compare=True, metadata=None):
Run Code Online (Sandbox Code Playgroud)
您将看到字段声明的默认值,例如defaultisdefault=MISSING而不是default=None。这样做主要是为了确定用户是否实际向工厂函数传递了default一个default_factory值fields。例如,field(default=None)像我们在上面的示例中所做的那样,通过是完全有效的;但是,由于实际上是默认值MISSING,dataclasses因此能够检测到已为此参数传递了一个值(值为None)。
MISSING申报如果您检查模块的源代码dataclasses,或者通过Ctrl(在 Mac 上)+左键单击代码中任意位置Command的关键字,您可以看到实际声明的方式:MISSINGMISSING
# A sentinel object to detect if a parameter is supplied or not. Use
# a class to give it a better repr.
class _MISSING_TYPE:
pass
MISSING = _MISSING_TYPE()
Run Code Online (Sandbox Code Playgroud)
顺应dataclasses模块定义的方式MISSING,理论上您可以定义自己的(空)类,然后实例化该类。
然而,我认为在这种情况下可以避免类实例化。下面是创建哨兵类/类型的简单说明:
class _UNSET: ... # here the ellipsis (`...`) is essentially the same as `pass`
Run Code Online (Sandbox Code Playgroud)
那么,用法如下:
from __future__ import annotations
from dataclasses import dataclass
class _UNSET: ...
@dataclass
class Var:
get: list
set: list | None = _UNSET
def __post_init__(self):
if self.set is _UNSET:
self.set = self.get
print(Var(get=[7]))
print(Var(get=[7], set=[8]))
print(Var(get=[7], set=None))
Run Code Online (Sandbox Code Playgroud)
set当在构造函数中省略 时,或者指定 的值(set例如 )时,这可以正确区分场景set=None。
结果,也符合预期:
Var(get=[7], set=[7])
Var(get=[7], set=[8])
Var(get=[7], set=None)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4971 次 |
| 最近记录: |