Skip to content Skip to sidebar Skip to footer

How To Make Non-frozen Dataclass Frozen, And Vice Versa?

I want to know any simple way to make the below dataclass bar frozen. @dataclass class Bar: foo: int bar = Bar(foo=1) In other words, I want the below function some_fn_to_free

Solution 1:

Python dataclasses are great, but the attrs package is a more flexible alternative, if you are able to use a third-party library. For example:

import attr

# Your class of interest.@attr.s()classBar(object):
   val = attr.ib()

# A frozen variant of it.@attr.s(frozen = True)classFrozenBar(Bar):
   pass# Three instances:# - Bar.# - FrozenBar based on that Bar.# - Bar based on that FrozenBar.
b1 = Bar(123)
fb = FrozenBar(**attr.asdict(b1))
b2 = Bar(**attr.asdict(fb))

# We can modify the Bar instances.
b1.val = 777
b2.val = 888# Check current vals.for x in (b1, fb, b2):
    print(x)

# But we cannot modify the FrozenBar instance.try:
    fb.val = 999except attr.exceptions.FrozenInstanceError:
    print(fb, 'unchanged')

Output:

Bar(val=888)
FrozenBar(val=123)
Bar(val=999)
FrozenBar(val=123) unchanged

Solution 2:

dataclass doesn't have built-in support for that. Frozen-ness is tracked on a class-wide basis, not per-instance, and there's no support for automatically generating frozen or unfrozen equivalents of dataclasses.

While you could try to do something to generate new dataclasses on the fly, it'd interact very poorly with isinstance, ==, and other things you'd want to work. It's probably safer to just write two dataclasses and converter methods:

@dataclassclassBar:
    foo: intdefas_frozen(self):
        return FrozenBar(self.foo)

@dataclass(frozen=True)classFrozenBar:
    foo: intdefas_unfrozen(self):
        return Bar(self.foo)

Post a Comment for "How To Make Non-frozen Dataclass Frozen, And Vice Versa?"