当提供的参数为 None 时,是否可以强制数据类字段调用其 default_factory?
Is it possible to force a dataclass field to call its default_factory when the supplied argument is None?
我有一个带有可变字段(列表)的数据class。我希望实现的是该字段永远不会是 None,即使在 __init__ 调用中明确设置为 None 也是如此。在正常的 class 中,实现起来很简单:
class A:
def __init__(self, l: Optional[List[int]] = None):
if l is None:
l = []
self.l = l
有没有办法只使用 dataclasses.field 函数来实现相同的结果,即不显式实现 __init__ 方法(当 class 有很多时,这会很麻烦属性)?当提供的初始化参数是 None 时,我可以强制 dataclasses.field 调用它的 default_factory
吗?
您可以使用 __post_init__
方法获得所需的结果,该方法会将 self.l
设置为空列表,即使它是 None
:
@dataclass
class A:
l: Optional[List[int]]
def __post_init__(self):
self.l = self.l or []
a = A(None)
print(a.l) # []
我不认为,直接强制 default_factory 在显式提供的 None 值上被调用是不可能的。但是您可以使用 __post_init__
方法显式检查 None 并提供 default_value,特别是当您必须检查许多属性时。
您可以使用 fields
函数自动扫描您的数据类以获取 None
值并为这些属性调用 default_factory,如果提供的话:
from dataclasses import dataclass, field, fields, MISSING
from typing import List
@dataclass
class A:
l: List[int] = field(default_factory=list)
def __post_init__(self):
for f in fields(self):
value = getattr(self, f.name)
if value is None and not f.default_factory is MISSING:
setattr(self, f.name, f.default_factory())
s = A([1,2])
print(s.l) # [1,2]
t = A(None)
print(t.l) # []
我有一个带有可变字段(列表)的数据class。我希望实现的是该字段永远不会是 None,即使在 __init__ 调用中明确设置为 None 也是如此。在正常的 class 中,实现起来很简单:
class A:
def __init__(self, l: Optional[List[int]] = None):
if l is None:
l = []
self.l = l
有没有办法只使用 dataclasses.field 函数来实现相同的结果,即不显式实现 __init__ 方法(当 class 有很多时,这会很麻烦属性)?当提供的初始化参数是 None 时,我可以强制 dataclasses.field 调用它的 default_factory
吗?
您可以使用 __post_init__
方法获得所需的结果,该方法会将 self.l
设置为空列表,即使它是 None
:
@dataclass
class A:
l: Optional[List[int]]
def __post_init__(self):
self.l = self.l or []
a = A(None)
print(a.l) # []
我不认为,直接强制 default_factory 在显式提供的 None 值上被调用是不可能的。但是您可以使用 __post_init__
方法显式检查 None 并提供 default_value,特别是当您必须检查许多属性时。
您可以使用 fields
函数自动扫描您的数据类以获取 None
值并为这些属性调用 default_factory,如果提供的话:
from dataclasses import dataclass, field, fields, MISSING
from typing import List
@dataclass
class A:
l: List[int] = field(default_factory=list)
def __post_init__(self):
for f in fields(self):
value = getattr(self, f.name)
if value is None and not f.default_factory is MISSING:
setattr(self, f.name, f.default_factory())
s = A([1,2])
print(s.l) # [1,2]
t = A(None)
print(t.l) # []