python dataclasses with optional attributes
from dataclasses import dataclass
@dataclass
class CampingEquipment:
knife: bool
fork: bool
missing_flask_size: ? # removed field() per answers below.
kennys_stuff = {
'knife':True,
'fork': True
}
print(CampingEquipment(**kennys_stuff))
gives me:
TypeError: CampingEquipment.__init__() missing 1 required positional argument: 'missing_flask_size'
How do you make Optional attr's of a dataclass?
Edit
What I meant by optional wasn't clear. By Optional I mean __dict__
may contain the key "missing_flask_size" or not. If I set a default value then the key will be there and it shouldn't be in some cases. I want to check it's type if it is there.
I tried moving the field(init=False) to the type location (after the colon) so I could make it more explicit as to the thing I wanted optional would be the key and not the value. That was just confusing for everyone, including me, so it's removed.
So I want this test to pass:
with pytest.raises(AttributeError):
ce = CampingEquipment(**kennys_stuff)
print(ce.missing_flask_size)
Solution 1:
A field
object is supposed to be used with =
, like a default value, not :
like an annotation.
Specifying init=False
for a field means the caller can't pass in a value for it at all. init=False
fields are supposed to be set in __post_init__
, like this:
@dataclass
class Example:
a: int
b: int
c: int = field(init=False)
def __post_init__(self):
self.c = self.a + self.b
print(Example(1, 2).c) # prints 3
If you want to make it optional for the caller to provide a value, you can set a default value. If the caller doesn't provide a value, the default will be used instead:
@dataclass
class Example:
a: int
b: int
c: int = -1
print(Example(1, 2).c) # prints -1
print(Example(1, 2, 3).c) # prints 3