【问题标题】:How to reference `self` in dataclass' fields?如何在数据类字段中引用“self”?
【发布时间】:2020-07-24 00:39:45
【问题描述】:

我正在尝试做相当于:

class A:
    def __init__(self):
        self.b = self.get_b()

    def get_b(self):
        return 1

使用@dataclass。我想在这里使用@dataclass,因为还有其他(省略的)字段从提供的构造函数参数初始化。 b 是从实例方法的结果初始化的字段之一。执行这个:

@dataclass
class A:
    b = self.get_b()

    def get_b(self):
        return 1

表明self 未在b 的范围内定义。是否可以在此处获得对self 的引用?

【问题讨论】:

  • 调用 your_other_class.function 而不是使用 self 因为它不在同一个上下文中。

标签: python self python-dataclasses


【解决方案1】:

使用__post_init__ 方法。

from dataclasses import dataclass, field


@dataclass
class A:
    b: int = field(init=False)

    def __post_init__(self):
        self.b = self.get_b()

不完全是一种改进,是吗?分配给字段的默认值相当于__init__中的默认参数值,例如,

def __init__(self, b=0):
    self.b = b

就像你不能在这样的参数默认值中使用self,你也不能将它用作字段默认值。默认值必须在实例实际存在之前存在

我们显式创建该字段,以便我们可以传递init=False,防止生成的__init__ 方法期望一个参数来初始化self.b


如果函数get_b真的独立于一个实例(也就是说,你不需要A的实例来返回值1),你可以使用一个已经定义的函数作为默认工厂。

from dataclasses import dataclass, field


@dataclass
class A:
    def get_b(self=None):
        return 1

    b: int = field(default_factory=get_b, init=False)

这里,get_b 将作为零参数的函数调用(因此定义中self 的默认值),而不是从类实例中调用。不过,这是相当不正统的,我不建议您像这样构建您的代码。

【讨论】:

  • 对于答案的最后一部分,将函数设为静态而不是说self=None 不是更常见吗?
  • 应该是这样,但我不想做出这种改变,以防 get_b 稍后也被用作实例方法(尽管没有理由让它成为一个实例方法)。
  • 另外,staticmethod 的实例本身实际上是不可调用的;您必须将其作为类或实例的属性调用,以便其 __get__ 方法返回可调用对象。在这里,实际的函数get_b 需要传递给field。您必须定义get_b,将其用作default_factory 参数,然后将名称重新绑定到带有get_b = staticmethod(get_b) 的静态方法。
  • 嗯,也许让它成为一个静态方法,然后使用field(default_factory=get_b.__func__, init=False) 不是坏。
  • 我对此并不感兴趣,但我想先看看一个真实的例子,说明为什么get_b 存在的原因,然后再决定如何处理它。
猜你喜欢
  • 2013-04-18
  • 1970-01-01
  • 2020-06-20
  • 1970-01-01
  • 2022-10-15
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
相关资源
最近更新 更多