如果你使用的是Python 3.10+,那么你可以在这个答案和Python文档中讨论的数据类中使用仅关键字参数。
如果你使用的是< Python 3.10,那么你可以利用数据类。字段,使用default_factory抛出。由于该属性将使用field()声明,因此它被视为具有默认值;但是,如果用户试图创建一个实例而没有提供该字段的值,它将使用工厂,这将会出错。
这种技术并不等同于仅使用关键字,因为您仍然可以按位置提供所有参数。但是,这确实解决了问题,而且比使用各种数据类dunder方法要简单得多。
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, TypeVar
T = TypeVar("T")
def required() -> T:
f: T
def factory() -> T:
# mypy treats a Field as a T, even though it has attributes like .name, .default, etc
field_name = f.name # type: ignore[attr-defined]
raise ValueError(f"field '{field_name}' required")
f = field(default_factory=factory)
return f
@dataclass
class Event:
id: str
created_at: datetime
updated_at: Optional[datetime] = None
@dataclass
class NamedEvent(Event):
name: str = required()
event = NamedEvent(name="Some Event", id="ab13c1a", created_at=datetime.now())
print("created event:", event)
event2 = NamedEvent("ab13c1a", datetime.now(), name="Some Other Event")
print("created event:", event2)
event3 = NamedEvent("ab13c1a", datetime.now())
输出:
created event: NamedEvent(id='ab13c1a', created_at=datetime.datetime(2022, 7, 23, 19, 22, 17, 944550), updated_at=None, name='Some Event')
created event: NamedEvent(id='ab13c1a', created_at=datetime.datetime(2022, 7, 23, 19, 22, 17, 944588), updated_at=None, name='Some Other Event')
Traceback (most recent call last):
File ".../gist.py", line 39, in <module>
event3 = NamedEvent("ab13c1a", datetime.now())
File "<string>", line 6, in __init__
File ".../gist.py", line 14, in factory
raise ValueError(f"field '{field_name}' required")
ValueError: field 'name' required
你也可以在github上找到这段代码。