python使用dataclass数据类有个坑

今天在创建数据类时,遇到一个问题。发现数据出现了问题。代码如下:


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

相关推荐

  1. python使用dataclass数据

    2024-04-12 00:26:03       35 阅读
  2. python 拷贝原来还这么

    2024-04-12 00:26:03       29 阅读
  3. python3的几

    2024-04-12 00:26:03       48 阅读
  4. 译文带你理解Pythondataclass装饰器

    2024-04-12 00:26:03       70 阅读
  5. Python BaseModel和dataclass用法和区别

    2024-04-12 00:26:03       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-12 00:26:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-12 00:26:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-12 00:26:03       87 阅读
  4. Python语言-面向对象

    2024-04-12 00:26:03       96 阅读

热门阅读

  1. 【QT教程】QT6布局管理

    2024-04-12 00:26:03       32 阅读
  2. js学习笔记5(API及DOM)

    2024-04-12 00:26:03       27 阅读
  3. 电厂业务数据笔记

    2024-04-12 00:26:03       36 阅读
  4. C++内存管理(个人笔记)

    2024-04-12 00:26:03       37 阅读
  5. Vue中实现回退到上一级目录或者回退到首页

    2024-04-12 00:26:03       39 阅读
  6. Vue插件使用详细介绍

    2024-04-12 00:26:03       36 阅读
  7. 拥抱Linux,拥抱开源,拥抱未来

    2024-04-12 00:26:03       40 阅读
  8. Week6-LeetCode

    2024-04-12 00:26:03       33 阅读