import asyncio
import numpy
import decimal
import re
import datetime
from math import radians, cos
import nest_asyncio
nest_asyncio.apply()
1.python 3.5的新增特性
01. 标准库中的改进
- 新的subprogress.run() 方法
02. 新的语法特性
001.使用async await语法实现协程(coroutine)
如下
async def hello():
print('hello')
await hello()
async for
可以遍历你写的异步操作的迭代器
下面是官方给出的例子, 不过不知道为什么在python3.8 jupyter notebook下不能正常执行,难道api已经弃用了?
就我去查了以下发现, "RuntimeError: This event loop is already running"
,这个错误其实是因为asyncio不允许事件循环的嵌套。jupyter本身的web后台已经运行了一个事件循环,所以你不能用get_event_loop开启一个新循环了。
所以我导入了一个nest-asyncio包,是这个问题的一个解决方案,之后就可以用了。
async def http_get(domain):
reader, writer = await asyncio.open_connection(domain, 80)
writer.write(b'\r\n'.join([
b'GET / HTTP/1.1',
b'Host: %b' % domain.encode('latin-1'),
b'Connection: close',
b'', b''
]))
async for line in reader:
print('>>>', line)
writer.close()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(http_get('www.baidu.com'))
finally:
print('finish')
# loop.close()
async with 实现异步的上下文管理器,比如异步锁
async with lock
官方给的例子同样无法执行,太蠢了
async def coro(name, lock):
print('coro {}: waiting for lock'.format(name))
async with lock:
print('coro {}: holding the lock'.format(name))
await asyncio.sleep(1)
print('coro {}: releasing the lock'.format(name))
loop = asyncio.get_event_loop()
lock = asyncio.Lock()
coros = asyncio.gather(coro(1, lock), coro(2, lock))
try:
loop.run_until_complete(coros)
finally:
print('finally')
# loop.close()
002.矩阵乘法专用的运算符@
x = numpy.ones(3)
m = numpy.eye(3)
print('x:', x)
print('m:', m)
x@m
003.新的解包操作符,可以解构字典和列表
其中*
解构列表,**
解构字典
print(*[1], *[2], 3, *[4, 5])
def fn(a, b, c, d):
print(a, b, c, d)
fn(**{'a': 1, 'c': 3}, **{'b': 2, 'd': 4})
也可以解构元祖,集合set等
*range(4), 4
[*range(4), 4]
{*range(4), 4, *(5, 6, 7)}
{'x': 1, **{'y': 2}}
03.新的库模块
- typing 类型提示
- zipapp 改进Python ZIP应用程序支持.
2.python 3.6的新增特性
01.新的语法特性
001.格式化字符串 PEP498
就类似于js的模板字符串,括号内的变量会在运行时求值,并且用format()进行格式化
name = 'zhangsan'
f'he said his name is {name}'
# 格式化的宽度
width = 10
# 精度,结果长度是4位
precision = 4
# decmials是进行十进制浮点数运算的模块,基于人类习惯的浮点数模型,具有精确性,比如0.1+0.1+0.1-0.3=0
value = decimal.Decimal("12.34567")
f"result: {value:{width}.{precision}}"
002.变量注释的语法 PEP526
这个语法的使用需要一些工具支持,比如pycharm
primes: list[int] = []
captain: str # Note: no initial value!
class Starship:
stats: dict[str, int] = {}
primes.append('sda')
print(primes)
003.数字中可以使用下划线增强可读性 PEP515
print(1_000_000_000_000_00)
print(0x_FF_FF_FF_FF)
字符串格式化也支持下划线_
选项
'{:_}'.format(1000000)
'{:_x}'.format(0xFFFFFFFF)
004.异步生成器 PEP525
python3.5中存在不能再同一个函数体中使用await和yield的限制,在python3.6中已经解除,这样就可以实现异步生成器了。
async def ticker(delay, to):
"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
yield i
await asyncio.sleep(delay)
# tickers = ticker(50,100)
async for i in ticker(1, 3):
print(i)
005.异步推导 PEP530
增加了对列表,集合和字典推导式和生成表达式中对async for的支持
await表达式也在所有种类的推导式得到了支持
result = [i async for i in aiter() if i % 2]
result = [await fun() for fun in funcs if await condition()]
006.增加文件系统路径协议 PEP519
文件路径历来都是用bytes和str来表示
大家都认定路径是这两种类型之一,问题在于阻止了路径的对象表示的库pathlib和其他库之间的使用。
定义了os.PakLick的接口,并且内置的open和os的其他模块也更新了。
这个设计使得其他第三方代码以比较少的修改,兼容pathlike对象
>>> import pathlib
>>> with open(pathlib.Path("README")) as f:
... contents = f.read()
...
>>> import os.path
>>> os.path.splitext(pathlib.Path("some_file.txt"))
('some_file', '.txt')
>>> os.path.join("/a/b", pathlib.Path("c"))
'/a/b/c'
>>> import os
>>> os.fspath(pathlib.Path("some_file.txt"))
'some_file.txt'
007.windows系统中 文件编码和控制台编码更改为UTF-8
3.python 3.7的新增特性
01.新增的语法特性
001.延迟的标注求值(一看就知道是用不到的语法)
002.async和await成为保留关键字
02.数据模型的改进
dict 对象会保持插入时的顺序这个特性 正式宣布 成为 Python 语言官方规范的一部分。
03.标准库中的改进
time 模块现在提供 纳秒级精度函数 的支持。
4.python 3.8的新增特性
01. 新增语法特性
001.赋值表达式 PEP572
新增的语法 := 可在表达式内部为变量赋值。 它被昵称为“海象运算符”因为它很像是 海象的眼睛和长牙。
下面这个例子,避免了调用len两次的情况。
你在if里不进行赋值,直接用len(a),那么你到格式化字符串的时候还要再用一次len()计算,
这种情况我们可能会再if外先定义一个len的变量,但是这个新特性的写法显然会更简洁一些,提升可读性
a = '1234567890123'
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
类似的,下面这个正则表达式的例子
advertisement = r'80% discount '
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
print(discount)
此运算符也适用于配合 while 循环计算一个值来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
另一个值得介绍的用例出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:
[clean_name.title() for name in names
if (clean_name := normalize('NFC', name)) in allowed_names]
002.仅限位置形参 PEP570
函数参数用/
,指明某些函数形参必须使用仅限位置而非关键字参数的形式
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
以下均为合法的调用:
f(10, 20, 30, d=40, e=50, f=60)
但是,以下均为不合法的调用:
f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument
003.f字符串支持用=,自动记录表达式和调试文档
增加 =
说明符用于 f-string。 形式为 f'{expr=}'
的 f-字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。
user = 'eric_idle'
member_since = datetime.date(1975, 7, 31)
f'{user=} {member_since=}'
通常的 f-字符串格式说明符 允许更细致地控制所要显示的表达式结果:
delta = datetime.date.today() - member_since
f'{user=!s} {delta.days=:,d}'
=
说明符将输出整个表达式,以便详细演示计算过程:
theta = 30
print(f'{theta=} {cos(radians(theta))=:.3f}')
5.python 3.9新增特性
01. 新增的语法特性
001. dict增加合并运算符
合并 (|
) 与更新 (|=
) 运算符已被加入内置的 dict
类。 它们为现有的 dict.update
和 {**d1, **d2}
字典合并方法提供了补充。
x = {"key1": "value1 from x", "key2": "value2 from x"}
y = {"key2": "value2 from y", "key3": "value3 from y"}
print(x | y)
print(y | x)