Reputation: 1074
I have dataclasses with static fields on them like so:
from typing import ClassVar
from dataclasses import dataclass, asdict
@dataclass
class X:
static_field: ClassVar[str] = "static_value"
normal_field: str
@dataclass
class Y:
x: X
y = Y(x=X(normal_field="normal_value"))
asdict(y) # yields {'x': {'normal_field': 'normal_value'}}
How can I make static_field
part of the output? The field static_field
should never be set when instantiating the class.
Upvotes: 2
Views: 1201
Reputation: 5030
This solution uses an undocumented feature, the __dataclass_fields__
attribute, but it works at least in Python 3.9:
from dataclasses import dataclass
from typing import Dict, Any, ClassVar
def asdict_with_classvars(x) -> Dict[str, Any]:
'''Does not recurse (see dataclasses._asdict_inner() for how to do that
right), and fails if x lacks a class variable declared in x's class
definition.'''
return dict(
(name, getattr(x, name))
for name in x.__dataclass_fields__
)
@dataclass
class Blah:
x: int
y: ClassVar[str] = 'the classvar'
print(asdict_with_classvars(Blah(22)))
Output:
{'x': 22, 'y': 'the classvar'}
If the ClassVar is declared in an abstract class and not defined, it's possible for an instance to be created that doesn't have a value for the ClassVar. In that case, the call to getattr()
will raise an AttributeError
. But it's not too hard to handle that and otherwise tailor this to your own needs.
Upvotes: 3
Reputation: 45806
From the docs:
If a field is a
ClassVar
, it is excluded from consideration as a field and is ignored by the dataclass mechanisms. SuchClassVar
pseudo-fields are not returned by the module-levelfields()
function.
So, I don't think that this is possible. You may need to rethink that part of the design.
Upvotes: 0