Python get the name of all fields in a dataclass

Question:

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

Asked By: Pioneer_11

||

Answers:

use the __dict__ property

def print_data_class(dataclass_instance):
   fields = [(attribute, value) for attribute, value in dataclass_instance.__dict__.items()]
   for field in fields:
       print("{}: {}".format(*field))
Answered By: Dean Van Greunen

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, k)}')


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
Answered By: K.Mat