在 Python 数据类中使用默认 uuid 值

Che*_*hen 2 python python-dataclasses

如果我执行以下命令:

@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')
Run Code Online (Sandbox Code Playgroud)

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

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

Tom*_*cik 6

正如文档中所述

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

在你的第一个例子中

@dataclass
class Test:
    hi: Optional[str] = field(
        default_factory=lambda: str(uuid.uuid1()))
Run Code Online (Sandbox Code Playgroud)

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

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

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


@dataclass
class Test:
    hi: Optional[uuid.UUID] = field(default_factory=get_new_uuid)
Run Code Online (Sandbox Code Playgroud)

因此,初始化时,每个实例都会Test调用get_new_uuid函数来获取新的 uuid。


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

@dataclass
class Test2:
    hi: Optional[str] = str(uuid.uuid1())
Run Code Online (Sandbox Code Playgroud)

这相当于这个

@dataclass
class Test2:
    hi: Optional[str] = field(default=str(uuid.uuid1()))
Run Code Online (Sandbox Code Playgroud)

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

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