将默认列表参数传递给数据类

时间:2018-08-28 17:54:33

标签: python python-3.x oop type-hinting

我想在我的课程中传递默认参数, 但不知何故我遇到了问题:

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)

如果现在尝试实例化Pizza,则会出现以下错误:

>>> 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

我在做什么错了?

3 个答案:

答案 0 :(得分:10)

来自the dataclasses.field docs

  

field()的参数为:

     
      
  • default_factory::如果提供,则必须为零参数可调用,   需要此字段的默认值时将调用。其中   其他目的,可以用来指定可变的字段   默认值,如下所述。两者都指定是错误的   默认和default_factory。
  •   

您的default_factory不是可调用的0参数,而是一个列表,这是导致错误的原因:

@dataclass
class Pizza():
    ingredients: List = field(default_factory=['dow', 'tomatoes'])  # <- wrong!

改为使用lambda函数:

@dataclass
class Pizza():
    ingredients: List = field(default_factory=lambda: ['dow', 'tomatoes'])

答案 1 :(得分:2)

对于复杂的数据类型,我倾向于这样缩写:

from dataclasses import dataclass, field
from typing import Dict, Tuple

def default_field(obj):
    return field(default_factory=lambda: obj)

@dataclass
class C:
    complex_attribute: Dict[str, Tuple[int, str]] = default_field({"a": (1, "x"), "b": (1, "y")})

答案 2 :(得分:-1)

这种方法不使用typingdataclasses模块,但是您可能想尝试以下方法:

class Pizza():
    defaults = {
        'toppings': ['peppers', 'cheese'],
        'ingredients': ['dough', 'tomato'],
        'meat': 'chicken'
    }
    def __init__(self, toppings=None, meat=None, ingredients=None):
        if toppings is None:
            setattr(self, 'toppings', defaults['toppings'])

         if meat is None:
            setattr(self, 'meat', defaults['meat'])

         if ingredients is None:
            setattr(self, 'ingredients', defaults['ingredients'])

我本可以将__init__中的参数设置为其默认值,但是我认为此可能在引用同一列表时会引起冲突。