Search code examples
pythonpython-3.9python-dataclasses

Python get the name of all fields in a dataclass


I am trying to write a function to log dataclasses I would like to get the name of all fields in the dataclass and print the value to each (similar to how you might write a function to print a dictionary)

i.e.

@dataclasses.dataclass
class Test:
    a: str = "a value"
    b: str = "b value"


test = Test()
def print_data_class(dataclass_instance):
   fields = # get dataclass fileds
   for field in fields:
       print(f{field}: {dataclass.field})
print_data_class(test)

-->
"a"  : "a value"
"b"  : "b value"

However I haven't been able to find how to get the fields of a dataclass, does anyone know how this could be done?

Thanks


Solution

  • This example shows only a name, type and value, however, __dataclass_fields__ is a dict of Field objects, each containing information such as name, type, default value, etc.

    Using dataclasses.fields()

    Using dataclasses.fields() you can access fields you defined in your dataclass.

    fields = dataclasses.fields(dataclass_instance)
    

    Using inspect.getmembers()

    Using inspect.getmembers() you can access all fields in your dataclass.

    members = inspect.getmembers(type(dataclass_instance))
    fields = list(list(filter(lambda x: x[0] == '__dataclass_fields__', members))[0][1].values())
    

    Complete code solution

    import dataclasses
    import inspect
    
    
    @dataclasses.dataclass
    class Test:
        a: str = "a value"
        b: str = "b value"
    
    
    def print_data_class(dataclass_instance):
    
        # option 1: fields
        fields = dataclasses.fields(dataclass_instance)
    
        # option 2: inspect
        members = inspect.getmembers(type(dataclass_instance))
        fields = list(list(filter(lambda x: x[0] == '__dataclass_fields__', members))[0][1].values())
    
        for v in fields:
          print(f'{v.name}: ({v.type.__name__}) = {getattr(dataclass_instance, v.name)}')
    
    
    print_data_class(Test())
    # a: (str) = a value
    # b: (str) = b value
    
    print_data_class(Test(a="1", b="2"))
    # a: (str) = 1
    # b: (str) = 2