Python 技能提升(三)

global 和 nonlocal

b = '全局变量 global variable'def foo():a = '局部变量 local variable'# 在局部里面操作全局变量,需要加上声明global bb = b + '!!!'print(b)foo()
# 全局变量 global variable!!!
b = '全局变量 global variable'def foo():a = '局部变量 local variable'# 在二级局部变量里面操作一级局部变量,则使用 nonlocal 进行声明def inner_foo():nonlocal aa = a + '!!!'print(a)inner_foo()print(a)foo()
# 局部变量 local variable!!!
# 局部变量 local variable!!!

协程

概念

基本认识

  • 协程不是计算机提供的,它由程序员认为创造
  • 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术
  • 简单来说,就是通过一个线程实现代码块相互切换执行

实现协程的方式

  • 通过第三方模块 greenlet
  • yield 关键字
  • asyncio 装饰器(Python 3.4)
  • async、await 关键字(Python 3.5)【推荐】

实现

通过 greenlet 实现(了解)

pip install greenlet
from greenlet import greenletdef func1():print(1)		# 第2步:输出1gr2.switch()	# 第3步:切换到 func2 函数print(2)		# 第6步:输出2gr2.switch()	# 第7步:切换到 func2 函数,从上一次执行的位置继续向后执行def func2():print(3)		# 第4步:输出 3gr1.switch()	# 第5步:切换到 func1 函数,从上一次执行的位置继续向后执行print(4)		# 第8步:输出4gr1 = greenlet(func1)
gr2 = greenlet(func2)gr1.switch()  # 第1步:去执行 func1 函数

通过 yield 关键字(了解)

def func1():yield 1yield from func2()yield 2def func2():yield 3yield 4# 调用生成器函数,返回生成器对象
obj = func1()
print(obj)# for...in... 背后会不断调用 next(obj) 来获取 yield 产生的数据
for i in obj:print(i)# <generator object func1 at 0x0000025CB2A84E80>
# 1
# 3
# 4
# 2"""
从上面的输出结果来看,我们通过 yield 实现了协程:先在func1中输出1,然后切换到func2中输出3,
接着继续输出4,最后又切换到func1中输出2
"""

通过 asyncio 模块(了解)

  • 在 Python 3.4 版本中引入了 asyncio 模块
import asyncio@asyncio.coroutine
def func1():print('正在发送请求下载图片A')yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到task_list中的其他任务print('图片A下载完成')@asyncio.coroutine
def func2():print('正在发送请求下载图片B')yield from asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到task_list中的其他任务print('图片B下载完成')task_list = [asyncio.ensure_future(func1()),asyncio.ensure_future(func2()),
]# 创建一个事件循环对象
loop = asyncio.get_event_loop()# 让事件循环对象,执行"任务列表"里面的任务
loop.run_until_complete(asyncio.wait(task_list))

通过 async 和 await 关键字(掌握)

  • 在 Python 3.5 版本中引入了 asyncawait 关键字
import asyncioasync def func1():print('正在发送请求下载图片A')await asyncio.sleep(3)  # 遇到IO耗时操作,自动切换到task_list中的其他任务print('图片A下载完成')async def func2():print('正在发送请求下载图片B')await asyncio.sleep(1)  # 遇到IO耗时操作,自动切换到task_list中的其他任务print('图片B下载完成')task_list = [asyncio.ensure_future(func1()),asyncio.ensure_future(func2()),
]loop = asyncio.get_event_loop()  # 创建一个事件循环对象
loop.run_until_complete(asyncio.wait(task_list))  # 让事件循环对象,执行"任务列表"里面的任务
# 在 Python 3.7 版本中,可以使用 asyncio.run() 来替代上面两行代码# 运行结果:
# 正在发送请求下载图片A
# 正在发送请求下载图片B
# 图片B下载完成
# 图片A下载完成

协程函数与协程对象

import asyncio
import time# 协程函数
async def func():print('执行中...')await asyncio.sleep(3)print('执行完毕!')# 协程对象
obj = func()  # 注意:在创建协程对象时,函数内部代码不会执行# 执行协程函数
# loop = asyncio.get_event_loop()  # 创建一个事件循环对象
# loop.run_until_complete(obj)     # 让事件循环对象做一些任务
asyncio.run(obj)  # 此行代码可以替代上面两行代码

await

# await + 可等待对象(协程对象、Future对象、Task对象)import asyncioasync def foo1():print('开始执行 foo1 内部代码')# 遇到IO操作时,挂起当前协程(任务),等IO操作完成之后再继续往下执行# 当协程挂起时,事件循环可以去执行其他协程(任务)response = await foo2()print('IO请求结束,结果为', response)print('结束执行 foo1 内部代码')async def foo2():print('Start foo2')await asyncio.sleep(2)print('End foo2')return 'OK'asyncio.run(foo1())# 开始执行 foo1 内部代码
# Start foo2
# End foo2
# IO请求结束,结果为 OK
# 结束执行 foo1 内部代码
import asyncioasync def foo1():print('开始执行 foo1 内部代码')response = await foo2()print('IO请求结束,结果为', response)response = await foo2()print('IO请求结束,结果为', response)print('结束执行 foo1 内部代码')async def foo2():print('Start foo2')await asyncio.sleep(2)print('End foo2')return 'OK'asyncio.run(foo1())# 开始执行 foo1 内部代码
# Start foo2
# End foo2
# IO请求结束,结果为 OK
# Start foo2
# End foo2
# IO请求结束,结果为 OK
# 结束执行 foo1 内部代码

task 对象

  • 用于在事件循环中添加多个任务的
import asyncioasync def foo2(name: str):print(f'{name}开始执行')await asyncio.sleep(2)print(f'{name}结束执行')return f'{name} OK'async def foo1():print('foo1 开始')# 创建task对象,将当前执行func函数任务添加到事件循环中task1 = asyncio.create_task(foo2('task_1'))# 创建task对象,将当前执行func函数任务添加到事件循环中task2 = asyncio.create_task(foo2('task_2'))response1 = await task1print(response1)response2 = await task2print(response2)print('foo1 结束')asyncio.run(foo1())  # 通过协程函数创建一个协程对象,充当参数传入asyncio.run()函数中# foo1 开始
# task_1开始执行
# task_2开始执行
# task_1结束执行
# task_2结束执行
# task_1 OK
# task_2 OK
# foo1 结束
import asyncioasync def foo2(name: str):print(f'{name}开始执行')await asyncio.sleep(2)print(f'{name}结束执行')return f'{name} OK'async def foo1():print('foo1 开始')task_list = [asyncio.create_task(foo2('task_1')),asyncio.create_task(foo2('task_2')),]return_value, pending = await asyncio.wait(task_list, timeout=2)  # 默认 timeout=None。如果超时,pending里面会有一个"待处理的任务"对象print(return_value)  # 返回一个集合print(pending)  # 返回一个集合print('foo1 结束')asyncio.run(foo1())

future 对象

  • task 继承 future,task 对象内部 await 结果的处理基于 future 对象来的
import asyncioasync def set_after(future):await asyncio.sleep(2)future.set_result('666')async def main():# 获取当前事件循环loop = asyncio.get_running_loop()# 创建一个任务(future对象),这个任务什么都不干future = loop.create_future()# 创建一个任务(task对象),绑定了set_after函数,函数内部在2s之后,会给future赋值# 即:手动设置future任务的最终结果,那么future就可以结束了await loop.create_task(set_after(future))# 等待任务最终结果,没有结果会一直等待下去data = await futureprint(data)  # 666asyncio.run(main())

异步迭代器

import asyncio
import randomclass Reader(object):"""自定义异步迭代器"""def __init__(self):self.count = 0def __aiter__(self):return selfasync def readline(self):await asyncio.sleep(random.randint(1, 5))self.count += 1if self.count == 100:return Nonereturn self.countasync def __anext__(self):val = await self.readline()if val is None:raise StopAsyncIterationreturn valasync def func():obj = Reader()async for i in obj:  # 背后会不断的调用 __anext__() 方法print(i)asyncio.run(func())

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

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

相关文章

Python 递归函数一例

现有示例数据 # 示例数据 pending_join [ {increment: "department Finance", statement_index: 0}, {increment: "name Lisa", statement_index: 2}, {increment: "gender Female", statement_index: 3}, {increment: "hire_date <…

redis如何实现分布式锁

Redisson是怎么实现分布式锁的 分布式锁&#xff1a;Redisson 提供了一种简单而强大的方式来实现分布式锁。 它支持多种锁模式&#xff0c;如公平锁、可重入锁、读写锁等&#xff0c;并且提供了锁的超时设置和自动释放功能。 锁的获取 在Redisson中常见获取锁的方式有 lock() …

【代码随想录训练营】【Day 37】【贪心-4】| Leetcode 840, 406, 452

【代码随想录训练营】【Day 37】【贪心-4】| Leetcode 840, 406, 452 需强化知识点 python list sort的高阶用法&#xff0c;两个key&#xff0c;另一种逆序写法python list insert的用法 题目 860. 柠檬水找零 思路&#xff1a;注意 20 块找零&#xff0c;可以找3张5块升…

Mysql基础教程(13):GROUP BY

MySQL GROUP BY 【 GROUP BY】 子句用于将结果集根据指定的字段或者表达式进行分组。 有时候&#xff0c;我们需要将结果集按照某个维度进行汇总。这在统计数据的时候经常用到&#xff0c;考虑以下的场景&#xff1a; 按班级求取平均成绩。按学生汇总某个人的总分。按年或者…

“世界酒中国菜”系列活动如何助推乡村振兴和文化交流?

"世界酒中国菜"系列活动如何助推乡村振兴和文化交流&#xff1f; 《经济参考报》&#xff08;2024年5月24日 第6版&#xff09; 新华社北京&#xff08;记者 张晓明&#xff09; “世界酒中国菜”系列活动自启动以来&#xff0c;已在国内外产生了广泛影响。这一国家…

mysql面试之分库分表总结

文章目录 1.为什么要分库分表2.分库分表有哪些中间件&#xff0c;不同的中间件都有什么优点和缺点&#xff1f;3.分库分表的方式(水平分库,垂直分库,水平分表,垂直分表)3.1 水平分库3.2 垂直分库3.3 水平分表3.4 垂直分表 4.分库分表带来的问题4.1 事务一致性问题4.2 跨节点关联…

【退役之重学 SQL】什么是笛卡尔积

一、初识笛卡尔积 概念&#xff1a; 笛卡尔积是指在关系型数据库中&#xff0c;两个表进行 join 操作时&#xff0c;没有指定任何条件&#xff0c;导致生成的结果集&#xff0c;是两个表中所有行的组合。 简单来说&#xff1a; 笛卡尔积是两个表的乘积&#xff0c;结果集中的每…

力扣 454题 四数相加Ⅱ 记录

题目描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0示例 1&#xff1a; 输入&#xff1a;nums1 …

Flutter 中的 SliverOpacity 小部件:全面指南

Flutter 中的 SliverOpacity 小部件&#xff1a;全面指南 Flutter 是一个功能强大的 UI 框架&#xff0c;由 Google 开发&#xff0c;允许开发者使用 Dart 语言来构建高性能、美观的跨平台应用。在 Flutter 的滚动组件体系中&#xff0c;SliverOpacity 是一个用来为其子 Slive…

强化学习中Q值的概念

在强化学习中&#xff0c;Q值是一个非常核心的概念&#xff0c;用来表示在给定的状态下&#xff0c;采取某个特定动作所期望获得的总回报。Q值基本上是一种衡量“动作价值”的方式&#xff0c;即在当前状态采取一个动作能带来多大价值。 定义和计算 Q值通常表示为 (Q(s, a))&…

RabbitMQ小结

MQ分类 Acitvemq kafka 优点&#xff1a;性能好&#xff0c;吞吐量高百万级&#xff0c;分布式&#xff0c;消息有序 缺点&#xff1a;单机超过64分区&#xff0c;cpu会飙高&#xff0c;消费失败不支持重试 &#xff0c; Rocket 阿里的mq产品 优点&#xff1a;单机吞吐量也…

香橙派 Kunpeng Pro:基于ncnn的深度学习模型量化与部署实践

一 引言 近10年里以深度学习为代表的机器学习技术在图像处理&#xff0c;语音识别&#xff0c;自然语言处理等领域里取得了非常多的突破&#xff0c;其背后的核心算法是深度学习为代表的AI基础模型。 一般来讲&#xff0c;我们进行AI项目研发时&#xff0c;遵循三个步骤。 第…

LabVIEW步进电机的串口控制方法与实现

本文介绍了在LabVIEW环境中通过串口控制步进电机的方法&#xff0c;涵盖了基本的串口通信原理、硬件连接步骤、LabVIEW编程实现以及注意事项。通过这些方法&#xff0c;用户可以实现对步进电机的精确控制&#xff0c;适用于各种自动化和运动控制应用场景。 步进电机与串口通信…

python3.8环境下安装pyqt5

1.实验目的 测试python可视化工具包pyqt5,为后期做系统前端页面做铺垫 2.实验环境 1.软件 anaconda2.5 pycharm2024.1.1 pyqt5 2.硬件 GPU 4070TI Intel I7 1400K 3. 安装步骤 (base) C:\Users\PC>conda -V conda 23.7.4(base) C:\Users\PC>conda create qttest p…

spring项目修改时间格式

一、配置方式 在application.yml上添加 spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8 二、注解方式 1、添加依赖 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId&…

解释def __int__(self):和def __init__(self):的区别

文章目录 __init__ 方法例子 __int__ 方法例子 总结 def __int__(self): 和 def __init__(self): 是Python中两个不同的特殊方法&#xff08;或魔法方法&#xff09;&#xff0c;它们有着不同的用途和含义。 __init__ 方法 作用&#xff1a;__init__ 方法是类的构造函数。当你…

大文件分片【笔记】

createChunk.js Spark-md5计算文件各分片MD5生成文件指纹 可以帮助我们更加方便地进行文件哈希计算和文件完整性检测等操作。 import sparkMd5 from ./sparkmd5.jsexport function createChunk(file, index, chunkSize) {return new Promise((resolve, reject) > {const sta…

整理好了!2024年最常见 20 道 Kafka面试题(一)

一、什么是Apache Kafka&#xff0c;它主要用于什么场景&#xff1f; Apache Kafka是一个分布式流处理平台&#xff0c;最初由LinkedIn开发&#xff0c;后来成为Apache软件基金会的一个开源项目。它被设计为一个高吞吐量、可扩展、容错的消息队列系统&#xff0c;能够处理实时…

【java】【python】leetcode刷题记录--栈与队列

232 用栈实现队列 题目描述 两个栈模拟队列的思路是利用栈&#xff08;后进先出结构&#xff09;的特性来实现队列&#xff08;先进先出结构&#xff09;的行为。这种方法依赖于两个栈来逆转元素的入队和出队顺序&#xff0c;从而实现队列的功能。 入队操作&#xff08;使用s…