python使用dataclass数据类有个坑

2024-04-12 01:44

本文主要是介绍python使用dataclass数据类有个坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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


from dataclasses import dataclass
@dataclass
class InPut:start:bool = Falsestop:bool = 0fault:bool = Noneinterval: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.intervalDevices.motor2.input.interval = HMI.input2.intervalDevices.motor3.input.interval = HMI.input3.intervalDevices.motor4.input.interval = HMI.input4.intervalDevices.motor5.input.interval = HMI.input5.intervalprint("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.intervalDevices.motor2.input.interval = HMI.input2.intervalDevices.motor3.input.interval = HMI.input3.intervalDevices.motor4.input.interval = HMI.input4.intervalDevices.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.intervalDevices.motor2.input.interval = HMI.input2.intervalDevices.motor3.input.interval = HMI.input3.intervalDevices.motor4.input.interval = HMI.input4.intervalDevices.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 = NoneoutPut: 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 = Falsestop:bool = 0fault:bool = Noneinterval:int = 0@dataclass
class OutPut:星启动:bool = None主启动:bool = None三角启动:bool = None@dataclass
class Temp():...@dataclass
class Motor:input:InPut = NoneoutPut: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.intervalDevices.motor2.input.interval = HMI.input2.intervalDevices.motor3.input.interval = HMI.input3.intervalDevices.motor4.input.interval = HMI.input4.intervalDevices.motor5.input.interval = HMI.input5.intervalprint("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

这篇关于python使用dataclass数据类有个坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/895764

相关文章

使用Dify访问mysql数据库详细代码示例

《使用Dify访问mysql数据库详细代码示例》:本文主要介绍使用Dify访问mysql数据库的相关资料,并详细讲解了如何在本地搭建数据库访问服务,使用ngrok暴露到公网,并创建知识库、数据库访... 1、在本地搭建数据库访问的服务,并使用ngrok暴露到公网。#sql_tools.pyfrom

VSCode配置Anaconda Python环境的实现

《VSCode配置AnacondaPython环境的实现》VisualStudioCode中可以使用Anaconda环境进行Python开发,本文主要介绍了VSCode配置AnacondaPytho... 目录前言一、安装 Visual Studio Code 和 Anaconda二、创建或激活 conda

使用mvn deploy命令上传jar包的实现

《使用mvndeploy命令上传jar包的实现》本文介绍了使用mvndeploy:deploy-file命令将本地仓库中的JAR包重新发布到Maven私服,文中通过示例代码介绍的非常详细,对大家的学... 目录一、背景二、环境三、配置nexus上传账号四、执行deploy命令上传包1. 首先需要把本地仓中要

pytorch+torchvision+python版本对应及环境安装

《pytorch+torchvision+python版本对应及环境安装》本文主要介绍了pytorch+torchvision+python版本对应及环境安装,安装过程中需要注意Numpy版本的降级,... 目录一、版本对应二、安装命令(pip)1. 版本2. 安装全过程3. 命令相关解释参考文章一、版本对

Spring Cloud之注册中心Nacos的使用详解

《SpringCloud之注册中心Nacos的使用详解》本文介绍SpringCloudAlibaba中的Nacos组件,对比了Nacos与Eureka的区别,展示了如何在项目中引入SpringClo... 目录Naacos服务注册/服务发现引⼊Spring Cloud Alibaba依赖引入Naco编程s依

Java springBoot初步使用websocket的代码示例

《JavaspringBoot初步使用websocket的代码示例》:本文主要介绍JavaspringBoot初步使用websocket的相关资料,WebSocket是一种实现实时双向通信的协... 目录一、什么是websocket二、依赖坐标地址1.springBoot父级依赖2.springBoot依赖

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架

讯飞webapi语音识别接口调用示例代码(python)

《讯飞webapi语音识别接口调用示例代码(python)》:本文主要介绍如何使用Python3调用讯飞WebAPI语音识别接口,重点解决了在处理语音识别结果时判断是否为最后一帧的问题,通过运行代... 目录前言一、环境二、引入库三、代码实例四、运行结果五、总结前言基于python3 讯飞webAPI语音

基于Python开发PDF转PNG的可视化工具

《基于Python开发PDF转PNG的可视化工具》在数字文档处理领域,PDF到图像格式的转换是常见需求,本文介绍如何利用Python的PyMuPDF库和Tkinter框架开发一个带图形界面的PDF转P... 目录一、引言二、功能特性三、技术架构1. 技术栈组成2. 系统架构javascript设计3.效果图

Java使用Mail构建邮件功能的完整指南

《Java使用Mail构建邮件功能的完整指南》JavaMailAPI是一个功能强大的工具,它可以帮助开发者轻松实现邮件的发送与接收功能,本文将介绍如何使用JavaMail发送和接收邮件,希望对大家有所... 目录1、简述2、主要特点3、发送样例3.1 发送纯文本邮件3.2 发送 html 邮件3.3 发送带