首页 > 解决方案 > 在 Python 数据类中使用默认 uuid 值

问题描述

如果我执行以下操作:

@dataclass
class Test:
    hi: Optional[str] = field(
        default_factory=lambda: str(uuid.uuid1()))

@dataclass
class Test2:
    hi: Optional[str] = str(uuid.uuid1())

if __name__ == "__main__":
    a = Test() # Test(hi='115a865c-33be-11eb-94a1-34c93db23648')
    b = Test() # Test(hi='115a865d-33be-11eb-8c6f-34c93db23648')
    c = Test2() # Test2(hi='10e44300-33be-11eb-85eb-34c93db23648')
    d = Test2() # Test2(hi='10e44300-33be-11eb-85eb-34c93db23648')

为什么Test会为每个实例返回不同的 uuid,而Test2每次都返回相同的 uuid?

另外,为什么default factory需要而不是default

标签: pythonpython-dataclasses

解决方案


文档中所述

default_factory:如果提供,它必须是一个零参数的可调用对象,当该字段需要默认值时将调用它。除其他目的外,这可用于指定具有可变默认值的字段,如下所述。同时指定 default 和 default_factory 是错误的。

在你的第一个例子中

@dataclass
class Test:
    hi: Optional[str] = field(
        default_factory=lambda: str(uuid.uuid1()))

您将匿名函数传递给默认工厂。

为了使事情更容易,让我们创建一个非匿名函数。

def get_new_uuid() -> str:
    return str(uuid.uuid1())


@dataclass
class Test:
    hi: Optional[uuid.UUID] = field(default_factory=get_new_uuid)

所以每个实例在初始化时都会Test调用get_new_uuid函数来获取新的 uuid。


您的第二个示例分配了一个默认值。

@dataclass
class Test2:
    hi: Optional[str] = str(uuid.uuid1())

相当于这个

@dataclass
class Test2:
    hi: Optional[str] = field(default=str(uuid.uuid1()))

如您所见,这里default使用了参数,而之前是default_factory. 在这里,您不传递函数,而是传递值。这是一次性的事情。

在没有实例化的情况下,Test您无法访问。hi但是Test2在导入时分配了默认值,因此您无需实例化即可访问它。它类似于 中定义的类属性和实例属性__init__


推荐阅读