在OP的原始示例中,定义了VS
类时,将创建一个Container
对象。然后,该对象将在Container
类的所有实例之间共享。这是一个问题,因为诸如VS
之类的用户定义类会导致可变对象。因此,在任何a
对象中更改Container
将在所有其他a
对象中更改Container
您希望每次在初始化时实例化Container
类时都生成一个新的VS对象。为此,使用default_factory
函数的field
是解决问题的好方法。传递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=2))
Container(a=VS(v=-999,s=-999))
Container(a=VS(v=1,s=2))
,
感谢Eric S提供的解释:
“”“
c1和c2共享a的相同实例。这是可变的默认参数问题:https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
使用default_factory为每个容器创建一个新的VS。
“”“
default_factory不允许我为多个属性使用唯一的一组默认VS值,因为需要在VS数据类中定义VS默认值。例如,如果我希望a默认为VS(1,1),但我希望b默认为VS(1,2),则default_factory对我没有帮助。因此,我发现了一种解决方法,即创建关键字条目的字典并将深拷贝传递到我的Container()构造函数中(请注意,如果我不传递深拷贝,则会遇到与上述相同的问题)。这是我的最终代码段和输出:
“”“代码”“”
@dataclass
class VS:
v: float = 1 # value
s: float = 1 # scale factor
def scaled_value(self):
return self.v*self.s
@dataclass
class Container:
a: VS = field(default_factory=VS)
b: float = 1
ip = {'a':VS(2,1),'b':1}
c1 = Container(**deepcopy(ip))
c2 = Container(**deepcopy(ip))
print(c1)
print(c2)
c1.a.v = 0
c1.b = 0
print(c1)
print(c2)
“”“”输出“”“
容器(a = VS(v = 2,s = 1),b = 1)
容器(a = VS(v = 2,s = 1),b = 1)
容器(a = VS(v = 0,s = 1),b = 0)
容器(a = VS(v = 2,s = 1),b = 1)
本文链接:https://www.f2er.com/1954610.html