含ctypes对象的dataclasses内存分配重叠问题咨询
问题原因解析
核心问题:类属性与实例属性的误用
你在dataclass中定义的x = ctypes.c_int(0)和y = ctypes.c_int(0)是类属性,而非实例属性。类属性绑定在类本身,所有该类的实例都会共享同一个类属性对象——而ctypes.c_int是可变对象,这就导致所有Point实例的x、y都指向同一块内存地址。
当你在TestObj中定义point1 = Point()和point2 = Point()时,这两个Point实例的x、y本质上是同一个ctypes.c_int(0)对象的引用。所以调用inc修改point1.x和point1.y时,point2的对应属性也会被修改——因为它们指向的是同一块内存。
为什么更换类名(Point2)就正常?
Point2是一个独立的类,它的x、y类属性属于Point2自己,和Point类的x、y是完全不同的ctypes.c_int对象。因此:
TestObj.point1(Point实例)共享Point类的x、yTestObj.point2(Point2实例)共享Point2类的x、y
这两组属性指向不同的内存地址,修改其中一组自然不会影响另一组。
正确的写法:使用实例属性
要让每个dataclass实例拥有独立的ctypes对象,需要定义实例属性,并通过default_factory为每个实例创建新的ctypes对象(直接赋值默认值会再次变成类级别的共享对象):
import dataclasses import ctypes @dataclasses.dataclass class Point: x: ctypes.c_int = dataclasses.field(default_factory=lambda: ctypes.c_int(0)) y: ctypes.c_int = dataclasses.field(default_factory=lambda: ctypes.c_int(0)) @dataclasses.dataclass class TestObj: point1: Point = dataclasses.field(default_factory=Point) point2: Point = dataclasses.field(default_factory=Point)
这样每个Point实例都会生成自己独有的x、y对象,TestObj的point1和point2的属性就不会共享内存,调用inc后只会修改point1的属性。
内容的提问来源于stack exchange,提问作者frank
相关产品推荐
相关产品推荐

