Python 具有可变默认参数的数据类继承 returns 零值
Python dataclass inheritance with mutable default arguments returns zero-value
我正在尝试从包含笛卡尔坐标 x、y 和 z 的 3 个列表中计算类似半径的数量。
下面是我重现我面临的问题的最小代码示例;
child-class 计算 radius-quantity 但 returns 为零值。
这是什么原因,如何解决?
脚本:
# -*- 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
因为您正在 覆盖 __post_init__
,所以列表仍然是空的,因为除了空列表默认值之外,它们从未被初始化过。如果你也想要它的行为,你必须调用你正在覆盖的 super-class 方法。
你想要的是:
def __post_init__(self):
super().__post_init__()
self.r = self.modulus(self.x, self.y, self.z)
请注意您的类型提示的几件事:您可能希望 float
用于子 class 中的 r
字段,以及 return modulus
的类型:
def modulus(self, *args) -> 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
我正在尝试从包含笛卡尔坐标 x、y 和 z 的 3 个列表中计算类似半径的数量。 下面是我重现我面临的问题的最小代码示例; child-class 计算 radius-quantity 但 returns 为零值。 这是什么原因,如何解决?
脚本:
# -*- 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
因为您正在 覆盖 __post_init__
,所以列表仍然是空的,因为除了空列表默认值之外,它们从未被初始化过。如果你也想要它的行为,你必须调用你正在覆盖的 super-class 方法。
你想要的是:
def __post_init__(self):
super().__post_init__()
self.r = self.modulus(self.x, self.y, self.z)
请注意您的类型提示的几件事:您可能希望 float
用于子 class 中的 r
字段,以及 return modulus
的类型:
def modulus(self, *args) -> 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