Mainly Tech projects on Python and Electronic Design Automation.

Sunday, October 11, 2020

Python dataclass __hash__ generation

 I was reading a blog explaining dataclasses and was confused about its description of the unsafe_hash parameter.

Reading the docs was also confusing so I decided to write a program that generated a truth table of all the parameters said to govern __hash__ generation for dataclasses and check the output generated in each case.

The code

# -*- coding: utf-8 -*-
"""

__hash__ generation for @dataclass()

    Documentation could be better w.r.t. unsafe_hash:
      https://docs.python.org/3/library/dataclasses.html?highlight=unsafe_hash
    
    Parameters:
      eq:           default True,  equality checks as a tuple of values.
      frozen:       default False, stops field re-assignment.
      unsafe_hash   default False, Forces the gen of a __hash__ method 
                                   irrespective of eq and frozen values.
      
    __hash__ methods on a dataclass:
      Ref: https://docs.python.org/3/reference/datamodel.html#object.__hash__
      
      If set to None:   class is unhashable.
      If present:       class is hashable
      If absent:        class is unhashable; eq *should* be false too.
      
Created on Sun Oct 11 10:12:17 2020

@author: Paddy3118


"""

from dataclasses import dataclass
from itertools import product


print(__doc__ + """
TABLE: generated by testing the generated dadaclass

unsafe_hash, eq, frozen => Dataclass __hash__ state""")
for unsafe_hash, eq, frozen in product((False, True), repeat=3):
    @dataclass(eq=eq, frozen=frozen, unsafe_hash=unsafe_hash)
    class Dc:
        x: int
    
    if  '__hash__' not in dict(Dc.__dict__):
        state = 'ABSENT'
    elif dict(Dc.__dict__)['__hash__'] is None:
        state = 'SET_NONE (Unhashable)'
    else:
        state = 'PRESENT'
    print(f"{unsafe_hash!s:5}, {eq!s:5}, {frozen!s:5} => {state}")
    del Dc
    
    

The output:

__hash__ generation for @dataclass()
    
    Documentation could be better w.r.t. unsafe_hash:
      https://docs.python.org/3/library/dataclasses.html?highlight=unsafe_hash
    
    Parameters:
      eq:           default True,  equality checks as a tuple of values.
      frozen:       default False, stops field re-assignment.
      unsafe_hash   default False, Forces the gen of a __hash__ method 
                                   irrespective of eq and frozen values.
    
    __hash__ methods on a dataclass:
      Ref: https://docs.python.org/3/reference/datamodel.html#object.__hash__
      
      If set to None:   class is unhashable.
      If present:       class is hashable
      If absent:        class is unhashable; eq *should* be false too.

Created on Sun Oct 11 10:12:17 2020

@author: Paddy3118



TABLE: generated by testing the generated dadaclass

unsafe_hash, eq, frozen => Dataclass __hash__ state
False, False, False => ABSENT
False, False, True  => ABSENT
False, True , False => SET_NONE (Unhashable)
False, True , True  => PRESENT
True , False, False => PRESENT
True , False, True  => PRESENT
True , True , False => PRESENT
True , True , True  => PRESENT


Conclusion:

Set eq and frozen as appropriate and the __hash__ method is likely to be what you want. Only set unsafe_hash if you know what you are doing.


End.

No comments:

Post a Comment

Followers

Subscribe Now: google

Add to Google Reader or Homepage

Go deh too!

whos.amung.us

Blog Archive