Search code examples
pythonpython-3.7python-dataclasses

How to use dataclasses to generate a field value?


I have the following class:

class WordItem:
    def __init__(self, phrase: str, word_type: WORD_TYPE):
        self.id = f'{phrase}_{word_type.name.lower()}'
        self.phrase = phrase
        self.word_type = word_type

    @classmethod
    def from_payload(cls, payload: Dict[str, Any]) -> 'WordItem':
        return cls(**payload)

How can I rewrite this class as a dataclass?

Specifically, how should the id field be declared? It has a generated value, and is not a field that the code creating instances would provide.


Solution

  • Just move each of your attributes to a type-annotated declaration on the class, where the class has been decorated with the @dataclasses.dataclass decorator.

    You can generate the value for id in a __post_init__ method; make sure you mark it as exempt from the __init__ arguments with a dataclass.field() object:

    from dataclasses import dataclass, field    
    
    @dataclass
    class WordItem:
        id: str = field(init=False)
        phrase: str
        word_type: WORD_TYPE
    
        def __post_init__(self):
            self.id = f'{self.phrase}_{self.word_type.name.lower()}'
    

    Demo:

    >>> from types import SimpleNamespace
    >>> wt = SimpleNamespace(name='Python')
    >>> WordItem('await', wt)
    WordItem(id='await_python', phrase='await', word_type=namespace(name='Python'))