写在前面

  • python2.6之后发布的python3.0(2008年),但是由于3.0并不能向下兼容2.0,所以10年的时候又发布了一个2.7版本,这个版本一直维护到了2020年,很多3.x后来的特性也被加入到了2.7的迭代中

3.10

更清楚的错误消息

异常信息中会给出关于语法错误的更精准信息

结构化模式匹配

提供各种嵌套语法匹配的match

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Point:
x: int
y: int

def location(point):
match point:
case Point(x=0, y=0):
print("Origin is the point's location.")
case Point(x=0, y=y):
print(f"Y={y} and the point is on the y-axis.")
case Point(x=x, y=0):
print(f"X={x} and the point is on the x-axis.")
case Point():
print("The point is located somewhere else on the plane.")
case _:
print("Not a point")

match points:
case []:
print("No points in the list.")
case [Point(0, 0)]:
print("The origin is the only point in the list.")
case [Point(x, y)]:
print(f"A single point {x}, {y} is in the list.")
case [Point(0, y1), Point(0, y2)]:
print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
case _:
print("Something else is found in the list.")

类型提示新特性

1
2
3
4
5
def square(number: int | float) -> int | float:
return number ** 2

isinstance(1, int | str)
True

3.9版本

新特性

标注语法中类型优化

不需要再从typing中导入对应的List类型命,直接使用list,==那么list和List的关系是什么呢==

1
2
3
def greet_all(names: list[str]) -> None:
for name in names:
print("Hello", name)

新的解析器

基于PEG的解析器替换LL,性能上大致相当,PEG特性更为灵活,3.10中旧的解析器将被移除,另外3.9版本为最后一个提供对Python2兼容的版本

multiprocessing

multiprocessing.SimpleQueue新增close()方法进行显式的关闭

ipaddress

不再支持IPv4地址字符串中存在前缀0,这个正好前两天碰到过,一般对IP地址的校验中认为前缀0是合法的

1
2
3
4
5
6
7
8
9
>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1')
IPv4Address('192.168.0.1')
>>> ipaddress.ip_address('192.168.0.01')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ipaddress.py", line 54, in ip_address
raise ValueError(f'{address!r} does not appear to be an IPv4 or IPv6 address')
ValueError: '192.168.0.01' does not appear to be an IPv4 or IPv6 address

3.8版本

‘:=’ 赋值表达式

表达式内部为变量赋值,以下代码避免len函数被调用两次,出了范围n的变量还在

1
2
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")

更多语言特性

  • continue语句可以在finally子句中使用

  • dict 和 dictview 可以使用 reversed() 按插入顺序反向迭代

  • 新增metadata模块,可以用于查询第三方库的元信息

    1
    2
    3
    4
    5
    6
    >>> from importlib.metadata import version, requires, files
    >>> version('requests')
    '2.22.0'
    >>> list(requires('requests'))
    ['chardet (<3.1.0,>=3.0.2)']

3.7版本

延迟的标注求值

对上个版本中变量标注语法的优化

breakpoint()

新增内置函数breakpoint,替换之前的pdb,经过测试此函数功能等效于以前的pdb,主要是pdb写起来有点复杂,做了一个简单的语法替换

import pdb
pdb.set_trace()

breakpoint()

纳秒级的时间函数

time.time()函数返回的浮点数时间精度跟不上现在计算机的时钟精度,所以进行了迭代

基于哈希的pyc文件

可以了解一下pyc文件的作用,和java字节码文件的异同

数据类dataclasses

没用过,看了说明没没懂使用场景 PEP557

1
2
3
4
5
6
7
8
9
@dataclass
class InventoryItem:
'''Class for keeping track of an item in inventory.'''
name: str
unit_price: float
quantity_on_hand: int = 0

def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand

SimpleQueue

queue新添加了一个SimpleQueue对象,之前在多进程通信里面用了它的Queue对象,可以去了解下新增对象的特性,另外FIFO是先进先出的缩写

3.6版本

格式化字符串

这个东西类似于format,很多人喜欢用这个语法糖

1
2
3
>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'

对变量类型的注释

通过这个语法,实现了类似于java的类型规范,但这里只是一个注释,也就是说有没有都无所谓,增加可读性

1
2
3
4
5
primes: List[int] = []
captain: str # 这个时候,此参数是没有被初始化的,直接使用会有一个类似于java未初始化的异常
class Starship:
stats: Dict[str, int] = {}

数字文字中的下划线

增加数据可读性的语法

1
2
3
4
>>> 1_000_000_000_000_000
1000000000000000
>>> 0x_FF_FF_FF_FF
4294967295

异步

1
2
3
4
5
6
7
8
9
10
# 异步生成器
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)

# 异步推导
result = [i async for i in aiter() if i % 2]
result = [await fun() for fun in funcs if await condition()]

3.5版本

使用async和await实现协程

‘*‘解包功能

*用于解包可迭代对象

**用于解包字典对象

对函数的注释

1
2
def greeting(name: str) -> str:
return 'Hello ' + name

os.scandir()

优化的目录迭代器

1
2
3
for entry in os.scandir(path):
if not entry.name.startswith('.') and entry.is_file():
print(entry.name)

heapq

python里面堆是什么
1
2
3
4
5
>>> import heapq
>>> a = ['9', '777', '55555']
>>> b = ['88', '6666']
>>> list(heapq.merge(a, b, key=len))
['9', '88', '777', '6666', '55555']

3.4版本

asyncio模块

协程相关的一个模块,协程这个东西应该研究一下

enum

枚举这个东西用得很少,或者对比和Java的枚举有什么区别

selectors

实现高层级高效率的IO复用,之前在socket编程的时候好像有用到,是对select模块的迭代

statistics

一个数学统计函数

tracemalloc

用于内存分配的分析

3.3版本

3.3版本的迭代内容基本都看不懂。。。

虚拟环境

也就是venv模块是在这个版本加入的

3.2版本

添加argparse

这是一个第三方模块,在这个版本被官方采纳,替换了原本的optparse模块

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser(description='此脚本运行需要输入必要参数')
parser.add_argument('--pid', '-p', help='产品ID,必要参数', required=False)
args = parser.parse_args()
prodcut_id = args.pid

基于字典的日志模块配置

之前是不支持这种配置格式的,添加之后方便了很多

1
2
3
4
5
6
logging_config = {
"version": 1,
"disable_existing_loggers": False
...
}
logging.config.dictConfig(logging_config)

添加模块concurrent.futures

这个是线程相关的,灵感来自java,哈哈

碎片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# format方法添加字符 # 功能
format(20, '#o')
'0o24'
format(12.34, '#5.0f')
' 12.'

# 静默启动功能,隐藏版本信息
➜ ~ python3 -q
>>>

# range对象添加count和index方法
>>> range(0, 100, 2).count(10)
1
>>> range(0, 100, 2).index(10)
5

# callable内置函数返场
>>> callable(max)
True

# 迭代工具新增累加函数
>>> from itertools import accumulate
>>> list(accumulate([8, 2, 50]))
[8, 10, 60]

# Counter类添加运算功能
>>> from collections import Counter
>>> tally = Counter(dogs=5, cats=3)
>>> tally -= Counter(dogs=2, cats=8)
>>> tally
Counter({'dogs': 3})

# datetime添加时区
from datetime import datetime, timezone

# 随机函数优化,使得整数可以更加均匀的分布
# sort函数使用的timsort算法进行优化

线程增加障碍点

这个可以详细的了解下
`from threading import Barrier, Thread`

3.1版本

3.x部分早期版本连Docker都配不出来,所以用python2进行对比

有序字典

1
2
3
4
5
6
7
8
9
10
>>> a = {}
>>> a['a'] = 1
>>> a['b'] = 2
>>> a['e'] = 5
>>> a['c'] = 3
>>> a
# python2
{'a': 1, 'c': 3, 'b': 2, 'e': 5}
# python3
{'a': 1, 'b': 2, 'e': 5, 'c': 3}

format()自动编号

这个特性我测试2.7里面已经有了,08年的时候发布了3.0,10年的时候发布的2.7

1
2
>>> 'Sir {} of {}'.format('Gallahad', 'Camelot')
'Sir Gallahad of Camelot'

碎片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# with语句允许多个上下文
>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile:
... for line in infile:
... if '<critical>' in line:
... outfile.write(line)

# round函数会返回整数,当传入参数为整数时
>>> round(1123, -2)
# 2
1100.0
# 3
1100

# 添加Counter
>>> from collections import Counter
>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue'])
Counter({'blue': 3, 'red': 2, 'green': 1})

性能优化

  • IO库使用C进行重写,有2-20倍速度提升
  • 元组和字典收集机制优化
  • UTF-8等解码速度提升2-4倍
  • 为JSON模块添加了一个C扩展,大幅改进性能
  • 整数现在存储在内部以 2**15 为基数或以基数存储 2**30(64位计算机上性能提升),以前固定为2**15 

3.0版本

print

print变成了一个方法

不再返回列表

这个变更主要是为了节省内存,不再直接生成一个列表对象,而是一个可迭代的对象,

而list是对象迭代器,是如何实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
>>> a = {'a': 1, 'b': 2, 'c': 3}
>>> b = a.keys()
>>> b
# python2
['a', 'c', 'b']
# python3
dict_keys(['a', 'b', 'c'])

>>> c = range(10)
>>> c
# python2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# python3
range(0, 10)

# map函数
>>> def square(x) :
... return x ** 2
...
>>> map(square, [1,2,3,4,5])
# python2
[1, 4, 9, 16, 25]
# python3
<map object at 0x105d682e0>

# zip函数
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> zipped = zip(a,b)
>>> zipped
# python2
[(1, 4), (2, 5), (3, 6)]
# python3
<zip object at 0x105d5dc40>
# 这里额外介绍下zip解压语法
>>> zip(*zipped)
[(1, 2, 3), (4, 5, 6)]

整数

将int这么一个极为基础的数据定义进行修改的原因是什么呢,像Java中会有一个整型缓冲池来进行优化,那么Python如何去优化这些极其常用的变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# python2
>>> type(1)
<type 'int'>
>>> type(1000000000000000000000000000000000)
<type 'long'>

# python3
>>> type(1)
<class 'int'>
>>> type(1000000000000000000000000000000000)
<class 'int'>

# python3中不再有maxint这么个东西
>>> import sys
>>> sys.maxint
9223372036854775807

小数

离奇
1
2
3
4
5
6
# python2
>>> 1/2
0
# python3
>>> 1/2
0.5

字符集

新语法

1
2
3
4
# 扩展的可迭代解包
(a, *rest, b) = range(5)

# 变量生效范围,列表推导的变量不再泄露到语句之外