Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using default uuid value in Python dataclasses

If I execute the following:

@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')

Why Test will return for every instance a different uuid, while Test2 will return the same each time?

Also, why default factory is needed and not default?

like image 324
Chen Avatar asked Oct 15 '25 17:10

Chen


1 Answers

As stated in the docs

default_factory: If provided, it must be a zero-argument callable that will be called when a default value is needed for this field. Among other purposes, this can be used to specify fields with mutable default values, as discussed below. It is an error to specify both default and default_factory.

In your first example

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

you pass an anonymous function to the default factory.

To make things easier, lets make a non anonymous function.

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


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

so each instance of Test calls get_new_uuid function to obtain new uuid, when initialized.


Your second example assigns a default value.

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

It's an equivalent of this

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

As you can see, here default parameter is used, while previously it was default_factory. Here, you don't pass a function, but a value. It's a one-time thing.

In Test you can't access hi without instantiating it. But Test2 has default value assigned on import, so you can access it without instantiating. It's similar to class attribute and instance attribute defined in __init__.

like image 123
Tom Wojcik Avatar answered Oct 17 '25 20:10

Tom Wojcik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!