第一次使用dataclass,也不太擅长Python。以下行为与我迄今的理解相抵触:
from dataclasses import dataclass
@dataclass
class X:
x: int = 1
y: int = 2
@dataclass
class Y:
c1: X = X(3, 4)
c2: X = X(5, 6)
n1 = Y()
n2 = Y()
print(id(n1.c1))
print(id(n2.c1))
n1.c1.x = 99999
print(n2)这个指纹
140459664164272
140459664164272
Y(c1=X(x=99999, y=4), c2=X(x=5, y=6))为什么c1的行为像类变量?我能做些什么来保持n2.c1 != n1.c1,我需要写一个init函数吗?
我可以在Y的基础上得到合理的结果:
def __init__(self):
self.c1 = X(3, 4)
self.c2 = X(5, 6)指纹:
140173334359840
140173335445072
Y(c1=X(x=3, y=4), c2=X(x=5, y=6))发布于 2022-09-04 12:46:35
为什么
c1的行为像类变量?
因为您为它们指定了默认值,因此它们现在是一个类属性。在可变默认值部分中,提到了:
Python将默认成员变量值存储在类属性中。
但是看看这个:
@dataclass
class X:
x: int = 1
y: int = 2
@dataclass
class Y:
c1: X
c2: X = X(5, 6)
print("c1" in Y.__dict__) # False
print("c2" in Y.__dict__) # Truec1没有默认值,所以它不在类的名称空间中。
实际上,通过这样做(定义默认值),Python将c1和c2存储在实例的名称空间(n1.__dict__)和类的命名空间(Y.__dict__)中。它们是相同的对象,只传递引用:
@dataclass
class X:
x: int = 1
y: int = 2
@dataclass
class Y:
c1: X = X(3, 4)
c2: X = X(5, 6)
n1 = Y()
n2 = Y()
print("c1" in Y.__dict__) # True
print("c1" in n1.__dict__) # True
print(id(n1.c1)) # 140037361903232
print(id(n2.c1)) # 140037361903232
print(id(Y.c1)) # 140037361903232所以现在,如果你想让它们与众不同,你有几种选择:
@dataclass
class X:
x: int = 1
y: int = 2
@dataclass
class Y:
c1: X = X(3, 4)
c2: X = X(5, 6)
n1 = Y(X(3, 4), X(5, 6))
n2 = Y(X(3, 4), X(5, 6))
print("c1" in Y.__dict__) # True
print("c1" in n1.__dict__) # True
print(id(n1.c1)) # 140058585069264
print(id(n2.c1)) # 140058584543104
print(id(Y.c1)) # 140058585065088field和pass default_factoryfrom dataclasses import dataclass, field
@dataclass
class X:
x: int = 1
y: int = 2
@dataclass
class Y:
c1: X = field(default_factory=lambda: X(3, 4))
c2: X = field(default_factory=lambda: X(5, 6))
n1 = Y()
n2 = Y()
print("c1" in Y.__dict__) # False
print("c1" in n1.__dict__) # True
print(id(n1.c1)) # 140284815353136
print(id(n2.c1)) # 140284815353712在第二个选项中,由于我没有指定default参数(两者都不能混合),所以类的命名空间中不会存储任何内容。field(default=SOMETHING)是= SOMETHING的另一种表达方式。
https://stackoverflow.com/questions/73598938
复制相似问题