Search code examples
pythonpython-3.xpython-dataclasses

How to compare dataclasses?


I would like to compare two global dataclasses in terms of equality. I changed the field in one of the dataclasses and python still insists on telling me, that those objects are equal. I don't know how internally dataclasses work, but when I print asdict I get an empty dictionary... What am I doing wrong and how can I compare dataclasses by checking for equality of its members?

I'm using Python 3.9.4

from dataclasses import dataclass, asdict

@dataclass
class TestClass:
    field1 = None
    field2 = False

test1 = TestClass()
test2 = TestClass()

def main():
    global test1
    global test2

    test2.field2 = True

    print('Test1:        ', id(test1), asdict(test1), test1.field1, test1.field2)
    print('Test2:        ', id(test2), asdict(test2), test2.field1, test2.field2)
    print('Are equal?    ', test1 == test2)
    print('Are not equal?', test1 != test2)

if __name__ == '__main__':
    main()

Output:

Test1:         2017289121504 {} None False
Test2:         2017289119296 {} None True
Are equal?     True
Are not equal? False

Solution

  • For Python to recognize fields of a dataclass, those fields should have PEP 526 type annotations.

    For example:

    from typing import Optional
    
    @dataclass
    class TestClass:
        field1: Optional[str] = None
        field2: bool = False
    

    With that definition comparisons and asdict work as expected:

    In [2]: TestClass(field2=True) == TestClass()
    Out[2]: False
    
    In [3]: asdict(TestClass(field2=True))
    Out[3]: {'field1': None, 'field2': True}