I'm sorry, but a solution that requires __class__ assignment is way too fragile for my taste.
On Mon, Feb 5, 2018 at 6:28 AM, Nick Coghlan <ncogh...@gmail.com> wrote: > On 5 February 2018 at 15:49, Guido van Rossum <gu...@python.org> wrote: > > My point is that once you have one of those patterns in place, changing > your > > code to avoid them may be difficult. And yet your code may treat the > objects > > as essentially immutable after the initialization phase (e.g. a parse > tree). > > So if you create a dataclass and start coding like that for a while, and > > much later you need to put one of these into a set or use it as a dict > key, > > switching to frozen=True may not be a quick option. And writing a > __hash__ > > method by hand may feel like a lot of busywork. So this is where > > [unsafe_]hash=True would come in handy. > > > > I think naming the flag unsafe_hash should take away most objections, > since > > it will be clear that this is not a safe thing to do. People who don't > > understand the danger are likely to copy a worse solution from > StackOverflow > > anyway. The docs can point to frozen=True and explain the danger. > > Aye, calling the flag unsafe_hash would convert me from -1 to -0. > > The remaining -0 is because I think there's a different and more > robust way to tackle your example use case: > > # Mutable initialization phase > >>> from dataclasses import dataclass > >>> @dataclass > ... class Example: > ... a: int > ... b: int > ... > >>> c = Example(None, None) > >>> c > Example(a=None, b=None) > >>> c.a = 1 > >>> c.b = 2 > >>> c > Example(a=1, b=2) > > > # Frozen usage phase > >>> @dataclass(frozen=True) > ... class LockedExample(Example): > ... pass > ... > >>> c.__class__ = LockedExample > >>> c.a = 1 > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "/home/ncoghlan/devel/cpython/Lib/dataclasses.py", line 448, > in _frozen_setattr > raise FrozenInstanceError(f'cannot assign to field {name!r}') > dataclasses.FrozenInstanceError: cannot assign to field 'a' > >>> c.b = 2 > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "/home/ncoghlan/devel/cpython/Lib/dataclasses.py", line 448, > in _frozen_setattr > raise FrozenInstanceError(f'cannot assign to field {name!r}') > dataclasses.FrozenInstanceError: cannot assign to field 'b' > >>> hash(c) > 3713081631934410656 > > The gist of that approach is to assume that there will be *somewhere* > in the code where it's possible to declare the construction of the > instance "complete", and flip the nominal class over to the frozen > subclass to make further mutation unlikely, even though the true > underlying type is still the mutable version. > > That said, if we do provide "unsafe_hash", then the documentation for > that flag becomes a place where we can explicitly suggest using a > frozen subclass instead. > > 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