Passing default list argument to dataclasses
Question:
I would like to pass default argument in my class,
but somehow I am having problem:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Pizza():
ingredients: List = field(default_factory=['dow', 'tomatoes'])
meat: str = field(default='chicken')
def __repr__(self):
return 'preparing_following_pizza {} {}'.format(self.ingredients, self.meat)
If I now try to instantiate Pizza
, I get the following error:
>>> my_order = Pizza()
Traceback (most recent call last):
File "pizza.py", line 13, in <module>
Pizza()
File "<string>", line 2, in __init__
TypeError: 'list' object is not callable
What am I doing wrong?
Answers:
From the dataclasses.field
docs:
The parameters to field()
are:
- default_factory: If provided, it must be a zero-argument callable that
will be called when a default value is needed for this field. Among
other purposes, this can be used to specify fields with mutable
default values, as discussed below. It is an error to specify both
default and default_factory.
Your default_factory
is not a 0-argument callable but a list, which is the reason for the error:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Pizza():
ingredients: List = field(default_factory=['dow', 'tomatoes']) # <- wrong!
Use a lambda function instead:
@dataclass
class Pizza():
ingredients: List = field(default_factory=lambda: ['dow', 'tomatoes'])
For complex datatypes i tend to abbreviate like so:
import copy
from dataclasses import dataclass, field
from typing import Dict, Tuple
def default_field(obj):
return field(default_factory=lambda: copy.copy(obj))
@dataclass
class C:
complex_attribute: Dict[str, Tuple[int, str]] = default_field({"a": (1, "x"), "b": (1, "y")})
I would like to pass default argument in my class,
but somehow I am having problem:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Pizza():
ingredients: List = field(default_factory=['dow', 'tomatoes'])
meat: str = field(default='chicken')
def __repr__(self):
return 'preparing_following_pizza {} {}'.format(self.ingredients, self.meat)
If I now try to instantiate Pizza
, I get the following error:
>>> my_order = Pizza()
Traceback (most recent call last):
File "pizza.py", line 13, in <module>
Pizza()
File "<string>", line 2, in __init__
TypeError: 'list' object is not callable
What am I doing wrong?
From the dataclasses.field
docs:
The parameters to
field()
are:
- default_factory: If provided, it must be a zero-argument callable that
will be called when a default value is needed for this field. Among
other purposes, this can be used to specify fields with mutable
default values, as discussed below. It is an error to specify both
default and default_factory.
Your default_factory
is not a 0-argument callable but a list, which is the reason for the error:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Pizza():
ingredients: List = field(default_factory=['dow', 'tomatoes']) # <- wrong!
Use a lambda function instead:
@dataclass
class Pizza():
ingredients: List = field(default_factory=lambda: ['dow', 'tomatoes'])
For complex datatypes i tend to abbreviate like so:
import copy
from dataclasses import dataclass, field
from typing import Dict, Tuple
def default_field(obj):
return field(default_factory=lambda: copy.copy(obj))
@dataclass
class C:
complex_attribute: Dict[str, Tuple[int, str]] = default_field({"a": (1, "x"), "b": (1, "y")})