全网最适合入门的面向对象编程教程:20 类和对象的 Python 实现-组合关系的实现与 CSV 文件保存

全网最适合入门的面向对象编程教程:20 类和对象的 Python 实现-组合关系的实现与 CSV 文件保存

摘要:

本文主要介绍了在使用 Python 面向对象编程时,如何实现组合关系,同时对比了组合关系和继承关系的优缺点,并讲解了如何通过 csv 模块来保存 Python 接收/生成的数据。

原文链接:

FreakStudio的博客

往期推荐:

可能是全网最适合入门的面向对象编程教程:Python实现-嵌入式爱好者必看!

全网最适合入门的面向对象编程教程:00 面向对象设计方法导论

全网最适合入门的面向对象编程教程:01 面向对象编程的基本概念

全网最适合入门的面向对象编程教程:02 类和对象的Python实现-使用Python创建类

全网最适合入门的面向对象编程教程:03 类和对象的Python实现-为自定义类添加属性

全网最适合入门的面向对象编程教程:04 类和对象的 Python 实现-为自定义类添加方法

全网最适合入门的面向对象编程教程:05 类和对象的Python实现-PyCharm代码标签

全网最适合入门的面向对象编程教程:06 类和对象的 Python 实现-自定义类的数据封装

全网最适合入门的面向对象编程教程:07 类和对象的Python实现-类型注解

全网最适合入门的面向对象编程教程:08 类和对象的 Python 实现-@property 装饰器

全网最适合入门的面向对象编程教程:09 类和对象的Python实现-类之间的关系

全网最适合入门的面向对象编程教程:10 类和对象的Python实现-类的继承和里氏替换原则

全网最适合入门的面向对象编程教程:11 类和对象的Python实现-子类调用父类方法

全网最适合入门的面向对象编程教程:12 类和对象的 Python 实现-Python 使用 logging 模块输出程序运行日志

全网最适合入门的面向对象编程教程:13 类和对象的 Python 实现-可视化阅读代码神器 Sourcetrail 的安装使用

全网最适合入门的面向对象编程教程:14 类和对象的Python实现-类的静态方法和类方法

全网最适合入门的面向对象编程教程:15 类和对象的Python实现-__slots__魔法方法

全网最适合入门的面向对象编程教程:16 类和对象的Python实现-多态、方法重写与开闭原则

全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

全网最适合入门的面向对象编程教程:18 类和对象的Python实现-多重继承与PyQtGraph串口数据绘制曲线图

全网最适合入门的面向对象编程教程:19 类和对象的 Python 实现-使用 PyCharm 自动生成文件注释和函数注释

更多精彩内容可看:

CM3调试系统简析

肝了半个月,嵌入式技术栈大汇总出炉

比赛获奖的武林秘籍:07 一文速通电子设计大赛,电子人必看的获奖秘籍!

比赛获奖的武林秘籍:06 5 分钟速通比赛路演答辩,国奖选手的血泪经验!

比赛获奖的武林秘籍:05 电子计算机类比赛国奖队伍技术如何分工和学习内容

比赛获奖的武林秘籍:04 电子类比赛嵌入式开发快速必看的上手指南

比赛获奖的武林秘籍:03 好的创意选取-获得国奖的最必要前提

比赛获奖的武林秘籍:02 国奖秘籍-大学生电子计算机类竞赛快速上手的流程,小白必看

比赛获奖的武林秘籍:01 如何看待当代大学生竞赛中“卷”“祖传老项目”“找关系”的现象?

比赛获奖的武林秘籍:00 学科竞赛-工科类大学生绕不开的话题,你了解多少?

文档和代码获取:

可访问如下链接进行对文档下载:

https://github.com/leezisheng/Doc

image

本文档主要介绍如何使用 Python 进行面向对象编程,需要读者对 Python 语法和单片机开发具有基本了解。相比其他讲解 Python 面向对象编程的博客或书籍而言,本文档更加详细、侧重于嵌入式上位机应用,以上位机和下位机的常见串口数据收发、数据处理、动态图绘制等为应用实例,同时使用 Sourcetrail 代码软件对代码进行可视化阅读便于读者理解。

相关示例代码获取链接如下:https://github.com/leezisheng/Python-OOP-Demo

正文

前面讲了面向类与对象的继承,知道了继承是一种什么“是”什么的关系。然而类与类之间还有另一种关系,这就是组合。组合是将几个对象收集在一起生成一个新对象的行为。当一个对象是另外一个对象的一部分时,组合通常是不错的选择。

例如,汽车是由发动机、传动装置、启动装置、车前灯、挡风玻璃以及其他部件组成的,发动机又是由活塞、曲柄轴和阀门等组合而成的。**汽车是发动机等多个元器件的抽象,而发动机是活塞等元器件的抽象,二者处于不同的层次而又有彼此交互的接口,组合是提供不同抽象层的好办法。**汽车对象可以提供司机所需要的接口,同时也能够获取内在组成部分,从而为机械师提供适合操作的深层抽象。当然,如果机械师需要更多信息来诊断问题或调整发动机,这些组成部分也可以进一步被细分。

总的来说,组合就是让不同的类混合并且加入其他类中来增加功能和代码重用性,这种适用于由多个小类组成一个大类的情况,并且不需要对小类进行太多修改。在前面示例中,我们实现了主机的串口收发和绘图功能,在实际应用中,我们往往需要将传感器数据存储到文件中,以便后续的查看和处理,很明显前面的传感器数据为一维的时间序列数据,适合存储为表格类型(即列标题为索引和值),我们通常将该类数据保存为 csv 格式文件,csv 是一种字符串文件的格式,它组织数据的语法就是在字符串之间加分隔符(行与行之间是加换行符,同行字符之间是加逗号分隔),可以用任意的文本编辑器打开(如记事本),也可以用 Excel 打开,还可以通过 Excel 把文件另存为 csv 格式。**用 csv 格式存储数据,读写比较方便,易于实现,文件也会比 Excel 文件小。**但 csv 文件缺少 Excel 文件本身的很多功能,如不能嵌入图像和图表,不能生成公式等等。

操作 csv 文件我们需要借助 csv 模块,python 自带 csv 模块,不需要我们使用 pip 安装,我们可以点击如下链接查看 csv 模块使用方法:

https://docs.python.org/zh-cn/3.13/library/csv.html#csv.writer

image

这里,我们首先定义一个 FileIOClass 类,其中具有初始化方法、写入传感器数据到文件方法和关闭文件方法,示例代码如下:

import csv
_# 使用typing模块提供的复合注解功能_
from typing import Listclass FileIOClass:def __init__(self,path:str="G:\\Python面向对象编程\\Demo\\file.csv"):'''初始化csv文件和列标题:param path: 文件路径和文件名'''self.path   = path_# path为输出路径和文件名,newline=''是为了不出现空行_self.csvFile = open(path, "w+", newline='')_# rowname为列名,index-索引,data-数据_self.rowname = ['index', 'data']_# 返回一个writer对象,将用户的数据在给定的文件型对象上转换为带分隔符的字符串_self.writer = csv.writer(self.csvFile)_# 写入csv文件的列标题_self.writer.writerow( self.rowname)def WriteFile(self,index:List[int],data:List[int])->None:''':param index: 传感器索引列表:param data:  传感器数据列表:return:'''writedatalist = []for i in range(len(data)):writedatalist.append([index[i],data[i]])_# 将列表中的每个元素将被写入CSV文件的一列中_self.writer.writerow(writedatalist[i])def CloseFile(self)->None:'''关闭文件:return: None'''self.csvFile.close()

这里,在初始化方法中,我们需要传入文件保存路径。之后创建一个 writer 对象,将用户的数据在给定的文件型对象上转换为带分隔符的字符串,同时写入 csv 文件的列标题。在 WriteFile 方法中传入数据的索引列表用于表示数据的先后顺序,之后是数据列表(这里的类型注解需要使用 typing 模块提供的复合注解功能),并循环将每个元素将被写入 CSV 文件的一列中,最后定义了文件的关闭方法。

image

在主函数中,我们创建 FileIOClass 对象,写入模拟传感器数据后关闭文件,以下为示例代码和运行效果:

if __name__ == '__main__':path  = "G:\\Python面向对象编程\\Demo\\file.csv"data  = [11,42,307,46,55,61,78,80,19,11]index = [count for count in range(len(data))]file = FileIOClass(path)file.WriteFile(index,data)file.CloseFile()

image

这里,我们可以直接在 MasterClass 类的初始化中创建 FileIOClass 类的实例化对象来实现组合。代码如下:

_# 文件保存路径_self.savepath = "G:\\Python面向对象编程\\Demo\\file.csv"_# 创建FileIOClass类的实例化对象_self.fileio = FileIOClass(self.savepath)

通过 sourcetrail,我们可以清晰看到类之间的组合与继承关系:

image

image

在主程序中,我们在主机接收 10 次数据后,将数据保存到 file.csv 中:

if __name__ == "__main__":
_    # 创建数据列表_datalist = []m = MasterClass(state = MasterClass.IDLE_STATE,port = "COM17",wintitle = "Basic plotting examples",plottitle = "Updating plot",width = 1000,height = 600)m.StartMaster()m.SendSensorCMD(MasterClass.SENDID_CMD)m.RecvSensorID()# 循环10次接收数据for i in range(10):m.SendSensorCMD(MasterClass.SENDVALUE_CMD)value = m.RecvSensorValue()datalist.append(value)indexlist = [count for count in range(len(datalist))]# 写入数据m.fileio.WriteFile(indexlist,datalist)m.fileio.CloseFile()

如下为运行效果:

image

目前,整个文件的完整代码如下,可以看到单单是这么一个简单程序就有了三百多行,对于代码查找修改来讲,非常不便。同时我们注意到,几个不同类之间似乎功能并不相同,不应该放到一个文件中。下一节我们将会说如何利用 Python 中的模块和包来组织我们的代码。

完整代码如下:

_# 串口相关库_
import serial
import serial.tools.list_ports
_# 队列相关_
import queue
import random
_# 日志输出相关库_
import logging
_# 曲线作图相关库_
import pyqtgraph as pg
import numpy as np
from pyqtgraph.Qt import QtCore
_# 文件读写相关库_
import csv
_# 使用typing模块提供的复合注解功能_
from typing import List
import time_# # 设置日志输出级别_
_# logging.basicConfig(level=logging.DEBUG)_
_# 在配置下日志输出目标文件和日志格式_
LOG_FORMAT="%(asctime)s-%(levelname)s-%(message)s"
logging.basicConfig(filename='my.log',level=logging.DEBUG,format=LOG_FORMAT)class SerialClass:_# 限定SerialClass对象只能绑定以下属性___slots__ = ('dev','_SerialClass__devstate')_# 初始化__# 使用默认参数_def __init__(self,devport:str     = "COM17",devbaudrate:int = 115200,devbytesize:int = serial.EIGHTBITS,devparity  :str = serial.PARITY_NONE,devstopbits:int = serial.STOPBITS_ONE):_# 直接传入serial.Serial()类_self.dev             = serial.Serial()self.dev.port        = devportself.dev.baudrate    = devbaudrateself.dev.bytesize    = devbytesizeself.dev.parity      = devparityself.dev.stopbits    = devstopbits_# 表示串口设备的状态-打开或者关闭__# 初始化时为关闭_self.__devstate      = Falseprint("SerialClass init")logging.info("SerialClass init")_# 取值方法_@propertydef devstate(self):return self.__devstate_# 打开串口_def OpenSerial(self):print("SerialClass-OpenSerial")logging.info("SerialClass-OpenSerial")self.dev.open()self.__devstate = True_# 关闭串口_def CloseSerial(self):print("SerialClass-CloseSerial")logging.info("SerialClass-CloseSerial")self.dev.close()self.__devstate = False_# 串口读取_def ReadSerial(self):print("SerialClass-ReadSerial")logging.info("SerialClass-ReadSerial")if self.__devstate:_# 阻塞方式读取__# 按行读取_data = self.dev.readline()_# 收到为二进制数据__# 用utf-8编码将二进制数据解码为unicode字符串__# 字符串转为int类型_data = int(data.decode('utf-8', 'replace'))return data_# 串口写入_def WriteSerial(self,write_data):print("SerialClass-WriteSerial")logging.info("SerialClass-WriteSerial")if self.__devstate:_# 非阻塞方式写入_self.dev.write(write_data.encode())_# 输出换行符__# write的输入参数必须是bytes 格式__# 字符串数据需要encode()函数将其编码为二进制数据,然后才可以顺利发送__# \r\n表示换行回车_self.dev.write('\r\n'.encode())def RetSerialState(self):if self.dev.isOpen():self.__devstate = Truereturn Trueelse:self.__devstate = Falsereturn Falseclass PlotClass:_# 绘图类初始化_def __init__(self,wintitle:str="Basic plotting examples",plottitle:str="Updating plot",width:int=1000,height:int=600):'''用于初始化Plot类:param wintitle:  窗口标题:param plottitle: 图层标题:param width:     窗口宽度:param height:    窗口高度'''_# Qt应用实例对象_self.app        = None_# 窗口对象_self.win        = None_# 设置窗口标题_self.title      = wintitle_# 设置窗口尺寸_self.width      = widthself.height     = height_# 传感器数据_self.value      = 0_# 计数变量_self.__count    = 0_# 传感器数据缓存列表_self.valuelist  = []_# 绘图曲线_self.curve      = None_# 图层对象_self.plotob     = None_# 图层标题_self.plottitle  = plottitle_# 定时器对象_self.timer = QtCore.QTimer()_# 定时时间_self.time  = 0_# Qt应用和窗口初始化_self.appinit()print("PLOT INIT SUCCESS")logging.info("PLOT INIT SUCCESS")_# 应用程序初始化_def appinit(self):'''用于qt应用程序初始化,添加窗口、曲线和图层:return: None'''_# 创建一个Qt应用,并返回该应用的实例对象_self.app = pg.mkQApp("Plotting Example")_# 生成多面板图形__# show:(bool) 如果为 True,则在创建小部件后立即显示小部件。__# title:(str 或 None)如果指定,则为此小部件设置窗口标题。_self.win = pg.GraphicsLayoutWidget(show=True, title=self.title)_# 设置窗口尺寸_self.win.resize(self.width, self.height)_# 进行窗口全局设置,setConfigOptions一次性配置多项参数__# antialias启用抗锯齿,useNumba对图像进行加速_pg.setConfigOptions(antialias=True, useNumba=True)_# 添加图层_self.plotob = self.win.addPlot(title=self.plottitle)_# 添加曲线_self.curve = self.plotob.plot(pen='y')_# 接收数据_def GetValue(self,value):'''用于接收传感器数据,加入缓存列表:param value: 传感器数据:return: None'''self.value = value_# 加入数据缓存列表_self.valuelist.append(value)print("PLOT RECV DATA : "+str(self.value))logging.info("PLOT RECV DATA : "+str(self.value))_# 更新曲线数据_def DataUpdate(self):'''用于定时进行曲线更新,这里模拟绘制正弦曲线:return: None'''_# 模拟绘制正弦曲线__# 计数变量更新_self.__count = self.__count + 0.1self.value = np.sin(self.__count)self.GetValue(self.value)_# 将数据转化为图形_self.curve.setData(self.valuelist)_# 设置定时更新_def SetUpdate(self,time:int = 100):'''设置定时更新任务:param time: 定时的时间:return: None'''_# 定时器结束,触发DataUpdate方法_self.timer.timeout.connect(self.DataUpdate)_# 启动定时器_self.timer.start(time)_# 定时时间_self.time = timeprint("PLOT SET UPDATA")logging.info("PLOT SET UPDATA")_# 进入主事件循环并等待_pg.exec()class FileIOClass:def __init__(self,path:str="G:\\Python面向对象编程\\Demo\\file.csv"):'''初始化csv文件和列标题:param path: 文件路径和文件名'''self.path   = path_# path为输出路径和文件名,newline=''是为了不出现空行_self.csvFile = open(path, "w+", newline='')_# rowname为列名,index-索引,data-数据_self.rowname = ['index', 'data']_# 返回一个writer对象,将用户的数据在给定的文件型对象上转换为带分隔符的字符串_self.writer = csv.writer(self.csvFile)_# 写入csv文件的列标题_self.writer.writerow(self.rowname)def WriteFile(self,index:List[int],data:List[int])->None:''':param index: 传感器索引列表:param data:  传感器数据列表:return:'''writedatalist = []for i in range(len(data)):writedatalist.append([index[i],data[i]])_# 将列表中的每个元素将被写入CSV文件的一列中_self.writer.writerow(writedatalist[i])def CloseFile(self)->None:'''关闭文件:return: None'''self.csvFile.close()class SensorClass(SerialClass):_# 类变量:__#   RESPOND_MODE -响应模式-0__#   LOOP_MODE    -循环模式-1_RESPOND_MODE,LOOP_MODE = (0,1)_# 类变量:__#   START_CMD       - 开启命令      -0__#   STOP_CMD        - 关闭命令      -1__#   SENDID_CMD      - 发送ID命令    -2__#   SENDVALUE_CMD   - 发送数据命令   -3_START_CMD,STOP_CMD,SENDID_CMD,SENDVALUE_CMD = (0,1,2,3)_# 类的初始化_def __init__(self,port:str = "COM11",id:int = 0,state:int = RESPOND_MODE):_# 调用父类的初始化方法,super() 函数将父类和子类连接_super().__init__(port)self.sensorvalue = 0self.sensorid    = idself.sensorstate = stateprint("Sensor Init")logging.info("Sensor Init")@staticmethod_# 判断传感器ID号是否正确:这里判断ID号是否在0到99之间_def IsTrueID(id:int = 0):if id >= 0 and id <= 99:print("Sensor ID True")return Trueelse:print("Sensor ID False")return False_# 传感器上电初始化_def InitSensor(self):_# 传感器上电初始化工作__# 同时输出ID号以及状态_print("Sensor %d Init complete : %d"%(self.sensorid,self.sensorstate))logging.info("Sensor %d Init complete : %d"%(self.sensorid,self.sensorstate))_# 开启传感器_def StartSensor(self):super().OpenSerial()print("Sensor %d start serial %s "%(self.sensorid,self.dev.port))logging.info("Sensor %d start serial %s "%(self.sensorid,self.dev.port))_# 停止传感器_def StopSensor(self):super().CloseSerial()print("Sensor %d close serial %s " % (self.sensorid, self.dev.port))logging.info("Sensor %d close serial %s " % (self.sensorid, self.dev.port))_# 发送传感器ID号_def SendSensorID(self):super().WriteSerial(str(self.sensorid))print("Sensor %d send id "%self.sensorid)logging.info("Sensor %d send id "%self.sensorid)_# 发送传感器数据_def SendSensorValue(self):_# 生成[1, 10]内的随机整数_data = random.randint(1, 10)super().WriteSerial(str(data))print("Sensor %d send data  %d" % (self.sensorid,data))logging.info("Sensor %d send data  %d" % (self.sensorid,data))_# 接收主机指令_def RecvMasterCMD(self):cmd = super().ReadSerial()print("Sensor %d recv cmd %d " % (self.sensorid,cmd))logging.info("Sensor %d recv cmd %d " % (self.sensorid,cmd))return cmdclass MasterClass(SerialClass,PlotClass):_# 类变量:__#   BUSY_STATE  -忙碌状态-0__#   IDLE_STATE  -空闲状态-1_BUSY_STATE, IDLE_STATE = (0, 1)_# 类变量:__#   START_CMD       - 开启命令      -0__#   STOP_CMD        - 关闭命令      -1__#   SENDID_CMD      - 发送ID命令    -2__#   SENDVALUE_CMD   - 发送数据命令   -3_START_CMD, STOP_CMD, SENDID_CMD, SENDVALUE_CMD = (0, 1, 2, 3)_# 类的初始化_def __init__(self,state:int = IDLE_STATE,port:str = "COM17",wintitle:str="Basic plotting examples",plottitle:str="Updating plot",width:int=1000,height:int=600):_# 分别调用不同父类的__init__方法_SerialClass.__init__(self,port)PlotClass.__init__(self,wintitle,plottitle,width,height)self.valuequeue   = queue.Queue(10)self.__masterstatue = state_# 初始化完成的标志量_self.INIT_FLAG = False_# 文件保存路径_self.savepath = "G:\\Python面向对象编程\\Demo\\file.csv"_# 创建FileIOClass类的实例化对象_self.fileio = FileIOClass(self.savepath)print("MASTER INIT SUCCESSS")logging.info("MASTER INIT SUCCESSS")@classmethoddef MasterInfo(cls):print("Info : "+str(cls))_# 开启主机_def StartMaster(self):super().OpenSerial()print("START MASTER :"+self.dev.port)logging.info("START MASTER :"+self.dev.port)_# 停止主机_def StopMaster(self):super().CloseSerial()print("CLOSE MASTER :" + self.dev.port)logging.info("CLOSE MASTER :" + self.dev.port)_# 接收传感器ID号_def RecvSensorID(self):sensorid = super().ReadSerial()print("MASTER RECIEVE ID : " + str(sensorid))logging.info("MASTER RECIEVE ID : " + str(sensorid))return sensorid_# 接收传感器数据_def RecvSensorValue(self):data = super().ReadSerial()print("MASTER RECIEVE DATA : " + str(data))logging.info("MASTER RECIEVE DATA : " + str(data))self.valuequeue.put(data)return data_# 主机发送命令_def SendSensorCMD(self,cmd):super().WriteSerial(str(cmd))print("MASTER SEND CMD : " + str(cmd))logging.info("MASTER SEND CMD : " + str(cmd))_# 主机返回工作状态-_def RetMasterStatue(self):return self.__masterstatue_# 重写父类的DataUpdate方法_def DataUpdate(self):self.SendSensorCMD(self.SENDVALUE_CMD)self.value = self.RecvSensorValue()self.WriteSerial("Recv:"+str(self.value))self.GetValue(self.value)self.curve.setData(self.valuelist)print("PLOT UPDATA : " + str(self.value))logging.info("PLOT UPDATA : " + str(self.value))class DevClass(SerialClass):def __init__(self,port:str = "COM1"):super().__init__(port)_# 开启设备_def StartDev(self):super().OpenSerial()print("START Dev :" + self.dev.port)def ReadSerial(self,byte_size):if super().RetSerialState():data = self.dev.read(byte_size)data = int(data.decode('utf-8', 'replace'))return data_# 判断串口类对象的串口是否开启_
def IsSerialConnected(serialclass):return serialclass.RetSerialState()if __name__ == "__main__":_# 创建数据列表_datalist = []m = MasterClass(state = MasterClass.IDLE_STATE,port = "COM17",wintitle = "Basic plotting examples",plottitle = "Updating plot",width = 1000,height = 600)m.StartMaster()m.SendSensorCMD(MasterClass.SENDID_CMD)m.RecvSensorID()_# 循环10次接收数据_for i in range(10):m.SendSensorCMD(MasterClass.SENDVALUE_CMD)value = m.RecvSensorValue()datalist.append(value)indexlist = [count for count in range(len(datalist))]_# 写入数据_m.fileio.WriteFile(indexlist,datalist)m.fileio.CloseFile()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3249816.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

初阶数据结构的实现1 顺序表和链表

顺序表和链表 1.线性表1.1顺序表1.1.1静态顺序表&#xff08;不去实现&#xff09;1.1.2动态顺序表1.1.2.1 定义程序目标1.1.2.2 设计程序1.1.2.3编写代码1.1.2.3测试和调试代码 1.1.2 顺序表的问题与思考 1.2链表1.2.1链表的概念及结构1.2.1.1 定义程序目标1.2.1.2 设计程序1.…

Ai先行者工具与其他品牌大比拼!

AI先行者工具凭借其独特的技术优势和创新能力&#xff0c;成为了行业的焦点。那么&#xff0c;它究竟有哪些过人之处呢&#xff1f; AI先行者工具在算法优化上做了大量的工作。通过深度学习和自然语言处理技术&#xff0c;它能够更准确地理解和回应用户的需求&#xff0c;提供…

Haproy服务

目录 一.haproxy介绍 1.主要特点和功能 2.haproxy 调度算法 3.haproxy 与nginx 和lvs的区别 二.安装 haproxy 服务 1. yum安装 2.第三方rpm 安装 3.编译安装haproxy 三.配置文件详解 1.官方地址配置文件官方帮助文档 2.HAProxy 的配置文件haproxy.cfg由两大部分组成&…

linux中list的基本用法

内核链表 1 list_head 结构 为了使用链表机制&#xff0c;驱动程序需要包含<linux/types.h>头文件&#xff0c;该文件定义了如下结构体实现双向链&#xff1a; struct list_head {struct list_head *next, *prev; };2 链表的初始化 2.1 链表宏定义和初始化 可使用以…

如何在Mac下修改VSCode侧边栏字体大小

在日常使用VSCode&#xff08;Visual Studio Code&#xff09;进行开发时&#xff0c;我们有时需要对IDE&#xff08;集成开发环境&#xff09;的界面进行一些个性化的调整&#xff0c;以提升我们的开发体验。 比如&#xff0c;有些用户可能会觉得VSCode的侧边栏字体大小不符…

JavaDS —— 二叉树

树的基本概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看 起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 树形结构中&#xff0c;子树之间不能有…

健康问题查询找搜索引擎还是大模型

随着自然语言处理&#xff08;NLP&#xff09;的最新进展&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已经成为众多信息获取任务中的主要参与者。然而&#xff0c;传统网络搜索引擎&#xff08;SEs&#xff09;在回答用户提交的查询中的作用远未被取代。例如&#xf…

idea怎么配置gradle多个版本

1.背景 gradle版本很多,而且很多时候版本是不兼容的,我们希望拉取下来的代码就包含已经配置好的版本,而不是去配置本机的gradle版本..... 意思就是要实现项目A可以用6.X版本 项目B可以使用7.X版本 项目C可以用9.X版本..... 2.配置方式 步骤一:项目根路径下保留一个文件夹…

阿里云ACP云计算高级攻城狮通用知识

&#x1f525;概述 阿里云云计算高级工程师ACP认证是面向使用阿里云云计算产品的架构、开发、运维类人员的专业技术认证&#xff0c;主要考核考生利用阿里云云计算技术服务体系设计稳定、安全、高性能、易扩展、低成本的企业云计算架构的能力。 前提&#xff1a;在写适用人群…

【ROS2】高级:从包文件读取 (C++)

目标&#xff1a;在不使用 CLI 的情况下从包中读取数据。 教程级别&#xff1a;高级 时间&#xff1a;10 分钟 目录 背景 先决条件 任务 1 创建一个包裹2 编写 C 读取器3 构建并运行 摘要 背景 rosbag2 不仅提供 ros2 bag 命令行工具。它还提供了一个 C API&#xff0c;用于从您…

基于JAVA+SpringBoot+uniapp的心理小程序(小程序版本)

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、SpringCloud、Layui、Echarts图表、Nodejs、爬…

5G mmWave PAAM 开发平台

Avnet-Fujikura-AMD 5G 毫米波相控阵天线模块开发平台 Avnet 和 Fujikura 为毫米波频段创建了一个领先的 5G FR2 相控阵天线开发平台。该平台使开发人员能够使用 AMD Xilinx 的 Zynq UltraScale™ RFSoC Gen3 和 Fujikura 的 FutureAcess™ 相控阵天线模块 (PAAM) 快速创建和制…

上海理工大学24计算机考研考情分析!初复试分值比55:45,复试逆袭人数不算多!

上海理工大学&#xff08;University of Shanghai for Science and Technology&#xff09;&#xff0c;位于上海市&#xff0c;是一所以工学为主&#xff0c;工学、理学、经济学、管理学、文学、法学、艺术学等多学科协调发展的应用研究型大学&#xff1b;是上海市属重点建设大…

Amisco供应汽车线圈与Husco是一家私营公司高性能液压和机电部件在汽车和非公路应用的组件设计和制造方面拥有超过 75 年的经验10于年的合作

Amisco和Husco在汽车线圈和高性能液压和机电部件的设计和制造方面合作已经超过10年。 Amisco是一家供应汽车线圈的公司&#xff0c;而Husco则专注于高性能液压和机电部件的设计和制造。 这两家公司在汽车和非公路应用领域拥有超过75年的经验。通过合作&#xff0c;Amisco和Husc…

【开源 Mac 工具推荐之 2】洛雪音乐(lx-music-desktop):免费良心的音乐平台

旧版文章&#xff1a;【macOS免费软件推荐】第6期&#xff1a;洛雪音乐 Note&#xff1a;本文在旧版文章的基础上&#xff0c;新更新展示了一些洛雪音乐的新功能&#xff0c;并且描述更为详细。 简介 洛雪音乐&#xff08;GitHub 名&#xff1a;lx-music-desktop &#xff09;…

将iPad 作为Windows电脑副屏的几种方法(二)

将iPad 作为Windows电脑副屏的几种方法&#xff08;二&#xff09; 1. 前言2. EV 扩展屏2.1 概述2.2 下载、安装、连接教程2.3 遇到的问题和解决方法2.3.1 平板连接不上电脑 3. Twomon SE3.1 概述3.2 下载安装教程 4. 多屏中心&#xff08;GlideX&#xff09;4.1 概述4.2 下载安…

LeetCode 算法:单词搜索 c++

原题链接&#x1f517;&#xff1a;单词搜索 难度&#xff1a;中等⭐️⭐️ 题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通…

解决npm install(‘proxy‘ config is set properly. See: ‘npm help config‘)失败问题

摘要 重装电脑系统后&#xff0c;使用npm install初始化项目依赖失败了&#xff0c;错误提示&#xff1a;‘proxy’ config is set properly…&#xff0c;具体的错误提示如下图所示&#xff1a; 解决方案 经过报错信息查询解决办法&#xff0c;最终找到了两个比较好的方案&a…

vscode+wsl2+anaconda环境的配置与使用

目录 下载anaconda Anaconda使用参考 vscodeubuntuanaconda 先用vscode连接本地ubuntu。 如果没有安装wsl2与ubuntu&#xff0c;可点击下面的链接。 问题&#xff1a;wsl install 无法解析服务器 成功记录&#xff1a; 在vscode终端用ubuntu安装anaconda。 创建pytho…

学习008-02-01 Define the Data Model and Set the Initial Data(定义数据模型并设置初始数据)

Define the Data Model and Set the Initial Data&#xff08;定义数据模型并设置初始数据&#xff09; This section explains how to design a business model (database) for an application built with Cross-Platform .NET App UI (XAF) and Entity Framework Core. 本节…