全网最适合入门的面向对象编程教程:46 Python函数方法与接口-函数与事件驱动框架

news2024/12/22 11:12:23

全网最适合入门的面向对象编程教程:46 Python 函数方法与接口-函数与事件驱动框架

image

摘要:

函数是 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 自动生成文件注释和函数注释

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

全网最适合入门的面向对象编程教程:21 类和对象的 Python 实现-多文件的组织:模块 module 和包 package

全网最适合入门的面向对象编程教程:22 异常捕获-异常和语法错误

全网最适合入门的面向对象编程教程:23 异常捕获-抛出异常

全网最适合入门的面向对象编程教程:24 异常捕获现-异常的捕获与处理:try/except语句、文件读写示例、Exception引用

全网最适合入门的面向对象编程教程:25 异常捕获-Python 判断输入数据类型

全网最适合入门的面向对象编程教程:26 异常捕获-上下文管理器和with语句

全网最适合入门的面向对象编程教程:26 异常捕获-上下文管理器和with语句

全网最适合入门的面向对象编程教程:27 异常捕获-Python 中异常层级与自定义异常类的实现

全网最适合入门的面向对象编程教程:28 异常捕获-Python编程原则、哲学和规范大汇总

全网最适合入门的面向对象编程教程:29 异常捕获-断言与防御性编程和help函数的使用

全网最适合入门的面向对象编程教程:29 异常捕获-断言与防御性编程和help函数的使用

全网最适合入门的面向对象编程教程:30 Python的内置数据类型-object根类

全网最适合入门的面向对象编程教程:31 Python的内置数据类型-对象Object和类型Type

全网最适合入门的面向对象编程教程:32 Python的内置数据类型-类Class和实例Instance

全网最适合入门的面向对象编程教程:33 Python 的内置数据类型-对象 Object 和类型 Type 的关系

全网最适合入门的面向对象编程教程:33 Python 的内置数据类型-对象 Object 和类型 Type 的关系

全网最适合入门的面向对象编程教程:34 Python的内置数据类型-Python常用复合数据类型:元组和命名元组

全网最适合入门的面向对象编程教程:35 Python的内置数据类型-文档字符串和__doc__属性

全网最适合入门的面向对象编程教程:36 Python的内置数据类型-字典

全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式

全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列

全网最适合入门的面向对象编程教程:39 Python 常用复合数据类型-集合

全网最适合入门的面向对象编程教程:40 Python 常用复合数据类型-枚举和 enum 模块的使用

全网最适合入门的面向对象编程教程:41 Python常用复合数据类型-队列(FIFO、LIFO、优先级队列、双端队列和环形队列)

全网最适合入门的面向对象编程教程:42 Python常用复合数据类型-collections容器数据类型

全网最适合入门的面向对象编程教程:43 Python常用复合数据类型-扩展内置数据类型

全网最适合入门的面向对象编程教程:44 Python内置函数与魔法方法-重写内置类型的魔法方法

全网最适合入门的面向对象编程教程:45 Python实现常见数据结构-链表、树、哈希表、图和堆

更多精彩内容可看:

CM3调试系统简析

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

Avnet ZUBoard 1CG开发板上手—深度学习新选择

SenseCraft 部署模型到Grove Vision AI V2图像处理模块

比赛获奖的武林秘籍:09 一文速通计算机设计大赛,比赛人必看的获奖秘籍

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

比赛获奖的武林秘籍: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

正文

函数

函数是一个命名的代码块,需要 0 个或多个输入参数,运行以后会返回输出值。在 Python 中,函数不仅是对象,也是第一类对象(First-Class Object),这是 Python 函数的一大特性。函数作为对象可以赋值给一个变量、可以作为元素添加到集合对象中、可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的。

image

简单来说,就是在 Python 中可以把函数像普通变量一样任意地使用,。包括赋值,以及作为其它函数的参数和返回值。这样就能很容易地写出高阶函数与闭包的代码。而在其他应用面向对象设计的语言中(如 C++)实现类似操作,需要借助函数指针进行实现。

在许多情况下,我们需要将函数作为参数传递到另一个函数中。最典型的例子就是事件驱动编程模式,**所谓事件驱动编程模式不同于原先依次执行每个函数的编程模式,其基本的处理思路是预先设计一个事件循环所形成的程序,这个事件循环程序不断地检查目前要处理的信息,根据要处理的信息执行一个触发函数进行必要的处理。**其中这个外部信息可能来自一个目录夹中的文件,可能来自键盘或鼠标的动作,或者是一个时间事件。

从事件角度说,事件驱动程序的基本结构是由一个事件收集器、一个事件发送器和一个事件处理器组成。事件收集器专门负责收集所有事件,包括来自用户的(如鼠标、键盘事件等)、来自硬件的(如时钟事件等)和来自软件的(如操作系统、应用程序本身等)。事件发送器负责将收集器收集到的事件分发到目标对象中。事件处理器做具体的事件响应工作,它往往要到实现阶段才完全确定。在事件处理器中一般都需要提前传入一个注册好的回调函数,回调函数被注册之后,程序将继续执行后面的语句,而回调函数则会在对应事件产生后被异步调用。

函数身为一个对象,拥有对象模型的三个通用属性:id、类型、和值。在下面的代码中,我们创建了一个平均值滤波函数,实现三个周期的传感器采样值计算平均值,在代码中,DataList 为全局变量,它用来记录 FileterLength 个周期的采样值,AverageFilter(value)为滤波函数,它的输入为新采集到的数据,函数中,首先将 DataList[]中的数据进行移位,并将新采集到的数据保存到 DataList[]最后的元素中,同时计算 DataList[]中 10 个数据的和,最后返回 FileterLength 个数据和的平均值。示例代码如下:

_# 全局变量,记录三个周期的采样值_
FileterLength   = 3
DataList        = [0] * FileterLength
def AverageFilter(value):
    '''
    平均值滤波函数,实现三个周期的传感器采样值计算平均值
    :param value: 当前采样值
    :return: 滤波后的传感器数值
    '''
    global DataList
    _# 临时变量,存储列表中数据之和_
    sum = 0
    for i in range(FileterLength-1):
        _# 实现列表的移位操作_
        DataList[i] = DataList[i+1]
        _# 实现列表求和_
        sum += DataList[i]
    DataList[FileterLength-1] = value
    sum += DataList[FileterLength-1]
    average = sum / len(DataList)
    return average

我们首先访问一下这个函数的基本属性:

print(id(AverageFilter))
print(type(AverageFilter))
print(AverageFilter)

运行结果如下:

image

我们可以给函数添加自定义属性并且访问自定义属性:

AverageFilter.description = ("The average value filter function realizes the calculation of the average value "
                             "of the sensor sample value for three periods")
print(AverageFilter.description)

运行结果如下:

image

事件驱动框架计时器

接下来我们用一个事件驱动框架计时器的示例更好的说明函数作为参数可以传递到另一个函数中的相关应用。示例代码如下:

import datetime
import time

_# 定义定时器事件类_
class TimedEvent:

    def __init__(self, endtime, callback):
        '''
        初始化方法,存储endtime和callback
        :param endtime:  callback执行前需要等待的时间
        :param callback: 回调函数,即到达执行时间后调用的函数
        '''
        self.endtime = endtime
        self.callback = callback

    def ready(self):
        '''
        判断是否事件已经到达了该执行的适合
        :return:
        '''
        return self.endtime <= datetime.datetime.now()

_# 定义定时器类,轮询检测实现任务调度_
class Timer:
    def __init__(self):
        '''
        初始化方法,定义一个events列表存储事件
        '''
        self.events = []

    def call_after(self, delay, callback):
        '''
        添加新的事件
        :param delay: 执行回调方法之前要等待的秒数
        :param callback: 回调方法
                         callback函数应该接收一个参数:执行调用的计时器
        :return:
        '''
        end_time = (datetime.datetime.now() +
                    datetime.timedelta(seconds=delay))
        self.events.append(TimedEvent(end_time, callback))

    def run(self):
        '''
        轮询检测,执行到达执行时间的回调函数
        :return:
        '''
        _# 轮询检测,执行到达执行时间的回调函数_
        while True:
            _# 使用一个生成器表达式,将将时间已到的事件过滤出来_
            ready_events = (e for e in self.events if e.ready())
            _# 按照顺序执行_
            for event in ready_events:
                event.callback(self)
                _# 执行完成后,移除已执行完毕的任务_
                self.events.remove(event)
            _# 在每次迭代过程中休眠 0.5 秒以防止系统死机_
            time.sleep(0.5)

下面,我们编写几个回调函数测试一下:

def format_time(message, *args):
    '''
    用字符串的 format 方法将当前时间添加到信息中,并说明变量参数
    :param message: 接收任意数量的定位参数
    :param args:    用于在函数中处理传递的位置参数序列
    :return: None
    '''
    _# 当前的时间,格式为:时-分-秒_
    now = datetime.datetime.now().strftime("%I:%M:%S")
    _# 格式化打印参数_
    print(message.format(*args, now=now))

_# 回调函数:任务一_
def Task_One(timer):
    format_time("{now}: Called Task One")

_# 回调函数:任务二_
def Task_Two(timer):
    format_time("{now}: Called Task Two")

_# 回调函数:任务三_
def Task_Three(timer):
    format_time("{now}: Called Task Three")

_# 创建定时器对象_
timer = Timer()
_# 添加回调函数_
timer.call_after(1, Task_One)
timer.call_after(2, Task_One)
timer.call_after(2, Task_Two)
timer.call_after(4, Task_Two)
timer.call_after(3, Task_Three)
timer.call_after(6, Task_Three)
_# 开始运行定时器_
format_time("{now}: Starting")
timer.run()

运行结果如下,可以看到到达各自的执行时间后,每个事件都简单地输出当前时间和一段简短的消息,告诉我们调用的是哪个回调方法。

image

实际上类的方法也可以用作回调函数,示例代码如下

_# 定义类_
class Repeater:
    def __init__(self):
        self.count = 0
    def repeater(self, timer):
        '''
        在函数中在创建一个定时任务
        :param timer: 定时器
        :return: None
        '''
        format_time("{now}: repeat {0}", self.count)
        self.count += 1
        _# 类的方法也可以用作回调函数_
        timer.call_after(5, self.repeater)

_# 创建定时器对象_
timer = Timer()
repeater = Repeater()
_# 添加回调函数,类的方法_
timer.call_after(5, repeater.repeater)
_# 开始运行定时器_
format_time("{now}: Starting")
timer.run()

运行结果如下:

image

从运行结果中我们不能看出,我们可以从当前正在运行的回调函数中给计时器添加新的事件。然后创建一个计时器并添加几个事件,在不同时间之后调用。

Format 函数

在 Python 中,format()是一个内置函数,用于格式化字符串。format()函数提供了灵活的方式来将变量插入到字符串中,并控制它们的显示格式。

它的语法如下:

format(value, format_spec)

其中,参数说明如下:

  • value: 要格式化的值;format_spec: 格式化规范,用于指定值的显示方式。
  • format()函数返回一个格式化后的字符串。

它是通过 {} 和 : 来代替以前的 % 。format 函数可以接受不限个参数,位置可以不按顺序。示例代码如下:

_# 不设置指定位置,按默认顺序_
print("{} {}".format("hello", "world"))
_# 设置指定位置_
print("{0} {1}".format("hello", "world"))
_# 设置指定位置_
print("{1} {0} {1}".format("hello", "world"))

输出如下:

image

image

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

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

相关文章

Simulink库模块作用及简单应用(一)

01--Data Store Memory模块 数据存储模块一般是和数据写入还有数据访问一同搭配使用的 可以从帮助文档看到该模型如下的关键使用信息&#xff1a; Data Store Memory 模块定义并初始化一个命名的共享数据存储&#xff0c;即一个内存区域&#xff0c;供指定相同数据存储名称的…

客户端负载均衡Ribbon 小实例

文章目录 一&#xff0c;概述二&#xff0c;实现过程三&#xff0c;项目源码1. 源码放送&#xff1a;2. 部署方式 四&#xff0c;功能演示五&#xff0c;其他 一&#xff0c;概述 一般来说&#xff0c;提到负载均衡&#xff0c;大家一般很容易想到浏览器 -> NGINX -> 反…

Java 每日一刊(第一期):Java 的历史

文章目录 Java 的起源与诞生Java 的早期发展&#xff08;1995-2000&#xff09;Java 的转型与扩展&#xff08;2000-2010&#xff09;Oracle 时代的 Java&#xff08;2010-至今&#xff09;本期小知识 Java 的起源与诞生 Java 的历史可以追溯到 20 世纪 90 年代&#xff0c;由 …

【数据结构(初阶)】——二叉树

【数据结构】——二叉树 文章目录 【数据结构】——二叉树前言1. 树的概念及结构1.1 树的概念1.2 树的结构 2. 二叉树的概念及结构2.1 二叉树的概念2.2 二叉树的结构2.3 二叉树的性质 3. 二叉树顺序结构及概念3.1 二叉树的顺序结构3.2 堆的概念及结构3.3 堆的实现3.3.1 堆的基本…

【C++ Qt day9】

2、将day1做的登录界面升级优化【资源文件的添加】 3、 使用手动连接&#xff0c;将登录框中的取消按钮使用第2种方式的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上…

黑马点评16——多级缓存-JVM进程缓存

文章目录 什么是多级缓存导入商品案例初识Caffeine实现进程缓存 什么是多级缓存 但是现在的nginx的压力太大了&#xff0c;所以nginx也要部署成集群 当然我们的redis、tomcat都可以部署成集群 导入商品案例 我们在docker中开启了一个mysql的数据库&#xff0c;里面配置了一个…

C和指针:高级指针话题

进一步探讨指向指针的指针 int i; int *pi; int **ppi; 这些声明在内存中创建了下列变量。如果它们是自动变量&#xff0c;无法猜测它们的初始值。 二级指针指向一级指针 ppi&pi; *ppi&i; ia; *pia; **ppia; 为什么要使用指针&#xff1f; 因为函数传参使用值传递不会…

[C#学习笔记]接口的特性与用法

视频地址&#xff1a;一期视频看透C#接口的全部特性及用法_哔哩哔哩_bilibili 强烈推荐学习C#和WPF的朋友关注此UP&#xff0c;知识点巨多&#xff0c;讲解透彻&#xff01; 一、总览 public interface IOverall {/// <summary>/// 最普通的方法/// </summary>v…

[数据集][目标检测]打电话检测数据集VOC+YOLO格式8985张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8985 标注数量(xml文件个数)&#xff1a;8985 标注数量(txt文件个数)&#xff1a;8985 标注…

【C++】C++入门基础,详细介绍命名空间,缺省参数,函数重载,引用,内联函数等

目录 1. 命名空间 1.1 使用命名空间的目的 1.2 命名空间定义 1.3 命名空间使用 2. 缺省参数 2.1 缺省参数概念 2.2 缺省参数分类 2.3 实际案例 2.4 注意事项 3. 函数重载 3.1 函数重载概念 3.2 函数重载原理 4. 引用 4.1 引用的概念 4.2 引用的特性 4.3 使用…

JavaScript案例---求质数

n等于19&#xff0c;是质数 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wid…

OpenAI Gymnasium, are there any libraries with algorithms supporting it?

题意&#xff1a;对于OpenAI Gym&#xff0c;是否有支持它的算法库&#xff1f; 问题背景&#xff1a; OpenAI has released a new library called Gymnasium which is supposed to replace the Gym library. There are many libraries with implamentations of RL algorithms…

机械学习—零基础学习日志(Python做数据分析02)

现在开始使用Python尝试做数据分析。具体参考的网址链接放在了文章末尾。 引言 我通过学习《利用Python进行数据分析》这本书来尝试使用Python做数据分析。书里让下载&#xff0c;anaconda&#xff0c;使用Jupyter来写代码&#xff0c;只是下载一个anaconda的确有点费时间&am…

RabbitMQ 04 集群,用于提高系统性能

01.背景 02.单个节点的MQ会持久化的记录什么数据 03.集群情况下的MQ会持久化的记录什么数据 04.集群中的队列 单个节点的队列&#xff1a; 集群的队列&#xff1a; 05. 两个原因&#xff1a; 这样做带来的好处&#xff1a; 05.集群的交换机 交换机的本质 交换机在集…

Unity TextMeshPro 设置竖排

默认竖排是这样的 但是我们要的竖排效果并不是这样我们要是竖排连续的根据文本限制来进行换行 第一步我们先设置文本的旋转Z轴为90如下图 然后我们给文本加一个Tag <rotate270> 如下图 但是这个效果还是不是我们想要的效果我们可以使用TexeMeshPro提供的一个选项EnableR…

97.游戏的启动与多开-共享内存多开检测

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 上一个内容&#xff1a;96.游戏的启动与多开-窗口多开检测与破解 以 96.游戏的启动与多开-窗口多开检测与破解 …

Word文档的读取(1)

读取一个班的答题卡 解决方法&#xff1a; 导入os模块后&#xff0c;将乔老师的文件夹路径 /Users/qiao/answerKey 赋值给变量allKeyPath。使用os.listdir()函数获取该路径下所有的答题卡名称列表&#xff0c;并赋值给变量allItems。最后使用for循环遍历所有答题卡&#xff0c…

【知识小妙招来喽!】文件防泄密措施有哪些?这6个有效方法防止企业员工泄密!

在信息高度发达的时代&#xff0c;企业数据的安全性和保密性成为了企业运营中不可忽视的重要环节。 一旦敏感文件被泄露&#xff0c;不仅可能导致商业机密被窃取&#xff0c;还可能给企业带来重大的经济损失和声誉损害。 因此&#xff0c;采取一系列有效的文件防泄密措施&…

spring security 中的异常

一、简介 Spring Security 中异常主要分为两大类: 1、AuthenticationException: 认证异常 2、AccessDeniedException: 授权异常 AuthenticationEntryPoint 该类用来统一处理 AuthenticationException 异常 AccessDeniedHandler 该类用来统一处理 AccessDeniedException 异常…

HarmonyOS笔记

HarmonyOS简介 HarmonyOS是新一代的智能终端操作系统&#xff0c;为不同设备的智能化、互联与协同提供了统一的语言&#xff0c;为用户带来简捷&#xff0c;流畅&#xff0c;连续&#xff0c;安全可靠的全场景交互体验。 HarmonyOS结合移动生态发展的趋势&#xff0c;提出了三大…