Python基础(十)——闭包、装饰器、设计模式与多线程编程

server/2024/9/22 14:25:27/

十一.高级用法

1.闭包

函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,把这个使用外部函数变量的内部函数称为闭包

解释:

外部函数的参数因为作用域的原因,只是一个临时变量,调用完函数对于外部而言变量就消失了,而内部函数的作用域则为外部函数定义的区域。因此,把原本的全局变量作为参数放入外部函数中,成为局部变量,而该局部变量只能被内部函数访问,从而实现变量的安全化。

适用于:依赖外部全局变量,但是不希望全局变量被访问而修改的情况。

缺点:

由于内部函数持续引用外部函数的值,导致这部分内存空间不被释放,一直占用内存。

python"># 简单的闭包
def outer(num1):def inner(num2):print(num1+num2)return inner # 返回值为内部函数f1 = outer(50) # f1接收的为一个函数
f1(20)
"""
返回值:
70
"""# 使用nonlocal关键字修饰外部函数
def outer(num1):def inner(num2):nonlocal num1# 使用nonlocal关键字修饰外部函数的变量,才可以在内部函数中修改它num1 = 200print(num1+num2)return inner # 返回值为内部函数f1 = outer(50) # f1接收的为一个函数
f1(20)
"""
返回值:
220
"""# 闭包实现ATM机
def outer(all_money = 0):def inner(money, flag=True):nonlocal all_moneyif flag:all_money += moneyprint(f"成功存款{money}元,账户余额为{all_money}元")else:all_money -= moneyprint(f"成功取款{money}元,账户余额为{all_money}元")return inneraccount = outer()
account(2000, True)
account(500, False)"""
返回值:
成功存款2000元,账户余额为2000元
成功取款500元,账户余额为1500元
"""
2.装饰器

装饰器也是一种闭包,其功能是在不破坏目标函数原有代码和功能的前提下,为目标函数增加新功能。

  • 一般写法:(闭包写法)执行逻辑

定义闭包函数,函数内部包括:执行目标函数、添加新的功能

python">import random
import time
def outer(func):def inner():print("我困死要睡觉了")  # 新的功能func()    # 执行目标函数print("我不得不起床了")  # 新的功能return innerdef sleep():  # 目标函数print("睡觉中……勿扰……")time.sleep(random.randint(1, 10))fun = outer(sleep)
fun()
"""
返回:
我困死要睡觉了
睡觉中……勿扰……
我不得不起床了
"""
  • 语法糖写法

使用@外部函数,定义在目标函数之上。把sleep函数作为参数传入outer函数,返回inner函数执行了操作逻辑。

python">import random
import time
def outer(func):def inner():print("我困死要睡觉了")func()print("我不得不起床了")return inner# @外部函数,定义在目标函数之上
@outer
def sleep():print("睡觉中……勿扰……")time.sleep(random.randint(1, 10))sleep()"""
返回值:
我困死要睡觉了
睡觉中……勿扰……
我不得不起床了
"""
3.设计模式

是一种编程套路思想,面向对象也属于设计模式的一种。

设计模式有多种,可以深入学习。此处仅介绍基础常用的单例模式和工厂模式。

  • 单例模式

某些场景下,需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例,用以节省类对象的开销和内存开销,比如某些工具类,仅需要一个实例,即可在各处使用。

【保证一个类只有一个实例,并提供一个访问它的全局访问点】

使用方式:

在一个文件中定义该类并获得类对象,在另一个文件中通过import导入类对象。

python"># test.pyclass tools:passmy_tool = tools()# main.py
from test import my_toolt1 = my_tool
t2 = my_tool
t3 = my_toolprint(id(t1))
print(id(t2))
print(id(t3))
# t1、t2、t3是同一个对象,地址相同
"""
返回值:
2146066533584
2146066533584
2146066533584
"""
  • 工厂模式

当需要大量创建一个类的实例时,从原生的使用类的构造去创建对象的形式。

优点:

大批量创建对象时有统一的入口,易于维护;

当发生修改时,仅修改工厂类的创建方法即可;

python">class Phone:passclass HuaWei(Phone):passclass XiaoMi(Phone):passclass Honour(Phone):passclass PhoneFactory:def get_phone(self, phone_type):if phone_type == '1':return HuaWei()elif phone_type == '2':return XiaoMi()else:return Honour()pf = PhoneFactory()
phone1 = pf.get_phone('1')
phone2 = pf.get_phone('2')
phone = pf.get_phone('3')
4.进程与线程

**进程:**一个程序运行在系统上则称该程序为一个进程,分配ID方便系统管理。操作系统中可以运行多个进程,即多任务运行。

**线程:**归属于进程,是进程实际工作的最小单位,执行不同的工作。一个进程可以开启多个线程,即多线程运行。

**注意:**进程之间是内存隔离的,不同的进程拥有各自的内存空间。

线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间共享进程拥有的内存。

**并行执行:**同时执行不同的工作,进程之间是并行执行的,线程之间也是。

5.多线程

使用threading模块实现。

  • 单线程
python">import timedef sing():while True:print("唱歌")time.sleep(1)def dance():while True:print("跳舞")time.sleep(1)if __name__ == '__main__':sing()dance()"""
输出:
唱歌
唱歌
唱歌
唱歌
唱歌
唱歌
唱歌
……
"""
  • 多线程
python">import threading
import timedef sing():while True:print("唱歌")time.sleep(1)def dance():while True:print("跳舞")time.sleep(1)
"""
thread = threading.Thread(group= , target= , name=, args= , kwargs=)
-group: 未来功能的预留参数
-target: 执行的目标任务名
-name: 线程名,一般不用设置
-args: 以元组形式给执行任务传参
-kwargs: 以字典形式给执行任务传参
"""if __name__ == '__main__':# 创建唱歌跳舞的线程sing_thread = threading.Thread(target=sing)dance_thread = threading.Thread(target=dance)# 线程工作sing_thread.start()dance_thread.start()
"""
输出:
唱歌
跳舞
跳舞唱歌
唱歌跳舞
唱歌跳舞
唱歌跳舞
唱歌
跳舞
唱歌跳舞
唱歌跳舞
唱歌跳舞
…………
"""   import threading
import timedef sing(msg):while True:print(msg)time.sleep(1)def dance(msg):while True:print(msg)time.sleep(1)if __name__ == '__main__':# 创建唱歌跳舞的线程sing_thread = threading.Thread(target=sing, args=("唱歌啦……",))dance_thread = threading.Thread(target=dance, kwargs={"msg": "跳舞啦……"})# 线程工作sing_thread.start()dance_thread.start()"""
输出:
唱歌啦……跳舞啦……
跳舞啦……唱歌啦……
唱歌啦……跳舞啦……
唱歌啦……跳舞啦……
跳舞啦……
唱歌啦……
唱歌啦……跳舞啦……
…………
"""

记录学习过程的笔记,欢迎大家一起讨论,会持续更新


http://www.ppmy.cn/server/120311.html

相关文章

Vue.js与Flask/Django后端配合

Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,而 Flask 和 Django 是两个流行的 Python Web 框架,分别用于构建轻量级和全功能的 Web 应用程序。将 Vue.js 与 Flask 或 Django 后端配合使用,可以创建一个现代化的、前后端分离的 W…

2024华为杯E题成品文章已出!

E题高速公路应急车道紧急启用模型 点击链接加入群聊【2024华为杯数学建模助攻资料】:http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kxtS4vwn3gcv8oCYYyrqd0BvFc7tNfhV7&authKeyedQFZne%2BzvEfLEVg2v8FOm%2BWNg1V%2Fiv3H4tcE6X%2FW6lCmkhaSaZV4PwQ%2FOVPDtF%2B&…

缓存预热方案详解

在高性能Web应用中,缓存技术是提升系统响应速度的关键手段之一。然而,在系统启动或重启后,缓存往往是空的,此时来自用户的请求将直接打到数据库上,导致响应时间增加。为了避免这种情况,缓存预热就显得尤为重…

如何安装和注册 GitLab Runner

如何安装和注册 GitLab Runner GitLab Runner 是一个用于运行 GitLab CI/CD (Continuous Integration/Continuous Deployment) 作业。它是一个与 GitLab 配合使用的应用程序,可以在本地或云中运行。Runner 可以执行不同类型的作业,例如编译代码、运行测…

【Docker】安装全流程与配置完整镜像源(可安装 nginx)

目录 一、卸载历史版本(选)二、配置 yum 源三、安装 docker四、配置 docker 镜像源加速(选、强烈建议)4.1 配置阿里镜像加速4.2 配置其他镜像源 五、启动 docker参考文章与视频 本文基于 Linux - CentOS 7 操作系统。 一、卸载历史…

系统架构设计师 大数据架构篇二

大数据架构 🌐 大数据处理系统分析 🔍 大数据处理系统三大挑战 🚀 非结构化数据处理:如何处理非结构化和半结构化数据。复杂性与不确定性:大数据复杂性、不确定性特征描述的刻画方法和大数据的系统建模。异构性影响…

机械设备产品资料方案介绍小程序系统开发制作

设备产品资料介绍小程序系统,是一家工业机械设备生产厂家为了更好的服务客户而定制开发的一套小程序系统,让用户通过小程序就可以了解公司产品介绍的详细参数、售后服务和产品操作手持等。 该小程序系统里面主要开发的功能模块有: 1、产品目…

【百日算法计划】:每日一题,见证成长(020)

题目 删除字符串中的所有相邻重复项 给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。 在 S 上反复执行重复项删除操作,直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一…