The underlying issue here is that we don't want an extra state flag in the object to indicate "this object is currently [im]mutable". Using __class__ assignment to signal this is clever way to add this state, though not without risks.
On Sun, Feb 18, 2018 at 4:34 PM, Nick Coghlan <ncogh...@gmail.com> wrote: > On 18 February 2018 at 14:10, Guido van Rossum <gu...@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 | ncogh...@gmail.com | Brisbane, Australia > -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com