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

Reply via email to