1、字符串格式化
1.1 f-string
格式化字符串,快速把变量、表达式嵌入字符串内部
用法:
{内容:格式符} 内容:变量 / 表达式; 冒号后:控制数字精度、对齐、进制、填充样式1)变量值加入字符串
name="张三"age=22s=f"姓名:{name},年龄:{age}"print(s)输出:
姓名:张三,年龄:222)表达式结果加入字符串
a=10b=3print(f"总和:{a+b},取整除法:{a//b}")print(f"大写:{'hello'.upper()}")输出
总和:13,取整除法:3 大写:HELLO3)保留小数位
num=3.1415926a=f"{num:.2f}"print(a)3.14
b=f"{num:.4f}"print(b)3.1416
4)千位分隔符
money=1234567c=f"{money:,}"print(c)输出:1,234,5675)百分比格式
rate=0.785c=f"{rate:.1%}"print(c)输出:78.5%6)补零、固定宽度
占3位,前面补0
n=5c=f"{n:03d}"print(c)输出:005占5个字符宽度,右对齐
c=f"{n:5d}"print(c)输出:57)< 左对齐、> 右对齐、^ 居中
8)进制转换
val=15>>>f"{val:d}"'15'>>>f"{val:x}"'f'>>>f"{val:X}"'F'>>>f"{val:b}"'1111'9)转义 {{}}
>>>f"{{hello}}"'{hello}'10)嵌套f-string
num=3.14>>>res=f"结果:{f'{num:.2f}'}">>>print(res)结果:3.1411)字典、对象取值
>>>user={"id":1,"nick":"小李"}>>>f"id:{user['id']},昵称:{user['nick']}"'id:1,昵称:小李'2、asyncio
2.1 异步IO
asyncio = Python 单线程异步 IO 编程库,靠协程 + 事件循环实现网络 IO 并发
示例:
importasyncioasyncdeftest():awaitasyncio.sleep(2)return"执行完毕"res=asyncio.run(test())print(res)调用 asyncio.run 后,等待test执行完毕,再往下执行。
2.2 同步阻塞、异步并发
注意:调用 asyncio.run 会卡住,站在使用者角度是同步阻塞;但是,协程内部,是异步并发的。
一个 async def 函数里面,遇到await 等待、休眠时,不会霸占 CPU,事件循环可以切换去跑其他协程,这就是异步的本质,内部可以同时干多件事。
外部调用者,必须等整个异步程序全部跑完,才交出控制权回到普通代码,所以外层看起来是阻塞卡住的。
2.3 async def协程函数
被 async def 关键字修饰的函数,统一叫做协程函数,形式如下:
asyncdefwork():awaitasyncio.sleep(1)return10- 直接调用协程函数,不会直接执行,而是生成一个协程对象;
- 协程对象交由事件循环运行:asyncio.run;
- 然后执行协程函数中的代码;
2.4 await 关键字
await 关键字是协程内部专用的;
只能写在 async def 函数里:
遇到 await xxx:
- 当前协程暂停、让出 CPU 控制权
- 事件循环去执行其他就绪任务
- 等待 IO 操作(休眠、网络请求)完成后,再切回来继续执行当前协程
2.5 多任务异步执行示例
两个任务并发执行
asyncdefa():awaitasyncio.sleep(2);print("A")asyncdefb():awaitasyncio.sleep(1);print("B")asyncdefmain():t1=asyncio.create_task(a())t2=asyncio.create_task(b())awaitt1awaitt2 asyncio.run(main())虽然两个任务a和b分别执行2秒、1秒;
但是整体只执行2秒;
2.6 asyncio.gather 批量执行
importasyncio# 定义几个异步任务asyncdeftask1():awaitasyncio.sleep(2)# 模拟耗时IOreturn"任务1完成"asyncdeftask2():awaitasyncio.sleep(1)return"任务2完成"asyncdeftask3():awaitasyncio.sleep(1.5)return"任务3完成"asyncdefmain():results=awaitasyncio.gather(task1(),task2(),task3())print(results)# 结果顺序永远和传入顺序一致if__name__=="__main__":asyncio.run(main())输出:
['任务1完成', '任务2完成', '任务3完成']2.7 loop.run_forever:事件永久运行
使用步骤:
1)asyncio.get_event_loop()
获取当前线程的事件循环对象(EventLoop),所有协程、异步任务、IO 事件都由这个循环统一调度执行
2)loop.run_forever()
让事件循环永久无限运行,不会主动退出;
当触发:loop.stop()、loop.close()或者系统发送的终止信号时,退出事件循环;
3)示例
importasyncioasyncdeftask():whileTrue:print("异步任务运行中")awaitasyncio.sleep(1)loop=asyncio.get_event_loop()loop.create_task(task())loop.run_forever()4)对比run()方法
python3.6及之前使用 loop.run_forever();
pyhton3.7之后推荐使用新方法 asyncio.run()
asyncdefmain():whileTrue:print("异步任务运行中")awaitasyncio.sleep(1)asyncio.run(main())2.8 run_until_complete:一次性异步
运行直到传入的协程执行完毕就退出
2.9 进程不退出
loop=asyncio.get_event_loop()…… loop.run_forever()如果将代码功能放入单独线程中运行,主线程没有永久循环时,进程会退出;
可以使用上面的方式实现:进程常驻、“保持运行”。
作用和 threading.Event().wait() 或 while True: time.sleep(1) 类似