简体   繁体   English

将参数传递给冻结的超级数据类

[英]Passing parameters to frozen super dataclass

I have a simple (frozen) dataclass inheritance as follows:我有一个简单的(冻结的)数据类 inheritance 如下:

from attrs import frozen

@frozen
class Interval:
    left: str
    right: str

@frozen
class RealInterval(Interval):
    def __attrs_pre_init__(self) -> None:
        super().__init__("-oo", "+oo")

x = RealInterval()

According to the documentation , it looks promising:根据文档,它看起来很有希望:

attrs_pre_init is automatically detected and run before attrs starts initializing. attrs_pre_init会在 attrs 开始初始化之前自动检测并运行。 This is useful if you need to inject a call to super().如果您需要注入对 super() 的调用,这很有用。 init ()初始化()

But when I check with mypy I get:但是当我检查mypy时,我得到:

$ mypy example.py 
example.py:13: error: Missing positional arguments "left", "right" in call to "RealInterval"
Found 1 error in 1 file (checked 1 source file)

Note that this is not a duplicate of this :请注意,这不是this的副本:

This should work even without attrs module即使没有attrs模块,这也应该可以工作

from dataclasses import dataclass

@dataclass(frozen=True)
class Interval:
    left: str
    right: str

@dataclass(frozen=True)
class RealInterval(Interval):
    def __init__(self) -> None:
        super().__init__("-oo", "+oo")

x = RealInterval()

__init__ of the subclass runs before __init__ of the superclass.子类的__init__在超类的__init__之前运行。

This can be done with attrs with replacing @dataclass(frozen=True) with @frozen .这可以通过attrs来完成,将@dataclass(frozen=True)替换为@frozen

Notice that this overrides the default __init__ method of the subclass.请注意,这会覆盖子类的默认__init__方法。

This is not how attrs (and for that matter: dataclasses work).这不是attrs的方式(就此而言:数据类的工作方式)。

The __init__ is written for specifically the attributes you're defining for performance reasons. __init__是专门为您出于性能原因定义的属性而编写的。

The easiest solution for your use-case is overriding the attributes:对于您的用例,最简单的解决方案是覆盖属性:

@frozen
class RealInterval(Interval):
    left: str = "-oo"
    right: str = "+oo"

Which gives you:这给了你:

>>> RealInterval()
RealInterval(left='-oo', right='+oo')
>>> RealInterval("foo", "bar")
RealInterval(left='foo', right='bar')

The pre_init logic is when you're subclassing classes you don't own, but that need their __init__ called. pre_init 逻辑是当你继承你不拥有的类时,但需要调用它们的__init__ That's true for some GUI kits for example.例如,某些 GUI 工具包就是如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM