[Python-Dev] Dataclasses, frozen and __post_init__

Nick Coghlan ncoghlan at gmail.com
Sun Feb 18 19:34:28 EST 2018


On 18 February 2018 at 14:10, Guido van Rossum <guido at python.org> wrote:
> Agreed the __pre_init__ idea is no improvement. I think we're back where you
> started -- just use `object.__setattr__` to set the attribute in
> `__post_init__`. That's what the PEP says is used by the generated
> `__init__`, so I think it is reasonable to copy that pattern. Presumably the
> situation doesn't occur that frequently in real code (__post_init__ feels
> like a last resort hack anyway).

FWIW, if someone really wanted to create a 3rd party context manager
to assist with this they can do:

    @contextmanager
    def mutable(obj):
        cls = obj.__class__
        obj.__class__ = object
        try:
            yield obj
        finally:
            obj.__class__ = cls

    @dataclass(frozen=True)
    class C:
       i: int
       j: int = None
       database: InitVar[DatabaseType] = None

       def __post_init__(self, database):
           if self.j is None and database is not None:
               with mutable(self):
                   self.j = database.lookup('j')

Using object.__setattr__ explicitly would be clearer, though.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list