当前位置:首页 > 软件设计 > 正文内容

全网最适合入门的面向目标编程教程:18 类和目标的 Python 完成-多重承继与 PyQtGraph 串口数据制作曲线图

邻居的猫1个月前 (12-09)软件设计597

全网最适合入门的面向目标编程教程:18 类和目标的 Python 完结-多重承继与 PyQtGraph 串口数据制作曲线图

摘要:

本文首要介绍了 Python 中创立自界说类时怎么运用多重承继、菱形承继的概念和易错点,一起解说了怎么运用 PyQtGraph 库对串口接纳的数据进行绘图。

原文链接:

FreakStudio的博客

往期引荐:

学嵌入式的你,还不会面向目标??!

全网最适合入门的面向目标编程教程: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“

更多精彩内容可看:

给你的 Python 加加快:一文速通 Python 并行核算

一文搞懂 CM3 单片机调试原理

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

电子核算机类竞赛的“武林秘籍”

一个MicroPython的开源项目集锦:awesome-micropython,包括各个方面的Micropython东西库

文档和代码获取:

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

https://github.com/leezisheng/Doc

image

本文档首要介绍怎么运用 Python 进行面向目标编程,需求读者对 Python 语法和单片机开发具有根本了解。比较其他解说 Python 面向目标编程的博客或书本而言,本文档愈加具体、侧重于嵌入式上位机运用,以上位机和下位机的常见串口数据收发、数据处理、动态图制作等为运用实例,一起运用 Sourcetrail 代码软件对代码进行可视化阅览便于读者了解。

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

正文

在 python 中一个类能承继自不止一个父类,这叫做 python 的多重承继,多重承继的语法与单承继相似:

class SubclassName(BaseClass1, BaseClass2, BaseClass3, ...):
    pass

当然,子类所承继的一切父类相同也能有自己的父类,这样就能够得到一个承继联系机构图如下图所示:

image

多重承继最常见的用处便是用于创立包括两组彻底不同行为的目标。例如,规划一个目标用于衔接扫描器并将扫描的文件经过传真发送出去,这一目标或许承继自两个彻底独立的 scanner 和 faxer 目标。

关于 MasterClass 来说,咱们期望它能够具有绘图功用,能够将串口接纳到的传感器数据动态制作曲线,这儿咱们凭借 PyQtGraph 库来完结,PyQtGraph 是纯 Python 图形 GUI 库,它充分运用 PyQt 和 PtSide 的高质量的图形体现水平缓 NumPy 的快速科学核算与处理才能,在数学、科学和工程范畴都有广泛的运用。

PyQtGraph 比较于 matplotlib 愈加适合于数据收集和剖析运用。

咱们运用如下两条句子完结 PyQtGraph 库和其依靠库 PyQt5 的装置:

**pip install pyqtgraph **

**pip install PyQt5 **

pip install numpy

这儿,咱们首要界说一个绘图类及其办法,示例代码如下:

class PlotClass:
    _# 绘图类初始化_
    def __init__(self,wintitle:str="Basic plotting examples",plottitle:str="Updating plot",width:int=1000,height:int=600):
        _# Qt运用实例目标_
        self.app        = None
        _# 窗口目标_
        self.win        = None
        _# 设置窗口标题_
        self.title      = wintitle
        _# 设置窗口尺度_
        self.width      = width
        self.height     = height
        _# 传感器数据_
        self.value      = 0
        _# 计数变量_
        self.__count    = 0
        _# 传感器数据缓存列表_
        self.valuelist  = []
        _# 绘图曲线_
        self.curve      = None
        _# 图层目标_
        self.plotob     = None
        _# 图层标题_
        self.plottitle  = plottitle
        _# Qt运用和窗口初始化_
        self.appinit()

    _# 运用程序初始化_
    def appinit(self):
        _# 创立一个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):
        self.value = value
        _# 参加数据缓存列表_
        self.valuelist.append(value)

    _# 更新曲线数据_
    def DataUpdate(self):
        _# 模仿制作正弦曲线_
        _# 计数变量更新_
        self.__count = self.__count + 0.1
        self.value = np.sin(self.__count)
        self.GetValue(self.value)
        _# 将数据转化为图形_
        self.curve.setData(self.valuelist)

    _# 设置守时更新_
    def SetUpdate(self,time:int = 100):
        _# 创立守时器目标_
        timer = QtCore.QTimer()
        _# 守时器完毕,触发DataUpdate办法_
        timer.timeout.connect(self.DataUpdate)
        _# 发动守时器_
        timer.start(time)
        _# 进入主事情循环并等候_
        pg.exec()

if __name__ == '__main__':
    _# 创立PlotClass目标,主动完结初始化_
    p = PlotClass()
    _# 设置守时更新使命_
    p.SetUpdate()

这儿,咱们界说了如下特点和办法:

特点/办法 作用
wintitle 窗口标题
plottitle 图层标题
width 窗口宽度
height 窗口高度
app Qt 运用实例目标
win 窗口目标
value 传感器数据
__count 计数变量
valuelist 传感器数据缓存列表
curve 绘图曲线
plotob 图层目标
appinit(self) 用于 qt 运用程序初始化,增加窗口、曲线和图层
GetValue(self,value) 用于接纳传感器数据,参加缓存列表
DataUpdate(self) 用于守时进行曲线更新,这儿模仿制作正弦曲线
SetUpdate(self,time:int = 100) 设置守时更新使命

首要,咱们在__init__和 appinit()中完结初始化操作,包括对类内特点、Qt 运用实例、窗口图层及曲线的初始化:

image

接着咱们在 SetUpdate 办法中创立守时器目标并设置守时使命,当设置的延时时刻抵达时,调用 DataUpdate 办法,在其间对数据曲线并进行更新,示例中,咱们运用__count 特点每次递加,使得其制作正弦曲线。

一起设置进入主事情循环并等候吗,以使得 Qt 界面坚持显现:

image

这儿,咱们在主函数中创立目标并发动运转守时改写曲线,如下为成果:

image

这儿,咱们想要使得 MasterClass 类一起具有串口收发和绘图功用,因而要用到多重承继,MasterClass 类一起承继于 SerialClass 和 PlotClass。经过多重承继,一个子类就能够一起取得多个父类的一切功用。

示例代码如下:

class 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

    @classmethod
    def MasterInfo(cls):
        print("Info : "+str(cls))

    _# 敞开主机_
    def StartMaster(self):
        super().OpenSerial()
        logging.info("START MASTER :"+self.dev.port)

    _# 中止主机_
    def StopMaster(self):
        super().CloseSerial()
        logging.info("CLOSE MASTER :" + self.dev.port)

    _# 接纳传感器ID号_
    def RecvSensorID(self):
        sensorid = super().ReadSerial()
        logging.info("MASTER RECIEVE ID : " + str(sensorid))
        return sensorid

    _# 接纳传感器数据_
    def RecvSensorValue(self):
        data = super().ReadSerial()
        logging.info("MASTER RECIEVE DATA : " + str(data))
        self.valuequeue.put(data)
        return data

    _# 主机发送指令_
    def SendSensorCMD(self,cmd):
        super().WriteSerial(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)

if __name__ == "__main__":
    _# 初始化目标_
    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()
    _# 设置守时更新使命_
    m.SetUpdate()

咱们能够看到两个父类和子类联系及不同类的特点和办法如下:

image

首要,咱们运用如下句子标明 MasterClass 承继于 SerialClass 和 PlotClass:

class MasterClass(SerialClass,PlotClass):

接着,咱们在 MasterClass 的初始化办法中别离调用不同父类的__init__办法:

SerialClass.__init__(self,port)
        PlotClass.__init__(self,wintitle,plottitle,width,height)

一起咱们在 MasterClass 中重写父类的 DataUpdate 办法,首要发送查询数据指令,接着等候接纳数据,完结数据接纳后发送接纳到的数据并存入数据缓存列表,在设置守时使命后,守时更新曲线。

image

如下为运转作用,咱们能够看到接纳到数据后正常完结曲线的更新:

image

在测验过程中,咱们能够看到 Qt 窗口会有无法呼应的状况呈现,这是因为界面主线程是单线程,假如在 UI 主线程中履行耗时操作,例如点击按钮,呼应函数去数据库查询数据,数据量比较大时,查询需求几秒钟乃至几十秒的时刻,假如 UI 主线程一向等候呼应函数回来,阻塞在呼应函数内部,就无法呼应界面的其他音讯或许事情,界面就会卡死,无呼应。这种状况能够运用 Python 的多线程或多进程得以防止,这个状况将在后边讲到。

能够看到,在创立包括两组彻底不同行为的目标的状况下,两个类接口不同,子类彻底能够正常运转,可是假如两个类的接口有堆叠,一起承继就或许形成紊乱。最好的办法便是防止这种状况,从头剖析系统,看看是否能够去掉多重承继联系并用其他的相关或组合规划代替。

一起牢记,尽量不要在子类的初始化办法中手动调用父类目标的初始化办法,会导致导致菱形承继无法被正确处理,尽量运用 Python 内置的 super() 函数,并且为 Python 类规则了规范的办法解析次序 MRO 。运用 super() 函数初始化父类能够保证菱形承继系统中的一起超类只初始化一次。MRO 则能够确认超类之间的初始化次序。

关于多重承继中调用同名办法时的具体状况和调用次序能够检查如下链接:

https://pythonhowto.readthedocs.io/zh-cn/latest/object.html#id29

image

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=319

分享给朋友:

“全网最适合入门的面向目标编程教程:18 类和目标的 Python 完成-多重承继与 PyQtGraph 串口数据制作曲线图” 的相关文章

规划形式之署理形式

规划形式之署理形式

界说 署理形式(Proxy Pattern)是软件工程中的一种规划形式,它归于结构型形式,用于在不直接拜访实践目标的状况下,经过一个或多个署理目标来直接拜访某个目标或履行某些操作。 意图 这种形式的首要意图是: 操控拜访:署理能够在拜访实在目标之前或之后增加额定的操作,如权限查看、推迟初始化、日志记...

简述面向对象三大特征的理解,面向对象三大特征的理解与探讨

简述面向对象三大特征的理解,面向对象三大特征的理解与探讨

面向对象的三大特征是封装、继承和多态。下面我将分别解释它们的概念和作用。1. 封装(Encapsulation):封装是将数据(属性)和行为(方法)捆绑在一起,形成一个对象。通过封装,我们可以隐藏对象的内部实现细节,只暴露出必要的接口供外部访问。这样可以保护数据的安全性,防止外部直接修改对象的状态。...

c是面向对象的语言吗,面向对象还是面向过程?

C语言本身不是一种面向对象的语言。它是一种过程式语言,主要用于编写系统软件、嵌入式软件和实时应用。C 是在C语言的基础上发展而来的,它添加了面向对象编程(OOP)的特性,如类、对象、继承、多态等。因此,如果你想要在C语言中使用面向对象编程,你需要使用C 或其他支持OOP的语言。C语言:面向对象还...

面向对象的核心思想,深入探讨面向对象的核心思想

面向对象编程(ObjectOriented Programming,OOP)是一种编程范式,它使用对象和类来组织和设计软件。面向对象的核心思想包括以下几个方面:1. 对象(Objects):对象是面向对象编程的基本构建块。对象是类的实例,它包含数据(属性)和行为(方法)。每个对象都有自己的状态和行为...

面向对象测试,概述与重要性

面向对象测试(ObjectOriented Testing)是一种针对面向对象软件系统的测试方法,它结合了面向对象编程的特点和软件测试的原则。面向对象测试包括以下几个主要方面:1. 单元测试:针对面向对象程序中的每个类或方法进行测试,确保它们按预期工作。这通常包括测试类的构造函数、属性和方法。2....

云架构设计,构建高效、安全、可扩展的云计算环境

云架构设计是指将云计算技术应用于企业或组织的IT基础设施中,以实现更高的灵活性、可扩展性和成本效益。云架构设计通常包括以下几个关键方面:1. 需求分析:首先需要了解企业的业务需求、性能要求、安全要求等,以确定云架构的目标和范围。2. 选择云服务模型:根据企业的需求,选择合适的云服务模型,如IaaS(...