Python 3.10有哪些有用的新特性或者功能?
这是一篇补作业的文章,本文以一个资深Python开发的角度分析这个版本添加了那些有用的新功能和特性。
新的上下文管理器语法
其实就是可以使用with把多个上下文管理器(Context Manager)用括号括起来。在之前的版本,有时候我们想要在一个with里面放多个上下文,放在一行很长,一个常见的方式是使用反斜杠,可以把open对齐:
In : with open('input', mode='rb') as input, \
...: open('output', mode='rb') as output:
...: ...
...:
但是这样写,会让pep8、black等代码检查工具报错: 它们都认为不应该使用反斜杠显式续行。
现在可以给这些上下文管理器加个括号就完美了(代码洁癖者的福音):
In : with (
...: open('input', mode='rb') as input,
...: open('output', mode='rb') as output
...: ):
...: ...
...:
更好的错误提示
在官方中列举了一些之前版本中不够明显友好的错误信息例子(延伸阅读链接1)。,这个版本集中的处理了它们。本文就列出2个我感受最明显的,其他的不挨个展示了。
对于初学者,第一次写hello world时就可能这么写:
In : print("Hello, World!)
File "<ipython-input-7-bc0808c61f64>", line 1
print("Hello, World!)
^
SyntaxError: EOL while scanning string literal
而新的版本提示如下:
In : print("Hello, World!)
Input In []
print("Hello, World!)
^
SyntaxError: unterminated string literal (detected at line 1)
同样是SyntaxError,是不是新版本的提示更容易理解呢?
再看判断时误用了单个等号(正确语法是双等号==):
In : if b = 1: pass
File "<ipython-input-8-e4cfea4b3624>", line 1
if b = 1: pass
^
SyntaxError: invalid syntax
而新的版本:
In : if b = 1: pass
Input In []
if b = 1: pass
^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
不仅提示错误类型,还给了提示。
当然大家也没必要具体了解每个错误提示的改进,反正知道从Python 3.10开始错误提示更友好了就可以了。
zip 函数的参数
相信每个工作经验多的Python开发都经历过这个坑:
In : list(zip(['a', 'b', 'c'], [1, 2]))
Out: [('a', 1), ('b', 2)]
当然参数内的元素长度不同时,长度长的那部分会被忽略,在没有任何提示的情况下。其实本来它的文档中提到了:
This continues until the shortest argument is exhausted.
但是对于大部分开发者来说没人真的能注意这个文档说明,这个问题是很隐性的,需要开发者了解zip的问题。而新的版本在参数内元素长度不同时,使用strict=True会报错:
In : list(zip(['a', 'b', 'c'], [1, 2], strict=True))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In , in <cell line: 1>()
----> 1 list(zip(['a', 'b', 'c'], [1, 2], strict=True))
ValueError: zip() argument 2 is shorter than argument 1
模块新增特性
这小节介绍一些模块新增的特性,分析其用途和用法。
itertools.pairwise
itertools.pairwise是把一个可迭代对象中的元素按照顺序两个挨着的元素放一组的形式返回迭代器。
在之前的版本中可以使用more-itertools这个包,现在已经把它加入到标准库了。
这么用:
In : list(pairwise([1, 2, 3, 4, 5]))
Out: [(1, 2), (2, 3), (3, 4), (4, 5)]
In : list(pairwise('ABCDE'))
Out: [('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'E')]
如果还不理解可以看函数文档:
Return an iterator of overlapping pairs taken from the input iterator.
s -> (s0,s1), (s1,s2), (s2, s3), … contextlib.aclosing
在之前已经一个标准的contextlib.closing装饰器,而contextlib.aclosing其实就是async的版本罢了。
我们先了解下contextlib.closing的作用。如官方介绍,它其实的作用是实现下面的逻辑:
f = <module>.open(<arguments>)
try:
<block>
finally:
f.close()
使用Python读写文件一个好的习惯是操作完成后应该要关闭文件句柄,内置的open配合with是一个很好地实践:
In : with open('new.txt', 'w') as f:
...: f.write('A\n')
...:
它的原理是在块代码执行完成后,会通过调用ff.__exit__自动关闭文件句柄:
In : ff = open('new.txt', 'w')
In : ff.closed
Out: False
In : ff.__exit__() # with就会调用它
In : ff.closed
Out: True
但是这里要注意,不是所有的open方法都原生支持with(或者说提供__exit__以及__enter__这个方法),当然还有其他类型的操作也需要被确保关闭(即便发生了异常)。
事实上,一般标准库或者知名项目都会支持with语法,但是当自己写或者公司项目里就可能没有了, 例如我这样定义一个类:
In : class Database:
...: def close(self):
...: print('Closed')
...:
In : with Database() as d:
...: ...
...:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-23-f0ea085f7488> in <module>
----> 1 with Database() as d:
2 ...
3
AttributeError: __enter__
这样就抛错了。所以可以使用contextlib.closing包装一下:
In : import contextlib
In : with contextlib.closing(Database()) as d:
...: ...
...:
Closed
而contextlib.aclosing其实就是asyncio的版本:
from contextlib import aclosing
async with aclosing(my_generator()) as values:
async for value in values:
if value == 42:
break
contextlib.AsyncContextDecorator
在Python3.2时加入了contextlib.ContextDecorator,它是contextlib.contextmanager的基础,如类名的表达,它的作用让上下文管理器能用作装饰器。举个例子就能理解了,下面是一个最基本的、不带参数的上下文管理器:
class mycontext:
def __enter__(self):
print('Starting')
return self
def __exit__(self, *exc):
print('Finishing')
return False
所以可以使用with语法这么用:
In : with mycontext():
...: print('Inner')
...:
Starting
Inner
Finishing
如果你想把这个上下文的管理改成装饰器怎么办呢? 只需要让mycontext继承contextlib.ContextDecorator这个基类就可以了:
In : class mycontext(contextlib.ContextDecorator): # 注意这里继承
...: def __enter__(self):
...: print('Starting')
...: return self
...:
...: def __exit__(self, *exc):
...: print('Finishing')
...: return False
...:
In : @mycontext()
...: def p():
...: print('Inner')
...:
In : p()
Starting
Inner
Finishing
是不是很方便?所以contextlib.AsyncContextDecorator其实就是asyncio的版本:
class mycontext(AsyncContextDecorator):
async def __aenter__(self):
print('Starting')
return self
async def __aexit__(self, *exc):
print('Finishing')
return False
关于Python技术储备
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
点此免费领取:CSDN大礼包:《python学习路线&全套学习资料》免费分享
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
四、Python视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、Python练习题
检查学习结果。
七、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】