[Python-Dev] Dataclasses, frozen and __post_init__

Guido van Rossum guido at python.org
Tue Feb 20 11:45:07 EST 2018


On Mon, Feb 19, 2018 at 8:16 PM, Glenn Linderman <v+python at g.nevcal.com>
wrote:

> On 2/19/2018 7:02 PM, Guido van Rossum wrote:
>
> But how?
>
> On Mon, Feb 19, 2018 at 5:06 PM, Chris Barker - NOAA Federal <
> chris.barker at noaa.gov> wrote:
>
>> ... maybe it would be helpful to be able to
>> freeze an instance after creation for multiple use-cases?
>>
>
> And there's the crux of the issue... if the creator of Python can't figure
> out how to make mutable objects immutable by fiat after creation, then it
> is unlikely anyone else can!
>

Um, the question was meant in the Socratic way. :-)

(Snipped the rest.)

TBH, I don't hate Nick's solution that assigns to __class__ in
__post_init__. You can probably come up with a class decorator that hides
construction of the frozen subclass. I do think that it should be used very
sparingly, as the existence of the subclass is hard to hide: instances of
MyRecord will show as instances of _LockedMyRecord when printed or
otherwise inspected, which could be confusing.

There's another very simple low-tech solution:

@dataclass
class MyRecord:
    a: int
    # etc.
    frozen: bool = False
    def freeze(self):
        self.frozen = True
    def __setattr__(self, name, value):
        if self.frozen: raise AttributeError
        super().__setattr__(name, value)
    def __hash__(self):
        assert self.frozen
        return super().__hash__()

It can easily be weaponized via an extra decorator, and it's simpler in
that it doesn't use a magical second class. I'm just not keen on adding the
extra attribute to all frozen instances created via
@dataclass(frozen=True), because it's extra space overhead.

(In fact you can conclude that I'm not keen on exposing *any* of these
"solutions" as a flag on the @dataclass() decorator. They all feel pretty
fragile to me.)

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180220/7562ea34/attachment.html>


More information about the Python-Dev mailing list