A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://mail.python.org/pipermail/python-dev/2018-February/152127.html below:

[Python-Dev] Dataclasses and correct hashability

[Python-Dev] Dataclasses and correct hashabilityNick Coghlan ncoghlan at gmail.com
Mon Feb 5 09:28:25 EST 2018
On 5 February 2018 at 15:49, Guido van Rossum <guido at 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   |   ncoghlan at gmail.com   |   Brisbane, Australia
More information about the Python-Dev mailing list

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4