Python各版本的差异总结

Python各版本的差异总结

文章目录

版本Python2Python3Python3.4Python3.5Python3.6Python3.7Python3.8Python3.9Python3.10Python3.11Python3.12Python3.13

版本

Python 是什么?

1989 年圣诞节期间,荷兰人 Guido van Rossum 在参与研发了 ABC 语言之后,开始研发一种更好的脚本语言,取名为 Python 。

取名为 Python 是为了致敬英国的喜剧团体 Monty Python 。与传统编程语言相比,Python 的优点为:简单易懂、通用性强 他成立了 Python 软件基金会,召集开源社区的志愿者,共同研发 Python ,主要工作为修复漏洞、增加新语法。

官方网站为 https://www.python.org/大概每年发布 Python 的一个新版本,每次增加两三种新语法。 Python 解释器是什么?

按照 Python 语法编写的代码,必须交给一种称为 Python interpreter 的软件来执行,中文名为 Python 解释器。一个电脑上,安装了什么版本的 Python 解释器,则能运行相同版本的 Python 代码,也能运行更老版本的 Python 代码。

例如:如果安装了 version = 3.6 的 Python 解释器,则通常可以运行 version ≤ 3.6 的 Python 代码,通常不能运行 version > 3.6 的 Python 代码。 一个电脑上,可以安装多个不同版本的 Python 解释器,从而支持多个版本的 Python 语法。

Python2

Python2.0 :于 2000 年发布 https://www.python.org/downloads/release/2.0/Python2.1 ~ Python2.6 略Python2.7 :于 2010 年发布 https://www.python.org/downloads/release/python-270/ ,这是 Python2 的最后一个子版本。

Python3

从 Python 2.x 到 Python 3.x 是一个大版本升级,有很多不向下兼容的差异。

因此, Python2.x 的解释器,通常不能运行 Python3.x 语法的代码。反之亦然,Python3.x 的解释器,通常不能运行 Python2.x 语法的代码。2020 年,Python 官方宣布停止维护 Python2.x ,不再修复漏洞。换句话说,这些旧版本的代码,都超过了保质期。

差异点Python2Python3输出方式用 print 关键字,例如 print "Hello"用 print() 函数,例如 print("Hello")输入方式用 raw_input() 函数用 input() 函数字符串的编码格式默认采用 ASCII默认采用 Unicode源文件的编码格式默认采用 ASCII ,因此使用中文时要在源文件开头加上一行 # -*- coding: utf-8 -*-默认采用 uft-8格式化字符串的方式用 % 符号,例如 "Hello %s" % ("World")用 str.format() 方法,例如 "Hello {}".format('World')………

Python3.0 :于 2008 年发布 https://www.python.org/download/releases/3.0/Python3.1 ~ Python3.3 略

Python3.4

于 2014 年发布:https://www.python.org/downloads/release/python-340/

采用 pip 作为 Python 包的默认安装方式。

增加标准库 pathlib ,用于按面向对象的方式操作文件路径。如下:

>>> from pathlib import Path

>>> p = Path('/root/test/1.py')

>>> p.name

'1.py'

>>> p.suffix

'.py'

>>> p.exists()

False

增加标准库 enum ,用于定义枚举类。如下:

>>> from enum import Enum

>>>

>>> class Test(Enum):

... a = 1

... b = 2

... c = 3

...

>>> Test.a

>>> Test['a'] # 可按名字索引

>>> list(Test) # 可迭代

[, , ]

增加标准库 asyncio ,用于实现异步 IO 。它取代了旧的 asyncore 库。

增加标准库 statistics ,提供了求平均值、中位数、方差等运算的函数。

增加标准库 tracemalloc ,用于跟踪内存分配的情况,方便调试。

Python3.5

于 2015 年发布:https://www.python.org/downloads/release/python-350/

扩展了迭代拆包运算符 * 、字典拆包运算符 ** 的语法。

可以在元组、列表、集合、字典表达式中使用:>>> *range(4)

SyntaxError: can't use starred expression here

>>> *range(4), 4

(0, 1, 2, 3, 4)

>>> [*range(4), 4]

[0, 1, 2, 3, 4]

>>> {'a': 1, **{'b': 2}}

{'a': 1, 'b': 2}

可以同时多次使用:>>> print(*[1], *[2], *{'c': 3})

1 2 c

>>> dict(**{'a': 1}, **{'b': 2})

{'a': 1, 'b': 2}

增加语法:使用 Python2 风格的百分号 % 来格式化字符串。

>>> '%a' % 3.14

'3.14'

>>> b'%a' % 3.14

b'3.14'

增加关键字 async、await ,用于定义协程:

async def read_db(db):

data = await db.fetch('SELECT ...')

增加语法:类型注释(type annotations)。

对于函数,可以用冒号 : 添加形参的注释,用 -> 添加返回值的注释。这些注释会存储在函数的 __annotations__ 属性中:>>> def fun1(a, b: "字符串或 None", c: int = 0) -> int:

... pass

...

>>> fun1.__annotations__

{'b': '字符串或 None', 'c': , 'return': }

对于变量,可以用冒号 : 添加注释:>>> x : int # 该语句可以执行,但并不会创建变量 x

>>> x

NameError: name 'x' is not defined

>>> x : int = 1 # 添加类型注释并赋值

>>> x

1

类型注释可以是任意可执行的表达式。例如:>>> x : int # 该注释为一个类型,不会强制类型检查,但可以供 IDE 等工具进行静态类型检查

>>> x : 'Hello' # 该注释为一个 str 值

>>> x : print('Hello') # 该注释为一个语句

Hello

增加标准库 typing ,定义了一些类型,常用于类型注释。

增加标准库 zipapp ,用于将 Python 脚本打包成可执行的归档文件,扩展名为 .pyz 。

Python3.6

于 2016 年发布:https://www.python.org/downloads/release/python-360/

dict 中的元素以前是按 key 顺序存储:

>>> {2:'', 1:''}

{1: '', 2: ''}

现在会按插入顺序存储:

>>> {2:'', 1:''}

{2: '', 1: ''}

增加语法:在数字中插入下划线作为分隔符,提高可读性。

>>> 1_000_111_000

1000111000

>>> '{:_}'.format(1000000) # 格式化字符串时也可输出下划线

'1_000_000'

增加语法:给字符串加上前缀 f 时,会将花括号 { } 中的内容当成 Python 代码执行。

这种语法称为 f-string ,常用于格式化字符串,比使用 str.format() 更方便。可以执行花括号中的代码,嵌入一个值到字符串中:>>> a = 1

>>> f'a={a}'

'a=1'

>>> f'a + 1 = {int(a) + 1}'

'a + 1 = 2'

>>> f'{{ a }}' # 如果原字符串包含花括号,则需要转义为两个花括号

'{ a }'

可以填充字符串到指定长度,实现 str.ljust()、str.rjust()、str.center() 的功能。>>> f'{a :5}' # 用空格填充字符串,至少输出 5 个字符的长度(如果原字符串超过该长度,则不会填充)

' 1'

>>> f'{a :05}' # 用数字 0 填充

'00001'

>>> f'{a :零>5}' # 用任意单个字符填充

'零零零零1'

>>> f'{a :>5}' # 右对齐(默认采用该对齐方式)

'1 '

>>> f'{a :<5}' # 左对齐

'1 '

>>> f'{a :^5}' # 中心对齐

' 1 '

完整语法示例:>>> content = 1

>>> fill = ' '

>>> align = '>'

>>> width = 5

>>> f'{content :{fill}{align}{width}}'

' 1'

可以截断字符串到指定长度:>>> f'{"helloworld" :.5}' # 截断字符串,最多输出 5 个字符的长度

'hello'

>>> f'{"helloworld" :10.5}' # 先截断,再填充

'hello '

可以转换数字的输出格式:>>> f'{10 :+d}' # 输出为 int 类型,并给非负数添加 + 前缀(否则默认只给负数添加 - 前缀)

'+10'

>>> f'{10000 :,d}' # 输出为 int 类型,并用 , 或 _ 作为千位分隔符

'10,000'

>>> f'{10 :f}' # 输出为 float 类型

'10.000000'

>>> f'{10 :e}' # 输出为科学计数法

'1.000000e+01'

可以转换数字的进制:>>> f'{10 :b}' # 输出为二进制

'1010'

>>> f'{10 :o}' # 输出为八进制

'12'

>>> f'{10 :x}' # 输出为小写的十六进制

'a'

>>> f'{10 :X}' # 输出为大写的十六进制

'A'

>>> f'{10 :#X}' # 加上 # ,则会添加这种进制类型对应的前缀

'0XA'

支持给类定义 __init_subclass__() 方法,用于初始化子类。如下:

>>> class Person:

... subclasses = []

... def __init_subclass__(cls, *args, **kwargs):

... super().__init_subclass__(*args, **kwargs)

... print('A new subclass is created:', cls)

... cls.subclasses.append(cls)

...

>>> class Man(Person): # 创建子类时,会自动执行父类的 __init_subclass__() 方法

... pass

...

A new subclass is created:

>>> Person.subclasses

[]

增加标准库 secrets ,用于生成安全的随机数。

原有的 random 模块生成的随机数可能被预测,安全性低,因此不适合用作密码、加密密钥。

Python3.7

于 2018 年发布:https://www.python.org/downloads/release/python-370/

Python3.8

于 2019 年发布:https://www.python.org/downloads/release/python-380/

增加语法:在 f-string 中可用 {var} 或 {var=} 的格式插入变量的值,方便调试。

>>> f'{a}'

NameError: name 'a' is not defined # 读取不存在的变量时会报错

>>> a = 1

>>> f'{a}'

'1'

>>> f'{a=}'

'a=1'

>>> f'DEBUG: {id(1)=}' # 也可插入函数的返回值,会自动转换成 str 类型

'DEBUG: id(1)=140298296357120'

增加语法:赋值表达式,用于给表达式中的变量赋值。

if a := input(): # 相当于先执行 a = input() 再执行 if a:

print(a)

>>> (a := 0) + 1

1

>>> a

0

增加语法:定义函数时,可以在形参列表中,插入一个正斜杆 / 、一个星号 *

原本,函数的每个形参,可以接收 positional argument 形式的实参,也可以接收 keyword argument 形式的实参。>>> def fun1(a, b=None):

... pass

...

>>> fun1(1, 2)

>>> fun1(a=1, b=2)

现在,可以在函数的形参列表中,插入一个正斜杆 / ,表示其左侧的所有形参,只允许接收 positional argument 形式的实参。>>> def fun1(a, b=None, /):

... pass

...

>>> fun1(1, 2)

>>> fun1(a=1, b=2)

TypeError: fun1() got some positional-only arguments passed as keyword arguments: 'a, b'

现在,可以在函数的形参列表中,插入一个星号 * ,表示其右侧的所有形参,只允许接收 keyword argument 形式的实参。>>> def fun1(*, a, b=None):

... pass

...

>>> fun1(1, 2)

TypeError: fun1() takes 0 positional arguments but 2 were given

>>> fun1(a=1, b=2)

更复杂的示例:>>> def fun1(a, / , b , *, c, **kwargs):

... pass

...

>>> fun1()

TypeError: fun1() missing 2 required positional arguments: 'a' and 'b'

>>> fun1(1, 2)

TypeError: fun1() missing 1 required keyword-only argument: 'c'

>>> fun1(1, 2, c=3)

支持在 finally 语句块中使用 continue 关键字。

multiprocessing 模块增加一个 SharedMemory 类,用于创建进程之间的共享内存。

Python3.9

于 2020 年发布:https://www.python.org/downloads/release/python-390/

dict 类增加合并运算符 |、更新运算符 |= 。

以前合并字典的方式主要有两种:{**d1, **d2}

d1.update(d2) # update() 方法会改变字典的内容

例如:>>> d1 = {1: 'A'}

>>> d2 = {2: 'B'}

>>> {**d1, **d2}

{1: 'A', 2: 'B'}

>>> d1.update(d2)

>>> d1

{1: 'A', 2: 'B'}

现在可以通过运算符合并字典:>>> d1 = {1: 'A'}

>>> d2 = {2: 'B'}

>>> d1 | d2 # 相当于 {**d1, **d2}

{1: 'A', 2: 'B'}

>>> d1 |= d2 # 相当于 d1.update(d2)

>>> d1

{1: 'A', 2: 'B'}

str 类增加两个方法 removeprefix()、removesuffix() 。如下:

>>> s = 'Hello'

>>> s.rstrip('lo') # 以前的 rstrip() 方法会删除右侧所有匹配的单个字符

'He'

>>> s.removesuffix('lo') # 现在的 removesuffix() 方法只会删除匹配的子字符串

'Hel'

其原理为:

def removeprefix(self: str, prefix: str, /) -> str:

if self.startswith(prefix):

return self[len(prefix):]

else:

return self[:]

支持将大部分内置类型的类名用作函数实参,便于声明注释。如下:

>>> T = type[int]

>>> T

type[int]

>>> list[str] == list[str]

True

>>> tuple[int, ...]

tuple[int, ...]

>>> def fun1(x: dict[str, list[int]]):

... pass

...

Python3.10

于 2021 年发布:https://www.python.org/downloads/release/python-3100/增加语法:match-case 模式匹配。增加语法:用 | 运算符连接多个类型,表示 Union 类型。>>> int | str # 相当于 typing.Union[int, str]

>>> isinstance(1, int|str) # 相当于 isinstance(1, (int, str)) 或 isinstance(1, typing.Union[int, str])

True

>>> issubclass(set, int|str)

False

调用 open() 函数时,允许传入参数 encoding='locale' ,等价于 encoding=None ,表示采用当前平台的默认编码格式。

Python3.11

于 2022 年发布:https://www.python.org/downloads/release/python-3110/

CPython 解释器优化了加载模块、调用函数等操作,使得 Python3.11 比 Python3.10 的启动速度、运行速度快了 10%~60% 。

增加了标准异常类型 BaseExceptionGroup、ExceptionGroup ,用于将多个异常打包为一组。异常组只能用语法 except* 捕捉。

例:>>> try:

... raise ExceptionGroup('异常组1', ([ # 创建异常组时,需要传入组名,和一组异常对象。支持嵌套异常组

... KeyError('invalid key'),

... TypeError('invalid type'),

... ValueError('invalid value'),

... ]))

... except* TypeError as e:

... print('A')

... except* (TypeError, ValueError) as e:

... print('B')

...

A

B

+ Exception Group Traceback (most recent call last):

| File "", line 2, in

| ExceptionGroup: 异常组1 (1 sub-exception)

+-+---------------- 1 ----------------

| KeyError: 'invalid key'

+------------------------------------

try 一个异常组时,会从上往下检查各个 except* 。

每个 except* 可以指定一个或多个异常,只要任一异常包含于异常组,则执行该 except* 子句。然后从异常组删除已捕捉的异常,继续匹配之后的 except* 。一个普通异常最多触发一个 except 子句,而一个异常组可能触发多个 except* 子句。如果 except* 没有捕捉异常组中的全部异常,则剩下的异常会被抛出。 打印 tracebacks 异常信息时,能更准确地指出引发异常的代码位置。

以前,Python 解释器在执行 Python 程序时,只知道当前执行的是哪条字节码。现在,用两个 uint8_t 数据类型记录每条字节码的起始偏移量、结束偏移量,从而能根据已执行的偏移量,判断目前执行到哪条字节码的哪个位置。例如编写一个 test.py 脚本:1 + 2/0 + 3

然后用 python 命令执行:[root@CentOS ~]# python test.py

Traceback (most recent call last):

File "/root/test.py", line 1, in

1 + 2/0 + 3

~^~

ZeroDivisionError: division by zero

倒数第二行信息是 Python3.11 才能打印的,指出这行代码的哪个位置引发了异常。缺点:

pyc 文件、内存中的字节码体积会增大 22% 。不过一般 Python 程序的字节码总共只有几十 MB ,影响小。用 Python 解释器交互式编程时,没有该功能。

Python3.12

于 2023 年发布:https://www.python.org/downloads/release/python-3120/

f-string 增加了几种语法。

花括号 { } 内可包含担任定界符的引号:>>> f'array={[1, 'hello']}'

"array=[1, 'hello']"

花括号 { } 内可嵌套多层 f-string :>>> f'{ f'{1+1}'= }'

" f'{1+1}'= '2'"

花括号 { } 内的 Python 代码可跨越多行,可添加注释:>>> f'{

... [1, # one

... 2] # two

... }'

'[1, 2]'

花括号 { } 内可以包含反斜杠 \ ,因此可以包含转义字符:>>> f'{'\n'}'

'\n'

简化定义泛型的语法。

旧的语法:from typing import TypeVar, Generic

T = TypeVar('T')

class Test(Generic[T]):

def __init__(self, value: T) -> None:

pass

新的语法:class Test[T]:

def __init__(self, value: T) -> T:

...

可用 type 关键字定义类型别名:

type Point = tuple[float, float]

在 Python 进程中创建子 Python 解释器时,允许每个 Python 解释器不再共享一个 GIL ,而是分别创建一个 GIL 。不过启用该功能需要调用 Cpython 的 API 。

Python3.13

于 2024 年发布:https://www.python.org/downloads/release/python-3130/

改进了交互式终端 shell ,更方便用户使用。

它基于 PyPy 解释器进行工作。提示符 >>>、... 和异常报错,会显示成彩色。支持多行编辑。如下,一条 Python 语句跨越多行时,可以按方向键,让光标上下移动,想修改哪行就修改哪行。>>> print(

... 1

... )

多行编辑时,即使包含空行,也能根据缩进,正确识别一个语句块的结束。>>> for i in range(3):

... print(i)

...

... print(i)

...

...

可按 F1 进入帮助模式。此时输入一个字符串,即可查询相关的帮助文档。按 q 可退出该模式。可按 F2 进入历史模式,用于查看用户输入的历史命令。此时不会显示 >>>、... ,方便鼠标拖动复制。按 q 可退出该模式。可按 F3 进入粘贴模式。 允许禁用 GIL 全局锁,使得多个 Python 线程可以被 CPU 同时执行,称为自由线程。

这是一个实验性功能,默认未开启。详见:https://py-free-threading.github.io/如果想启用该功能,用户需要自己从源代码构建 CPython 解释器,添加 --disable-gil 选项。可执行 python -c "import sys; print(sys._is_gil_enabled())" 来检查 GIL 是否启用。如果某个 Python 模块调用了 C/C++ 代码,则必须显示声明 GIL_NOT_USED ,否则 Python 解释器依然会启用 GIL 全局锁。 允许在 CPython 解释器中,启用 JIT 即时编译器,从而加快某些 Python 代码的执行速度。

这是一个实验性功能,默认未开启。如果想启用该功能,用户需要自己从源代码构建 CPython 解释器,添加 --enable-experimental-jit 选项。

相关推荐

pdf怎么删除空白页面?四种有效的方法分享
365bet在线手机版

pdf怎么删除空白页面?四种有效的方法分享

📅 08-02 👁️ 5024
orca杀人鲸
beat365老版本

orca杀人鲸

📅 07-07 👁️ 4142
《简社》诗词课,借对
亚洲365世界杯

《简社》诗词课,借对

📅 07-02 👁️ 8538
为什么lol玩家都认为亚索哪个皮肤最好看?
beat365老版本

为什么lol玩家都认为亚索哪个皮肤最好看?

📅 07-28 👁️ 6576
含维生素B的食物和水果蔬菜有哪些
亚洲365世界杯

含维生素B的食物和水果蔬菜有哪些

📅 07-14 👁️ 3438
Android 遊戲 人氣排行
beat365老版本

Android 遊戲 人氣排行

📅 06-29 👁️ 3560
今日头条1000粉丝难吗?多久可以达到?
beat365老版本

今日头条1000粉丝难吗?多久可以达到?

📅 08-06 👁️ 8393
什么是 B2B 电子商务?
beat365老版本

什么是 B2B 电子商务?

📅 07-14 👁️ 8732
《阴阳师》红蓝蛋怎么吃划算 一键育成暴食鬼最优解