Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a dataclass field without annotating the type?

Tags:

When there is a field in a dataclass for which the type can be anything, how can you omit the annotation?

@dataclass
class Favs:
    fav_number: int = 80085
    fav_duck = object()
    fav_word: str = 'potato'

It seems the code above doesn't actually create a field for fav_duck. It just makes that a plain old class attribute.

>>> Favs()
Favs(fav_number=80085, fav_word='potato')
>>> print(*Favs.__dataclass_fields__)
fav_number fav_word
>>> Favs.fav_duck
<object at 0x7fffea519850>
like image 244
wim Avatar asked Apr 19 '18 22:04

wim


2 Answers

The dataclass decorator examines the class to find fields, by looking for names in __annotations__. It is the presence of annotation which makes the field, so, you do need an annotation.

You can, however, use a generic one:

@dataclass
class Favs:
    fav_number: int = 80085
    fav_duck: 'typing.Any' = object()
    fav_word: str = 'potato'
like image 53
wim Avatar answered Oct 25 '22 19:10

wim


According to PEP 557 which defines the meaning of data classes,

The dataclass decorator examines the class to find fields. A field is defined as any variable identified in __annotations__. That is, a variable that has a type annotation.

Which is to say that the premise of this question (e.g. "How can I use dataclass with a field that has no type annotation) must be rejected. The term 'field' in the context of dataclass necessitates that the attribute has a type annotation by definition.

Note that using a generic type annotation like typing.Any is not the same as having an unannotated attribute, since the attribute will appear in __annotations__.

Finally, the helper function make_dataclass will automatically use typing.Any for the type annotation in cases when only an attribute name is supplied, and this is also mentioned in the PEP with an example.

like image 23
ely Avatar answered Oct 25 '22 18:10

ely