gpt4 book ai didi

Python dataclasses.dataclass 引用变量而不是实例变量

转载 作者:行者123 更新时间:2023-12-04 01:19:07 29 4
gpt4 key购买 nike

c1c2 的构造函数中的默认值应该为bb 生成新的实例变量。相反,它看起来像 c1.ac2.a 引用了同一个变量。 @dataclass 是否正在创建类变量?这似乎与预期的功能不一致,而且我在文档中找不到任何关于类变量的信息。所以,我认为这是一个错误。有人可以向我解释如何解决吗?我应该将其报告为 python 跟踪器上的错误吗?

我知道这个问题一定与 python 通过引用传递对象和通过值传递内置类型的方式有关,因为 b 属性 (它只是一个 float )显示预期/期望的行为,而 a 属性 (这是一个用户定义的对象) 只是一个引用。

谢谢!

代码:

from dataclasses import dataclass

@dataclass
class VS:
v: float # value
s: float # scale factor

def scaled_value(self):
return self.v*self.s

@dataclass
class Container:
a: VS = VS(1, 1)
b: float = 1

c1 = Container()
c2 = Container()

print(c1)
print(c2)

c1.a.v = -999
c1.b = -999

print(c1)
print(c2)

输出:

Container(a=VS(v=1, s=1), b=1)
Container(a=VS(v=1, s=1), b=1)
Container(a=VS(v=-999, s=1), b=-999)
Container(a=VS(v=-999, s=1), b=1)

最佳答案

在 OP 的原始示例中,当定义 Container 类时,将创建单个 VS 对象。然后该对象在 Container 类的所有实例之间共享。这是一个问题,因为用户定义的类(例如 VS)会导致可变对象。因此,更改任何 Container 对象中的 a 都会更改所有其他 Container 对象中的 a

每次在初始化时实例化 Container 类时,您都希望生成一个新的 VS 对象。为此,使用 field 函数的 default_factory 是一个很好的方法。传递 lambda 函数允许所有这些内联完成。

我将一个 c 成员变量添加到另一个 VS 类的容器中,以说明这样做时成员是独立的。

from dataclasses import dataclass, field

@dataclass
class VS:
v: float # value
s: float # scale factor

def scaled_value(self):
return self.v*self.s

# Use a zero-argument lambda function for default factor function.
@dataclass
class Container:
a: VS = field(default_factory= lambda:VS(1,1) )
b: float = 1
c: VS = field(default_factory= lambda:VS(1,2) )

c1 = Container()
c2 = Container()

print(c1)
print(c2)

c1.a.v = -999
c1.c.s = -999

print(c1)
print(c2)

输出:

Container(a=VS(v=1, s=1), b=1, c=VS(v=1, s=2))
Container(a=VS(v=1, s=1), b=1, c=VS(v=1, s=2))
Container(a=VS(v=-999, s=1), b=1, c=VS(v=1, s=-999))
Container(a=VS(v=1, s=1), b=1, c=VS(v=1, s=2))

关于Python dataclasses.dataclass 引用变量而不是实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62852942/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com