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(dict(members)['__dataclass_fields__'].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(dict(members)['__dataclass_fields__'].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
Answer from K.Mat on Stack OverflowThis 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(dict(members)['__dataclass_fields__'].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(dict(members)['__dataclass_fields__'].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
Also, you can use __annotations__, well, because data fields are always annotated. This is the essense of dataclasses usage.
It works with classes
fields = list(Test.__annotations__)
and with instances
fields = list(test.__annotations__)
There should be noted that it doesn't work with dataclass subclasses. Obviously. However, simplicity gives you fields names directly, without extra code for extraction from Field objects.
How can I get Python 3.7 new dataclass field types? - Stack Overflow
python - How do I pull out the attributes or field names from a dataclass? - Stack Overflow
python - Extract all field names from nested dataclasses - Stack Overflow
Annotations using inner field names and values of TypedDicts/dataclass like objects - Ideas - Discussions on Python.org
Inspecting __annotations__ gives you the raw annotations, but those don't necessarily correspond to a dataclass's field types. Things like ClassVar and InitVar show up in __annotations__, even though they're not fields, and inherited fields don't show up.
Instead, call dataclasses.fields on the dataclass, and inspect the field objects:
field_types = {field.name: field.type for field in fields(MyClass)}
Neither __annotations__ nor fields will resolve string annotations. If you want to resolve string annotations, the best way is probably typing.get_type_hints. get_type_hints will include ClassVars and InitVars, so we use fields to filter those out:
resolved_hints = typing.get_type_hints(MyClass)
field_names = [field.name for field in fields(MyClass)]
resolved_field_types = {name: resolved_hints[name] for name in field_names}
from dataclasses import dataclass
@dataclass
class MyClass:
id: int = 0
name: str = ''
myclass = MyClass()
myclass.__annotations__
>> {'id': int, 'name': str}
myclass.__dataclass_fields__
>> {'id': Field(name='id',type=<class 'int'>,default=0,default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD),
'name': Field(name='name',type=<class 'str'>,default='',default_factory=<dataclasses._MISSING_TYPE object at 0x0000000004EED668>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)}
on a side note there is also:
myclass.__dataclass_params__
>>_DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=False)
The answer depends on whether or not you have access to an object of the class.
Just using the class
If you only have access to the class, then you can use dataclasses.fields(C) which returns a list of field objects (each of which has a .name property):
[field.name for field in dataclasses.fields(C)]
From an existing object
If you have a constructed object of the class, then you have two additional options:
- Use
dataclasses.fieldson the object:
[field.name for field in dataclasses.fields(obj)]
- Use
dataclasses.asdict(obj)(as pointed out by this answer) which returns a dictionary from field name to field value. It sounds like you are only interested in the.keys()of the dictionary:
dataclasses.asdict(obj).keys() # gives a dict_keys object
list(dataclasses.asdict(obj).keys()) # gives a list
list(dataclasses.asdict(obj)) # same
Full example
Here are all of the options using your example:
from dataclasses import dataclass, fields, asdict
@dataclass
class C:
x: int
y: int
z: int
t: int
# from the class
print([field.name for field in fields(C)])
# using an object
obj = C(1, 2, 3, 4)
print([field.name for field in fields(obj)])
print(asdict(obj).keys())
print(list(asdict(obj).keys()))
print(list(asdict(obj)))
Output:
['x', 'y', 'z', 't']
['x', 'y', 'z', 't']
dict_keys(['x', 'y', 'z', 't'])
['x', 'y', 'z', 't']
['x', 'y', 'z', 't']
You can use the asdict method of the dataclasses module. For example:
from dataclasses import dataclass, asdict
@dataclass
class Person:
age: int
name: str
adam = Person(25, 'Adam')
# if you want the keys
print(asdict(adam).keys()) # dict_keys(['age', 'name'])
# if you want the values
print(asdict(adam).values()) # dict_values([25, 'Adam'])
Both methods above return a View object which you can iterate on, or you can convert it to list using list(...).