使用类或静态方法作为数据类中的default_factory

Kur*_*aki 10 python python-dataclasses

我想使用该方法填充数据类的属性default_factory。但是,由于工厂方法仅在该特定类的上下文中有意义,因此我想将其保留在类内部(例如作为静态或类方法)。例如:

from dataclasses import dataclass, field
from typing import List

@dataclass
class Deck:
    cards: List[str] = field(default_factory=self.create_cards)

    @staticmethod
    def create_cards():
        return ['King', 'Queen']
Run Code Online (Sandbox Code Playgroud)

但是,我在第 6 行收到此错误(如预期):

NameError:名称“self”未定义

我怎样才能克服这个问题?我不想将该create_cards()方法移出类。

mom*_*omo 7

一种可能的解决方案是将其移至__post_init__(self). 例如:

@dataclass
class Deck:
    cards: List[str] = field(default_factory=list)

    def __post_init__(self):
        if not self.cards:
            self.cards = self.create_cards()

    def create_cards(self):
        return ['King', 'Queen']
Run Code Online (Sandbox Code Playgroud)

输出:

d1 = Deck()
print(d1) # prints Deck(cards=['King', 'Queen'])
d2 = Deck(["Captain"])
print(d2) # prints Deck(cards=['Captain'])
Run Code Online (Sandbox Code Playgroud)

  • 使用“field(...)”的原因是提供默认值。如果我们省略这部分,`d1 = Deck()`就不再有效,并且必须用空列表调用,即`d1 = Deck([])`(IHMO 不太优雅)。使用建议的方法,您的代码变得非常灵活(例如,您可能允许不同类型的“cards: Union[List[str], str]”),并且始终可以正确地将其初始化为列表“self.cards = [self.cards]” `)。如果您为其他开发人员开发一个库,这也可能很有用,因为您知道,您的方法将始终以相同的方式运行并允许蹩脚的输入(“Deck(None)”) (2认同)