Home > Software design >  how to safely initialize a dataclass based on a dict with unexpected keys?
how to safely initialize a dataclass based on a dict with unexpected keys?

Time:12-08

I'd like to initialize A from a dict which can contain unexpected keys. I'd like to initialize with the given, known keys and ignore the rest

` from dataclasses import dataclass

@dataclass class A: a: str b: int

a1 = A({'a': 'Foo', 'b': 123}) # works a2 = A({'a': 'Foo', 'b': 123, 'c': 'unexpected'}) # raises TypeError `

Is there a Python feature that I'm missing or do I have to filter the dict upfront?

CodePudding user response:

Another option is to use the dataclasses.fields function with a classmethod.

from dataclasses import dataclass, fields


@dataclass
class A:
    a: str
    b: int

    @classmethod
    def from_dict(cls, d: dict) -> "A":
        field_names = (field.name for field in fields(cls))
        return cls(**{k: v for k, v in d.items() if k in field_names})

a1 = A.from_dict({'a': 'Foo', 'b': 123})
a2 = A.from_dict({'a': 'Foo', 'b': 123, 'c': 'unexpected, but who cares?'})

CodePudding user response:

Apparently it is easier than I expected...

from dataclasses import dataclass

@dataclass(init=False)
class A:
    a: str
    b: int

    def __init__(self, a: str, b: int, **therest):
        self.a = a
        self.b = b

The init=False parameter of the dataclass decorator indicates you will provide a custom __init__ function. Docs here

CodePudding user response:

just replace built-in dataclass with pydantic implementation

from pydantic.dataclasses import dataclass

@dataclass
class A:
    a: str
    b: int

a1 = A(**{'a': 'Foo', 'b': 123}) # works
a2 = A(**{'a': 'Foo', 'b': 123, 'c': 'unexpected'})
print(a1, a2) # prints A(a='Foo', b=123) A(a='Foo', b=123)
  • Related