今天在创建数据类时,遇到一个问题。发现数据出现了问题。代码如下:
from dataclasses import dataclass
@dataclass
class InPut:
start:bool = False
stop:bool = 0
fault:bool = None
interval:int = 0
@dataclass
class OutPut:
星启动:bool = None
主启动:bool = None
三角启动:bool = None
@dataclass
class Temp():
...
@dataclass
class Motor:
input:InPut = InPut()
outPut:OutPut = OutPut()
temp:Temp = Temp()
上面创建了4个类,其中Motorl 里面的3个属性是由上面的3个数据类对象构成。这样Motor类就会很方便的操作输入和输出。然后分别写两个类,没个类属性保存Motor对象代码如下:
class Devices:
motor1 = Motor()
motor2 = Motor()
motor3 = Motor()
motor4 = Motor()
motor5 = Motor()
class HMI:
input:InPut = InPut(interval=50)
input2:InPut = InPut(interval=100)
input3:InPut = InPut(interval=300)
input4:InPut = InPut(interval=400)
input5:InPut = InPut(interval=600)
在写个映射函数,把HMI类的数据映射给Devices类,代码如下:
def mapping():
Devices.motor1.input.interval = HMI.input.interval
Devices.motor2.input.interval = HMI.input2.interval
Devices.motor3.input.interval = HMI.input3.interval
Devices.motor4.input.interval = HMI.input4.interval
Devices.motor5.input.interval = HMI.input5.interval
print("motor1.input.interval:",Devices.motor1.input.interval)
print("motor2.input.interval:",Devices.motor2.input.interval)
print("motor3.input.interval:",Devices.motor3.input.interval)
print("motor4.input.interval:",Devices.motor4.input.interval)
print("motor5.input.interval:",Devices.motor5.input.interval)
if __name__ == '__main__':
mapping()
貌似没问题,打印结果如下:
motor1.input.interval: 600
motor2.input.interval: 600
motor3.input.interval: 600
motor4.input.interval: 600
motor5.input.interval: 600
结果都是600,怎么会这样?先把motor对象的ID打出来。
def mapping():
Devices.motor1.input.interval = HMI.input.interval
Devices.motor2.input.interval = HMI.input2.interval
Devices.motor3.input.interval = HMI.input3.interval
Devices.motor4.input.interval = HMI.input4.interval
Devices.motor5.input.interval = HMI.input5.interval
# print("motor1.input.interval:",Devices.motor1.input.interval)
# print("motor2.input.interval:",Devices.motor2.input.interval)
# print("motor3.input.interval:",Devices.motor3.input.interval)
# print("motor4.input.interval:",Devices.motor4.input.interval)
# print("motor5.input.interval:",Devices.motor5.input.interval)
print("motor1",id(Devices.motor1))
print("motor2",id(Devices.motor2))
print("motor3",id(Devices.motor3))
print("motor4",id(Devices.motor4))
print("motor5",id(Devices.motor5))
if __name__ == '__main__':
mapping()
#运行结果:
motor1 2213315589264
motor2 2213317258400
motor3 2213316869232
motor4 2213317974672
motor5 2213317975920
def mapping():
Devices.motor1.input.interval = HMI.input.interval
Devices.motor2.input.interval = HMI.input2.interval
Devices.motor3.input.interval = HMI.input3.interval
Devices.motor4.input.interval = HMI.input4.interval
Devices.motor5.input.interval = HMI.input5.interval
# print("motor1.input.interval:",Devices.motor1.input.interval)
# print("motor2.input.interval:",Devices.motor2.input.interval)
# print("motor3.input.interval:",Devices.motor3.input.interval)
# print("motor4.input.interval:",Devices.motor4.input.interval)
# print("motor5.input.interval:",Devices.motor5.input.interval)
print("motor1.input",id(Devices.motor1.input))
print("motor2.input",id(Devices.motor2.input))
print("motor3.input",id(Devices.motor3.input))
print("motor4.input",id(Devices.motor4.input))
print("motor5.input",id(Devices.motor5.input))
结果
motor1.input 2891784968080
motor2.input 2891784968080
motor3.input 2891784968080
motor4.input 2891784968080
motor5.input 2891784968080
上面的id是一样的,说明指向了同一个内存地址。这里就有一个坑。
分析原因及解决办法如下:
在这个代码中,因为使用了`dataclass`的默认值初始化方式,会导致所有`Motor`类的实例都共享相同的`InPut`类的实例,从而导致它们的`id`都是相同的。如果希望每个`Motor`实例拥有独立的`InPut`实例,可以通过在`Motor`类的`__post_init__`方法中为`input`属性赋予新的`InPut`实例来实现。下方修改代码:
@dataclass
class Motor:
input: InPut = None
outPut: OutPut = OutPut()
temp: Temp = Temp()
def __post_init__(self):
if self.input is None:
self.input = InPut()
通过在`Motor`类中定义`__post_init__`方法,可以确保每个`Motor`实例都有独立的`InPut`实例,从而使它们的`id`不再相同。
完整代码如下:
from dataclasses import dataclass
@dataclass
class InPut:
start:bool = False
stop:bool = 0
fault:bool = None
interval:int = 0
@dataclass
class OutPut:
星启动:bool = None
主启动:bool = None
三角启动:bool = None
@dataclass
class Temp():
...
@dataclass
class Motor:
input:InPut = None
outPut:OutPut = OutPut()
temp:Temp = Temp()
def __post_init__(self):
if self.input is None:
self.input = InPut()
class Devices:
motor1 = Motor()
motor2 = Motor()
motor3 = Motor()
motor4 = Motor()
motor5 = Motor()
class HMI:
input:InPut = InPut(interval=50)
input2:InPut = InPut(interval=100)
input3:InPut = InPut(interval=300)
input4:InPut = InPut(interval=400)
input5:InPut = InPut(interval=600)
def mapping():
Devices.motor1.input.interval = HMI.input.interval
Devices.motor2.input.interval = HMI.input2.interval
Devices.motor3.input.interval = HMI.input3.interval
Devices.motor4.input.interval = HMI.input4.interval
Devices.motor5.input.interval = HMI.input5.interval
print("motor1.input.interval:",Devices.motor1.input.interval)
print("motor2.input.interval:",Devices.motor2.input.interval)
print("motor3.input.interval:",Devices.motor3.input.interval)
print("motor4.input.interval:",Devices.motor4.input.interval)
print("motor5.input.interval:",Devices.motor5.input.interval)
print("motor1.input",id(Devices.motor1.input))
print("motor2.input",id(Devices.motor2.input))
print("motor3.input",id(Devices.motor3.input))
print("motor4.input",id(Devices.motor4.input))
print("motor5.input",id(Devices.motor5.input))
if __name__ == '__main__':
mapping()
问题得以解决。
结果如下:
motor1.input.interval: 50
motor2.input.interval: 100
motor3.input.interval: 300
motor4.input.interval: 400
motor5.input.interval: 600
motor1.input 2353790703552
motor2.input 2353793639328
motor3.input 2353793640240
motor4.input 2353793638944
motor5.input 2353793639808