web-dev-qa-db-ja.com

デフォルトのリスト引数をデータクラスに渡す

クラスにデフォルトの引数を渡したいのですが、どういうわけか問題があります。

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

何が悪いのですか?

10
H.Bukhari

the _dataclasses.field_ docs から:

field()のパラメーターは次のとおりです。

  • default_factory:指定する場合、それはゼロ引数の呼び出し可能でなければなりませんこのフィールドにデフォルト値が必要な場合に呼び出されます。以下で説明するように、これは他の目的の中でも特に、変更可能なデフォルト値を持つフィールドを指定するために使用できます。 defaultとdefault_factoryの両方を指定するとエラーになります。

あなたの_default_factory_は0引数の呼び出し可能ではなくリストです。これがエラーの理由です。

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

代わりにラムダ関数を使用してください:

_@dataclass
class Pizza():
    ingredients: List = field(default_factory=lambda: ['dow', 'tomatoes'])
_
16
Aran-Fey

複雑なデータ型の場合、次のように略記する傾向があります。

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")})
3
gessulat