1.3 从2.7到3.7,Python的新特性
目前,Python有两个版本,一个是2.x版,另一个是3.x版,这两个版本是不兼容的。3.x版不考虑对2.x版代码的向后兼容,当前来看,3.x版会越来越普及。在写本书时,Python的最新版本是3.7.0,本书中的示例和讲解的内容都是基于这个版本进行的。建议读者安装3.6.2以上的版本,这样学习本教程中的内容才会更加容易。
在3.x中,一些语法、内建函数和对象的行为有所调整。大部分Python库都同时支持Python 2.7.x和3.x版本,所以无论选择哪个版本都可以。为了在使用Python时避免某些版本中常见的陷阱,或者需要移植某个Python项目时,依然有必要了解一下Python两个常见版本之间的主要区别。
2.x和3.x版本之间的主要区别如下:
1. 使用__future__模块
Python 3.x引入了一些与Python 2.x不兼容的关键字和特性。在Python 2.x中,可以通过内置的__future__模块导入这些新内容。如果你希望在Python 2.x环境下写的代码也可以在Python 3.x中运行,那么建议使用__future__模块。
2. print函数
虽然print语法是Python 3中一个很小的改动,而且应该已经广为人知,但是依然值得提一下:Python 2中的print语句被Python 3中的print()函数取代,这意味着在Python 3中必须用括号将需要输出的对象括起来。在Python 2中使用额外的括号也可以,但是如果要在Python 3中以Python 2的形式不带括号调用print函数,就会触发SyntaxError(语法错误)。
3. 整数除法
由于人们常常会忽视Python 3在整数除法上的改动(写错了也不会触发SyntaxError),因此在移植代码或在Python 2中执行Python 3的代码时需要特别注意这个改动。
4. Unicode
Python 2有基于ASCII的str()类型,可通过单独的unicode()函数转成unicode类型,但没有byte类型。在Python 3中有了Unicode(UTF-8)字符串和两个字节类(bytes和bytearrays)。
5. xrange
在Python 2.x中,经常会用xrange()创建一个可迭代对象,通常出现在“for循环”或“列表/集合/字典推导式”中。在Python 3中,range()的实现方式与xrange()函数相同,所以不存在专用的xrange()(在Python 3中使用xrange()会触发NameError)。
6. 触发异常
Python 2支持新旧两种异常触发语法,而Python 3只支持带括号的语法(不然会触发SyntaxError)。
7. 处理异常
Python 3中的异常处理发生了一点变化。在Python 3中必须使用as关键字,Python 2中不需要。
8. next()函数和.next()方法
由于会经常用到next()函数(.next()方法),因此要提到另一个语法改动(实现方面也做了改动):在Python 2中,函数形式和方法形式都可以使用;在Python 3中,只能使用next()函数(试图调用.next()方法会触发AttributeError)。
9. for循环变量与全局命名空间泄漏
在Python 3.x中,for循环中的变量不再会泄漏到全局命名空间中了。
10. 比较无序类型
Python 3中另一个优秀的改动是,如果我们试图比较无序类型,就会触发一个TypeError。
11. 使用input()解析输入内容
Python 3改进了input()函数,这样该函数就会总是将用户的输入存储为str对象。在Python 2中,为了避免读取非字符串类型会发生的一些危险行为,不得不使用raw_input()代替input()。
12. 返回可迭代对象,而不是列表
某些函数和方法在Python 3中返回的是可迭代对象,而不像在Python 2中返回列表。对象只遍历一次会节省很多内存,如果通过生成器多次迭代这些对象,效率就不高了。此时如果需要列表对象,可以通过Python 3的list()函数简单地将可迭代对象转成列表。
Python 3.7相对于Python 3.5,有如下新特性:
(1)重新实现了字典(dict)类型,以便能像PyPy的字典类型一样使用更紧凑的表达方式。与Python 3.5相比,这使字典的内存用量减少了20%~25%。该特性在3.6版本实现。
(2)为asyncio模块增加了新功能,如显著的可用性、性能优化以及大量的错误修复。从Python 3.6开始,asyncio模块不再是临时的,其API也进入了稳定状态。
(3)引入了一种新的字符串:_f-strings_,或者格式化字符串。格式化字符串带'f'前缀,类似于str.format()接受的格式化字符串。它们包含由花括号括起来的替换字段,替换字段是表达式,它们会在运行时计算,然后使用format()协议进行格式化。
(4)在Python 3.6版本后,可在同一个函数体中使用await和yield。
(5)添加了对async for在list、set、dict解析式以及generator表达式中的使用支持。
(6)支持nanosecond的时间函数,方便对nanosecond的操作,提供了6个新增的函数,分别为:clock_gettime_ns()、clock_settime_ns()、monotonic_ns()、perf_counter_ns()、process_time_ns()和time_ns()。
(7)在新版本中添加了@dataclass装饰器,利用该装饰器可以减少数据类型定义的代码行数。