我们在编写pthon代码时,模块间的数据通信主要采用以下几种方法:

1、采用全局变量。所有模块都通过引用全局变量,通过本模块对此全局变量数据的修改值,其他模块也能访问并得到此全局变量的当前值,由于全局变量的不可控性(经常出现访问的并不是要访问的变量值),不建议大家编码时过多使用全局变量。

2、通过定义的类实例化对象。通过对象调用本类对象的当前属性、方法、函数来得到本类相关数据。此方法限定了只能在定义有类对象的模块中来使用,有时要时实撑握类对象中的变化数据也较麻烦,需要通计时器或管理线程来定时刷对象属性数据得到其当前值。对没有定义类对象的其他模块要想访问此类对象的数据,需要通过定义类对象所在的模块作为中转站来传递数据,可能也很麻烦。

3、采用回调函数来实时得到类对象中的数据,方法是模块A中定义类B对象时,同时传入B对象一个A模块的函数作为B向A实时传递数据的回调函数。使用时,代码运行到B对象模块某一位置,调用此回调函数,即可实时的将B模块中的计算数据回传给了A,让A模块再进一步去处理。如B一直在计算数据,并不断的将计算情况回调给A,A接收到数据后,根据数据不断的对UI界面进行更新。但同B和A模块无直接关联的C模块想要再得到B模块的当前数据就处理起来就很复杂。

4、采用pyside或QT模块定义的类时,可以通过信号槽实时反馈类对象中的数据变化给类对象定义的模块中。信号槽的使用相对抽象,这里不作举例。

5、本文根据python的特性,结合以上方式,偿试采用一个全局字典变量,此字典变量专门存储所有可对外公开调用的模块中的函数方法,对软件中任意一模块,不论是否同其他模块有关联(如无需定义或引用类对象),均可以通过字典存储的其他模块函数来调用此函数。这只是对模块间调用函数的一个测试,可能不符合标准的程序设计思维,仅供大家参考。

测试代码分成以下几个模块:

main.py:主模块,用于测试调用各模块使用全局字典中存储的类对象函数。

testClass.py: 同main模块有关联,在main.py模块实例化此模块类对象,以便进行测试

此模块中也演示了main模块传入的回调函数的示例。

otherClass.py:同main.py和testClass.py模块无任何关联的模块,用于调用全局字典中的testClass类对象函数

gdic.py:定义全局字典变量的模块:

此模块中有定义有全局字典g_dicFuntion,字典数据格式定义如下:

key为整数ID号,每项字典元素格式为:{ID:[要调用的函数名称(实际就是地址),[函数参数列表],['所属模块文件名','所属类名','函数功能说明','函数返回值']}

main.py模块代码如下:

"""
main.py: python中偿试用全局字典调用各类中的函数:用字典存储函数地址,实现在任意可调用处调用
"""
import time,sys,io,randomfrom gdic import g_dicFuntion,gf_addFunToDic  #从gdic.py中导入公用全局变量和全局函数
from testClass import *                       #有加入字典存储函数的类
from otherClass import *                      #测试调用加入字典存储的函数类#本模块中的用于测试的外部函数   
#【字典key=0=>mani.py中的全局函数test1(id)】 
def test1(id):return f'test1({id})'#当作回调函数用于测试:参数采用*,表示参数数量不限
def test2(*args):print(f'得到其他模块传回的值数量={len(args)},参数值={args}')  #本示例回调的两个数据:x+y+z=24,[1, 3.14, True, 'abc', [4, 5, 6]]for i in range(len(args)):print(args[i])############################################################################
if __name__ == '__main__':"""函数主入口"""global g_dicFuntion        #声明全局变量#g_dicFuntion[0]=[test1,[1234],['pyTextFun.py','test1(id)','参数:id=整型','返回值:字符串']]                             #方法一:向字典中加入函数信息gf_addFunToDic(keyID=0,funName=test1,lstArgc=[1234],lstInfo=['pyTextFun.py','test1(id)','参数:id=整型','返回值:字符串'])   #推荐:向字典中加入函数信息【ID=0,即字典的key=0】print(g_dicFuntion)curFuntion=g_dicFuntion.get(0,None)print(curFuntion[0](curFuntion[1][0]))#定义CTest类对象1时,同时传入要回调本模块用的回调函数名test2cTest_obj1=CTest(9,8,7,test2)           #类对象中的函数self.ctest()保存到全局字典变量中,供其他模块无差别调用,建议实例化对象的同时,就对此对象要对外公开的函数分配ID并加入到全局字典中gf_addFunToDic(keyID=1,funName=cTest_obj1.ctest,lstArgc=[9,8,7],lstInfo=['classTest.py','ctest(self,x,y,z)','x=整型,y=整型,z=整型','返回值:字符串'])   #向字典中加入函数信息【ID=1】cTest_obj2=CTest(4,5,6)           #CTest第二个实例化对象,方法同上gf_addFunToDic(keyID=2,funName=cTest_obj2.ctest,lstArgc=[4,5,6],lstInfo=['classTest.py','ctest(self,x,y,z)','x=整型,y=整型,z=整型','返回值:字符串'])   #向字典中加入函数信息【ID=2】cTest_obj1.ctest(1,2,3)     #调用对象方法,此方法有回调函数的示例      cOtherObj=otherClass()      #定义第三方类对象,用来调用类CTest的对象ctestObj1等中的函数及方法(注意此方法是针对实例化对象ctestObj1的,不同的类实例化对象的同一方法可以在字典中分别保存(key不同)cOtherObj.use_classTest()   #调用类CTest的实例化对象cTestObj1等的函数ctest(self,x,y,z)del cTest_obj1              #删除对象cTest_obj1,删除后,此实例化对象不可用,但对象原占用的内存段可能可执行代码段可能还存在CTest.isEnabled[0]=False    #不准再使用cTest_obj1对象在字典中key=1的函数了cOtherObj.use_classTest()   #再测试下结果:仍不会报错,估计此cTest_obj1对象对应的内存段的可执行代码没有被更新覆盖仍可以使用,但不保证代码运行久了不会出错,故应在相关代码中作处理,略

testClass.py模块代码如下:

"""
testClass.py:外部类模块,供pyClassFun.py模块测试全局字典调用类中函数
"""
from gdic import g_dicFuntion,gf_addFunToDic  #从gdic.py中导入公用全局变量和全局函数#本模块中的用于测试的外部函数    
def test3(id):return 'test3'
def test4(x,y):return 'test4'#本模块中的类
class CTest():"""用于测试的类"""objCount=0                 #所有CTest类实例化对象共用的全局变量,使用方法CTest.objCountisEnabled=[]               #本类当前可使用的类对象序号,如类对象被释放或锁定,不准再用字典中存储的类函数地址来调用时,对应下标元素改为Falseglobal g_dicFuntion        #声明为全局变量def __init__(self,x,y,z,callback=None):          self.x,self.y,self.z=x,y,zself.callback=callback      #类对象定义处同时传入回调函数#也可以在初始化时就对类中的可供外部调用的函数分配ID,如下行代码,只适用于实例化一个对象,如实例化多个对象时,ID号的控制将很麻烦#gf_addFunToDic(ID=1,funName=self.ctest,lstArgc=[x,y,z],lstInfo=['classTest.py','ctest(self,x,y,z)','x=整型,y=整型,z=整型','返回值:字符串'])   #向字典中加入函数信息【ID=1】CTest.objCount+=1                    #在其他模块中每初始化一个新类对象,此数自+1CTest.isEnabled.append(True)   #同时增加一可用状态开关#【字典key=1=>mani.py中的类实例化对象cTest_obj1】#【字典key=2=>mani.py中的类实例化对象cTest_obj2】def ctest(self,x,y,z):"""类实例化对象的此函数要被外被其他模块调用,初始化时,已将此函数加入到全局字典中,"""if(self.callback is not None):       #模块向另一模块实时传递数据方法一:函数回调,前提:定义对象时要传入回调函数名称(实际是地址)lstValues=[1,3.14,True,'abc',[4,5,6]]self.callback(x+y+z,lstValues)   #通过回调函数传回本模块生成的数据值return f'CTest->ctest(x={x},y={y},z={z}),CTest.isEnabled={CTest.isEnabled},类对象被实例化数量CTest.ID={CTest.objCount},'

otherClass.py模块代码如下:

"""
otherClass.py:同main.py和testClass.py无任何关联的模块,用于调用全局字典中的testClass类对象函数
"""
from gdic import g_dicFuntion,gf_addFunToDic  #从gdic.py中导入公用全局变量和全局函数class otherClass():"""测试用其他类任意调用全局字典中已保存的类函数的第三方类"""global g_dicFuntion        #声明为全局变量def __init__(self):passdef use_classTest(self):"""跨模块用全局字典中保存的函数地址调用函数,不必使用信号槽或逐级调用"""print('\n===模块otherClass.py中的self.use_classTest函数通过全局字典记录的函数地址调用其他模块函数:本例调用classText.ctest(x,y,z)===')curFuntion_1=g_dicFuntion.get(1,None)   #得到classTest模块中的类CTest实例化对象cTest_obj1的函数ctest(x,y,z)地址,【在字典中:key=1】if(curFuntion_1 is not None):reFun=curFuntion_1[0](curFuntion_1[1][0],curFuntion_1[1][1],curFuntion_1[1][2])print(f'调用字典中保存的KEY={1}的类函数的传入参数值 = {reFun}\n')  else:print(f'调用字典中保存的KEY={1}的类函数为空,没有调用成功\n')curFuntion_2=g_dicFuntion.get(2,None)   #得到classTest模块中的类CTest实例化对象cTest_obj2的函数ctest(x,y,z)地址,【在字典中:key=2】if(curFuntion_2 is not None):reFun=curFuntion_2[0](curFuntion_2[1][0],curFuntion_2[1][1],curFuntion_2[1][2])print(f'调用字典中保存的KEY={2}的类函数的传入参数值 = {reFun}\n')  else:print(f'调用字典中保存的KEY={2}的类函数为空,没有调用成功\n')

全局字典变量模块gdic.py代码如下:

"""
gdic.py:定义全局变量的模块
"""
#定义全局变量
g_dicFuntion={}     #全局字典,保存要调用的函数信息{ID:[要调用的函数名称(实际就是地址),[函数参数列表],['所属模块文件名','所属类名','函数功能说明','函数返回值']}def gf_addFunToDic(keyID,funName,lstArgc,lstInfo):"""向记录全局函数全局字典变量中加入一项函数记录"""print(type(keyID).__name__)c=g_dicFuntion.get(keyID,None)if(type(keyID).__name__=='int' and (g_dicFuntion.get(keyID,None)  is  None)):g_dicFuntion[keyID]=[funName,lstArgc,lstInfo]return Trueelse:print('\n!!!!要加入字典的函数keyID不为整数,或字典key(ID)号已存在,需重新指定key(ID)号!!!!\n')raise ValueError('!!!!要加入字典的函数keyID不为整数,或字典key(ID)号已存在,需重新指定key(ID)号!!!!')  #抛出异常"""
全局字典中可对外使用的函数、方法明细表
keyID号    模块              实例化对象                函数               参数                 返回值         使用时效              调用模块
0       main.py              无                   test1               id=整数                 字符串          长期       main.py
1       classTest.py   main.py->cTest_obj1   self.use_classTest      x=9,y=8,z=7              字符串         有限     otherClass.py->use_classTest
2       classTest.py   main.py->cTest_obj2   self.use_classTest      x=4,y=5,z=6              字符串         长期     otherClass.py->use_classTest
3
4
5
6
7
8
9
"""

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91012.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91012.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/91012.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 部署 flink 1.15.1 并提交作业

下载 1.15.1 https://flink.apache.org/downloads.html#apache-flink-1151 部署模式分类 会话模式应用模式单作业模式 1、会话模式 先启动一个集群,保持一个会话,然后通过客户端提交作业,所有作业都在一个会话执行; 会话模式适合规…

Redis数据量过大的隐患:查询会变慢吗?如何避免?

一、Redis数据过多引发的五大隐患(附系统交互图) #mermaid-svg-X83bpHUu830QXKUt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-X83bpHUu830QXKUt .error-icon{fill:#552222;}#mermaid-svg-…

网络与信息安全有哪些岗位:(3)安全运维工程师

安全运维工程师是企业安全防线的 “日常守护者”,既要确保安全设备与系统的稳定运行,又要实时监控潜在威胁,快速响应并处置安全事件,是连接安全技术与业务运营的关键角色。其核心价值在于通过常态化运维,将安全风险控制…

鱼皮项目简易版 RPC 框架开发(三)

本文为笔者阅读鱼皮的项目 《简易版 RPC 框架开发》的笔记,如果有时间可以直接去看原文, 1. 简易版 RPC 框架开发 前面的内容可以笔者的前面两个篇笔记 鱼皮项目简易版 RPC 框架开发(一) 鱼皮项目简易版 RPC 框架开发(…

嵌入式Linux:注册线程清理处理函数

在 Linux 多线程编程中,线程终止时可以执行特定的清理操作,通过注册线程清理函数(thread cleanup handler)来实现。这类似于使用 atexit() 注册进程终止处理函数。线程清理函数用于在线程退出时执行一些资源释放或清理工作&#x…

【Git】Linux-ubuntu 22.04 初步认识 -> 安装 -> 基础操作

文章目录Git 初识Git 安装Linux-centosLinux-ubuntuWindowsGit 基本操作配置 Git认识工作区、暂存区、版本库添加文件 -- 场景一查看 .git 文件添加文件 -- 场景二修改文件版本回退撤销修改情况一:对于工作区的代码,还没有 add情况二:已经 ad…

轻量级音乐元数据编辑器Metadata Remote

简介 什么是 Metadata Remote (mdrm) ? Metadata Remote 是一个基于 Web 的音频元数据编辑工具,旨在简化在无头服务器(即没有图形用户界面的服务器)上编辑音频文件的元数据。用户只需使用 Docker 和浏览器,无需复杂的…

免费使用|共享服务器上线RTX3080(20GB显存)

共享服务器也上架GPU啦 生物信息学中有很多用到GPU的场景,例如我们分享过的:利用GPU加速TensorFlow、部署本地DeepSeek,空间转录组学习手册合辑加速。因此多种GPU供大家选择:RTX5090、4080S、5070显卡上机。为了让此前的CPU服务器…

搭建DM数据守护集群

1环境与规划准备3个kylin 10操作系统的虚拟机,规划IP、端口、安装目录等。说明搭建REALTIME归档模式、事务一致性的数据守护名称项初始主库机器dm1初始备库机器dm2监视器机器dmmon外部业务IP192.168.23.129192.168.23.130192.168.23.131内部心跳IP192.168.23.129192…

AUTOSAR进阶图解==>AUTOSAR_SRS_OCUDriver

AUTOSAR OCU驱动程序详解 AUTOSAR标准输出比较单元驱动程序架构与实现分析目录 1. 概述 1.1 OCU驱动程序简介1.2 功能概述 2. OCU驱动程序架构 2.1 架构图2.2 层次结构 3. OCU驱动程序组件设计 3.1 组件图3.2 接口定义 4. OCU驱动程序状态管理 4.1 状态图4.2 状态转换 5. OCU驱…

InfluxDB 与 HTTP 协议交互进阶(一)

引言 在当今数字化时代,数据处理的高效性和准确性成为了众多领域关注的焦点。InfluxDB 作为一款开源的时序数据库,凭借其高性能、易扩展等特性,在时间序列数据处理中占据了重要地位。而 HTTP 协议作为互联网应用层的核心协议之一&#xff0c…

NAS远程访问新解法:OMV与cpolar的技术协同价值

文章目录前言1. OMV安装Cpolar2. 配置FTP公网地址3. OMV FTP 配置4. OMV FTP远程连接前言 当家庭存储需求突破本地边界时,传统NAS方案往往陷入"连接困境":复杂的端口转发配置、高昂的公网IP成本、以及始终存在的安全顾虑…开源解决方案OMV虽然…

vue 渲染 | 不同类型的元素渲染的方式(vue组件/htmlelement/纯 html)

省流总结&#xff1a;&#xff08;具体实现见下方&#xff09; vue 组件 ——》<component :is组件名> htmlelement 元素 ——》 ref 、★ v-for ref 或是 ★ vue 的 nextTick 纯 html 结构——》v-html 另外&#xff0c;当数据异步加载时&#xff0c;vue3中如何渲…

Charles中文版深度解析,轻松调试API与优化网络请求

在现代软件开发过程中&#xff0c;调试API、捕获HTTP/HTTPS流量以及优化网络性能是开发者不可避免的挑战。特别是在处理复杂的网络请求和验证API接口的数据传输准确性时&#xff0c;开发者需要一款强大且易于使用的工具。Charles抓包工具凭借其功能强大、界面简洁、易于操作的特…

【CF】Codeforces Round 1039 (Div. 2) E1 (二分答案求中位数)

E1. Submedians (Easy Version)题目&#xff1a;思路&#xff1a;经典不过加了点东西对于求中位数&#xff0c;我们必然要想到二分答案&#xff0c;具体的&#xff0c;对于所有大于等于 x 的数我们令其奉献为 1&#xff0c;小于的为 -1&#xff0c;如果存在某段区间的奉献和大于…

ESP32-S3学习笔记<8>:LEDC的应用

ESP32-S3学习笔记&#xff1c;8&#xff1e;&#xff1a;LEDC的应用1. 头文件包含2. LEDC的配置2.1 配置定时器2.1.1 speed_mode/设置速度模式2.1.2 duty_resolution/设置占空比分辨率2.1.3 timer_num/选择定时器2.1.4 freq_hz/设定PWM频率2.1.5 clk_cfg/选择LEDC的外设时钟源2…

网络安全第14集

前言&#xff1a;小迪安全14集&#xff0c;这集重点内容&#xff1a;0、什么是js渗透测试&#xff1f;在javascript中也存在变量和函数&#xff0c;存在可控变量和函数就有可能存在在漏洞&#xff0c;js开发的web应用和php、java开发的区别是&#xff0c;js能看得到的源代码&am…

代码随想录算法训练营第三十三天

LeetCode.62 不同路径 题目链接 不同路径 题解 class Solution {public int uniquePaths(int m, int n) {// dp表示到达ij有多少条路径int[][] dp new int[110][110];dp[1][1] 1;for(int i 0;i<m;i){dp[i][0] 1;}for(int j 0;j<n;j){dp[0][j] 1;}for(int i 1;i…

银行回单OCR识别技术原理

银行回单OCR&#xff08;光学字符识别&#xff09;技术通过结合图像处理、模式识别和自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;将纸质或电子版银行回单中的非结构化文本&#xff08;如账号、金额、日期等&#xff09;转化为结构化数据。以下是其核心原理和关键…

Day22-二叉树的迭代遍历

昨天学习了递归遍历&#xff1a;递归就是一次次的把参数压入栈中&#xff0c;然后返回的时候还是上一次递归保存的参数。今天学习迭代遍历。迭代遍历就是用栈去模拟保存二叉树的节点&#xff0c;然后依次去遍历&#xff0c;只不过要注意栈的后入先出的规则。前序遍历&#xff1…