如何在继承的数据类中创建可选字段?
How to create an optional field in a dataclass that is inherited?
from typing import Optional
@dataclass
class Event:
id: str
created_at: datetime
updated_at: Optional[datetime]
#updated_at: datetime = field(default_factory=datetime.now) CASE 1
#updated_at: Optional[datetime] = None CASE 2
@dataclass
class NamedEvent(Event):
name: str
创建事件实例时,我通常不会有 updated_at
字段。我可以将 current time
作为默认值传递,也可以在数据库中插入时为其添加一个值,并在后续使用该对象时获取它。哪种方法更好?
根据我的理解,我无法在不传递 case1 和 case2 中的 updated_at 字段的情况下创建 NamedEvent
实例 ,因为我在 name 字段中没有默认值。
您遇到的根本问题似乎与 中描述的问题相同。 post 的简短版本是在函数签名(包括 dataclass-generated __init__
方法)中,强制参数(如 NamedEvent 的 name
)不能跟在默认参数之后值(定义事件 updated_at
的行为所必需的)- child 的字段将始终跟在其 parent.
的字段之后
因此,要么您的 parent class 中没有默认值(在这种情况下不起作用),要么您的所有 child 字段都需要默认值(这很烦人,有时根本不可行)。
我上面链接的 post 讨论了一些您可以应用来解决您的问题的模式,但作为更好的选择,您也可以使用已经解决了这个问题的第三方包 pydantic
为你。示例实现可能如下所示:
import pydantic
from datetime import datetime
class Event(pydantic.BaseModel):
id: str
created_at: datetime = None
updated_at: datetime = None
@pydantic.validator('created_at', pre=True, always=True)
def default_created(cls, v):
return v or datetime.now()
@pydantic.validator('updated_at', pre=True, always=True)
def default_modified(cls, v, values):
return v or values['created_at']
class NamedEvent(Event):
name: str
通过验证器的 default-value 规范有点麻烦,但总的来说它是一个非常有用的包,它修复了您 运行 在使用数据 classes 时遇到的许多缺点,再加上一些。
使用 class 定义,可以像这样创建 NamedEvent
的实例:
>>> NamedEvent(id='1', name='foo')
NamedEvent(id='1', created_at=datetime.datetime(2020, 5, 2, 18, 50, 12, 902732), updated_at=datetime.datetime(2020, 5, 2, 18, 50, 12, 902732), name='foo')
from typing import Optional
@dataclass
class Event:
id: str
created_at: datetime
updated_at: Optional[datetime]
#updated_at: datetime = field(default_factory=datetime.now) CASE 1
#updated_at: Optional[datetime] = None CASE 2
@dataclass
class NamedEvent(Event):
name: str
创建事件实例时,我通常不会有 updated_at
字段。我可以将 current time
作为默认值传递,也可以在数据库中插入时为其添加一个值,并在后续使用该对象时获取它。哪种方法更好?
根据我的理解,我无法在不传递 case1 和 case2 中的 updated_at 字段的情况下创建 NamedEvent
实例 ,因为我在 name 字段中没有默认值。
您遇到的根本问题似乎与 __init__
方法)中,强制参数(如 NamedEvent 的 name
)不能跟在默认参数之后值(定义事件 updated_at
的行为所必需的)- child 的字段将始终跟在其 parent.
因此,要么您的 parent class 中没有默认值(在这种情况下不起作用),要么您的所有 child 字段都需要默认值(这很烦人,有时根本不可行)。
我上面链接的 post 讨论了一些您可以应用来解决您的问题的模式,但作为更好的选择,您也可以使用已经解决了这个问题的第三方包 pydantic
为你。示例实现可能如下所示:
import pydantic
from datetime import datetime
class Event(pydantic.BaseModel):
id: str
created_at: datetime = None
updated_at: datetime = None
@pydantic.validator('created_at', pre=True, always=True)
def default_created(cls, v):
return v or datetime.now()
@pydantic.validator('updated_at', pre=True, always=True)
def default_modified(cls, v, values):
return v or values['created_at']
class NamedEvent(Event):
name: str
通过验证器的 default-value 规范有点麻烦,但总的来说它是一个非常有用的包,它修复了您 运行 在使用数据 classes 时遇到的许多缺点,再加上一些。
使用 class 定义,可以像这样创建 NamedEvent
的实例:
>>> NamedEvent(id='1', name='foo')
NamedEvent(id='1', created_at=datetime.datetime(2020, 5, 2, 18, 50, 12, 902732), updated_at=datetime.datetime(2020, 5, 2, 18, 50, 12, 902732), name='foo')