How to ignore attributes with the value None when initializing a class object?

109 Views Asked by At

Using a simple code example. There is a simple class, and a child:

from dataclasses import dataclass

@dataclass
class TestMain:
    one_test: int = None
    two_test: int = None


@dataclass
class SecondTest(TestMain):
    three_test: int = None
    four_test: int = None

I am creating an object specifying a dictionary, but not all attributes are specified in the dictionary:

test_data = {'one_test': 1,
             'two_test': 2,
             'three_test': 3}
test_object = SecondTest(**test_data)

If I continue to interact with the object, or look through test_data.__dict__, then I will see the attribute four_test = None.

Please specify how to do it correctly so that when creating objects, all the attributes that are not specified are not taken into account in any way? What is the best way to get rid of them, not to take them into account in the object?

I tried using asdict:

dict_object = asdict(test_object, dict_factory=lambda x: {k: v for (k, v) in x if v is not None})

I think this is redundant. There should be something simpler, without unnecessary transformations.

1

There are 1 best solutions below

1
Alex On BEST ANSWER

Here is the solution to your problem:

from dataclasses import dataclass
from typing import Optional


@dataclass
class A:
    first: Optional[int] = None
    second: Optional[int] = None

    def __post_init__(self) -> None:
        for key, value in tuple(self.__dict__.items()):
            if value is None:
                # Empty class item will be deleted.
                del self.__dict__[key]


@dataclass
class B (A):
    third: Optional[int] = None
    fourth: Optional[int] = None


if __name__ == '__main__':
    DICT = {"first": 1, "second": 2, "fourth": 4}
    test = B(**DICT)
    print(test.__dict__)
{'first': 1, 'second': 2, 'fourth': 4}