带有可变默认参数的Python数据类继承返回零值

带有可变默认参数的Python数据类继承返回零值,python,python-3.x,oop,inheritance,python-dataclasses,Python,Python 3.x,Oop,Inheritance,Python Dataclasses,我试图从包含笛卡尔坐标x,y和z的3个列表中计算一个类似半径的量。 下面是我的最小代码示例,用于重现我所面临的问题; 子类计算半径数量,但返回零值。 原因是什么?如何解决 脚本: # -*- coding: utf-8 -*- from dataclasses import dataclass, field from typing import List @dataclass class LoadHalo: x: List = field(default_factory=list)

我试图从包含笛卡尔坐标x,y和z的3个列表中计算一个类似半径的量。 下面是我的最小代码示例,用于重现我所面临的问题; 子类计算半径数量,但返回零值。 原因是什么?如何解决

脚本:

# -*- coding: utf-8 -*-

from dataclasses import dataclass, field
from typing import List


@dataclass
class LoadHalo:
    x: List = field(default_factory=list)
    y: List = field(default_factory=list)
    z: List = field(default_factory=list)

    def __post_init__(self):
        self.x = [1, 2, 3]
        self.y = [1, 3, 5]
        self.z = [1, 4, 7]


@dataclass
class BinHalo(LoadHalo):
    r: List = field(default_factory=list)

    def __post_init__(self):
        self.r = self.modulus(self.x, self.y, self.z)

    def modulus(self, *args):
        """Modulus of vector of arbitrary size."""
        return sum([i ** 2 for containers in args for i in containers]) ** .5


halo = BinHalo()
print(f"halo.x: {halo.x}")
print(f"halo.r: {halo.r}")
输出x和r的以下值:

halo.x: []
halo.r: 0.0
因为您正在重写uu post_init uuuu,所以列表仍然是空的,因为除了空列表默认值之外,它们从未被初始化过。如果还需要其行为,则必须调用要重写的超类方法

您需要的是以下内容:

def __post_init__(self):
    super().__post_init__()
    self.r = self.modulus(self.x, self.y, self.z)
注意类型提示中的几点:您可能希望子类中的r字段和模数的返回类型使用float:

此外,还应使用float对象初始化默认列表,以便编写:

x: List[float]
对于列表字段,因为您可能希望使用浮点数学

总而言之,我对一切都有如下定义:

from dataclasses import dataclass, field
from typing import List


@dataclass
class LoadHalo:
    x: List[float] = field(default_factory=list)
    y: List[float] = field(default_factory=list)
    z: List[float] = field(default_factory=list)

    def __post_init__(self) -> None:
        self.x = [1.0, 2.0, 3.0]
        self.y = [1.0, 3.0, 5.0]
        self.z = [1.0, 4.0, 7.0]


@dataclass
class BinHalo(LoadHalo):
    r: float = 0.0 # or whatever is suitable

    def __post_init__(self) -> None:
        super().__post_init__()
        self.r = self.modulus(self.x, self.y, self.z)

    def modulus(self, *args: List[float]) -> float:
        """Modulus of vector of arbitrary size."""
        return sum([i ** 2 for containers in args for i in containers]) ** .5

在self.r=self.moduleusself.x、self.y、self.zVery之前添加super.\uuuuuu post\uuu init\uuuuuuuuuu非常清晰的工作示例。这正是我想要的。谢谢你@juanpa。arrivillaga@GustavRasmussen不用担心,你应该考虑使用MyPy来检查你的代码。
from dataclasses import dataclass, field
from typing import List


@dataclass
class LoadHalo:
    x: List[float] = field(default_factory=list)
    y: List[float] = field(default_factory=list)
    z: List[float] = field(default_factory=list)

    def __post_init__(self) -> None:
        self.x = [1.0, 2.0, 3.0]
        self.y = [1.0, 3.0, 5.0]
        self.z = [1.0, 4.0, 7.0]


@dataclass
class BinHalo(LoadHalo):
    r: float = 0.0 # or whatever is suitable

    def __post_init__(self) -> None:
        super().__post_init__()
        self.r = self.modulus(self.x, self.y, self.z)

    def modulus(self, *args: List[float]) -> float:
        """Modulus of vector of arbitrary size."""
        return sum([i ** 2 for containers in args for i in containers]) ** .5