Python 3 特性 (与 Python2 比较)

Python 3 新特性

原文链接: https://www.asmeurer.com/python3-presentation/python3-presentation.pdf

包括:
1. 更加灵活的拆包特性 (unpack)
2. 函数输入参数的关键词强制参数 (输入参数的 * 符号)
3. 异常链 (抛出异常时更加完整的异常栈信息)
4. 更加细化的 OSError 类型 (https://www.python.org/dev/peps/pep-3151/)
5. 大多数基础方法都替换成了生成器 (rangezipmapdict.values …)
6. 不同基础类型禁止相互比较
7. yield from 语法的支持
8. 异步 i/o - asyncio 库
9. 标准库的修改与加强
10. unicode 和 bytes (逃离字符编码的噩梦吧)
11. __matmul__@ (新的运算符号)

特性 1: 更加灵活的拆包特性 (unpack)

python 2 中可以如此拆包

>>> a, b = range(2)
>>> a
0
>>> b
1

python3 中可以这样

>>> a, b, *rest = range(10)
>>> a
0
>>> b
1
>>> rest
[2, 3, 4, 5, 6, 7, 8, 9]
>>> a, *rest, b = range(10)
>>> *rest, b = range(10)

利用这个特性获取一个文件的首位两行

>>> with open("using_python_to_profit") as f:
...     first, *_, last = f.readlines()
>>> first
'Step 1: Use Python 3\n'
>>> last
'Step 10: Profit!\n'

特性 2: 关键词强制参数

>>> def f(a, b, *, option=True):  # 这样的调用方式,option 在传参时必须明确写出
...    pass

在这种情况下,下面的调用是会报错的

>>> f(1, 2, False)  # 会报错

正确的调用方式

>>> f(1, 2, option=False)

这种写法在 python3 的官方库中很常见

这样的好处之一是避免了在未来的版本中,替换了函数输入参数的前后顺序,使用这个函数的代码就会发生异常

另一个好处是,有事参数含义并非很明确,如果调用时不写成 参数名=参数值 的形式,代码的阅读性会变得很差

特性 3: 异常链

Python3 对于异常链保留了更加完整的异常栈信息

一种常见的场景是,代码捕捉到某个异常,进行一些处理后再抛出定义好的异常,例如

def mycopy(source, dest):
    try:
        shutil.copy2(source, dest)
    except OSError:
        raise NotImplementedError("automatic sudo injection")

假设 shutil.copy2 出错了,python2 的异常栈信息只会打印

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in mycopy
NotImplementedError: automatic sudo injection

而 python3 会显示

Traceback (most recent call last):
File "<stdin>", line 3, in mycopy
File "/Users/aaronmeurer/anaconda3/lib/python3.3/shutil.py", line 243, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)
File "/Users/aaronmeurer/anaconda3/lib/python3.3/shutil.py", line 109, in copyfile
    with open(src, 'rb') as fsrc:
PermissionError: [Errno 13] Permission denied: 'noway'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in mycopy
NotImplementedError: automatic sudo injection

同时支持下面的语法格式 (还没怎么见过实际使用)

raise exception from e

特性 4: OSError 类型

  • https://www.python.org/dev/peps/pep-3151/

特性 5: 大多数基础方法都替换成了生成器

  • rangezipmapdict.values
  • 避免了由于代码编写不当造成的大量内存使用

特性 6: 不同基础类型禁止相互比较

Python3 不在提供诸如 'one' > 2 这种语法的支持,这样的写法在大多数情况下都是意义不明的,而且 Python3 禁止这种语法可以使得潜在的 bug 更少

里一个例子是下面的代码,在 Python3 也会报错

>>> sorted(['1', 2, '3'])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'

特性 7: yield from 语法的支持

yield from 语法的支持,是 python 正规语法对协程(coroutine)的支持,在这之前都是依赖第三方包来实现这一概念 (greenlet 等),对协程概念不了解的可以搜索相关帖子

特性 8: 异步 i/o - asyncio 库

这绝对是 Python 最难理解的概念之一了,官方示例如下

import asyncio

async def main():
    print('Hello ...')
    await asyncio.sleep(1)
    print('... World!')

# Python 3.7+
asyncio.run(main())

如果一个程序是完全从头通过 asyncio 来实现的,使用起来还 “相对” 简单;但如果想在已有代码的某一部分上使用这一技术,至少以我的技术水平觉得是非常别扭的。

特性 9: 标准库的修改与加强

比如 Type hint 特性原来依赖第三方包,现在已经是官方支持;说实话这一部分我了解的比较少,一般是需要的时候去查看官方文档

特性 10: unicode 和 bytes

Python 2 中,str 类型的行为更像是 bytes,而 unicode 类型来表示非 ascii 码的字符串数据。Python 3 中,str 就是以 unicode 编码的字符串,而 bytes 就是单纯的 bytes 类型

特性 11: __matmul__@

Python 3 添加了新的运算符号 @,只要一个类实现了 __matmul__ 方法即可。

例如 numpy 的点乘,Python2 的写法是

>>> a = np.array([[1, 0], [0, 1]])
>>> b = np.array([[4, 1], [2, 2]])
>>> np.dot(a, b)
array([[4, 1],
       [2, 2]])

而 Python3 可以写成

>>> a = np.array([[1, 0], [0, 1]])
>>> b = np.array([[4, 1], [2, 2]])
>>> a @ b
array([[4, 1],
       [2, 2]])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值