• Python 3.8.0 正式版发布,新特性初体验


    北京时间 10 月 15 日,Python 官方发布了 3.8.0 正式版,该版本较 3.7 版本再次带来了多个非常实用的新特性。

    赋值表达式

    PEP 572: Assignment Expressions

    新增一种新语法形式::=,又称为“海象运算符”(为什么叫海象,看看这两个符号像不像颜表情),如果你用过 Go 语言,应该对这个语法非常熟悉。

    具体作用我们直接用实例来展示,比如在使用正则匹配时,以往版本中我们会如下写:

    import re
    
    pattern = re.compile('a')
    data = 'abc'
    match = pattern.search(data)
    if match is not None:
        print(match.group(0))
    

    而使用赋值表达式时,我们可以改写为:

    if (match := pattern.search(data)) is not None:
        print(match.group(0))
    

    在 if 语句中同时完成了求值、赋值变量、变量判断三步操作,再次简化了代码。

    下面是在列表表达式中的用法:

    filtered_data = [y for x in data if (y := func(x)) is not None]
    

    强制位置参数

    PEP 570: Python Positional-Only parameters

    新增一个函数形参标记:/,用来表示标记左侧的参数,都只接受位置参数,不能使用关键字参数形式。

    >>> def pow(x, y, z=None, /):
    ...     r = x ** y
    ...     return r if z is None else r%z
    ...
    >>> pow(5, 3)
    125
    >>> pow(x=5, y=3)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: pow() takes no keyword arguments
    

    这实际上是用纯 Python 代码来模拟现有 C 代码实现的内置函数中类似功能,比如内置函数 len('string') 传参是不能使用关键字参数的。

    Runtime 审计钩子

    PEP 578: Python Runtime Audit Hooks

    这让我们可以对某些事件和 API 添加一些钩子,用于在运行时监听事件相关的参数。

    比如这里监听 urllib 请求:

    >>> import sys
    >>> import urllib.request
    >>> def audit_hook(event, args):
    ...     if event in ['urllib.Request']:
    ...         print(f'{event=} {args=}')
    ...
    >>> sys.addaudithook(audit_hook)
    >>> urllib.request.urlopen('https://httpbin.org/get?a=1')
    event = 'urllib.Request' args =( 'https://httpbin.org/get?a=1' , None , {}, 'GET' )
    <http.client.HTTPResponse object at 0x108f09b38>
    

    官方内置了一些 API,具体可查看 PEP-578 规范文档,也可以自定义。

    f-strings 支持等号

    在 Python 3.6 版本中增加了 f-strings,可以使用 f 前缀更方便地格式化字符串,同时还能进行计算,比如:

    >>> x = 10
    >>> print(f'{x+1}')
    11
    

    在 3.8 中只需要增加一个 = 符号,即可拼接运算表达式与结果:

    >>> x = 10
    >>> print(f'{x+1=}')
    'x+1=11'
    

    这个特性官方指明了适用于 Debug。

    Asyncio 异步交互模式

    在之前版本的 Python 交互模式中(REPL),涉及到 Asyncio 异步函数,通常需要使用 asyncio.run(func()) 才能执行。

    而在 3.8 版本中,当使用 python -m asyncio 进入交互模式,则不再需要 asyncio.run

    >>> import asyncio
    >>> async def test():
    ...     await asyncio.sleep(1)
    ...     return 'test'
    ...
    >>> await test()
    'test'
    

    跨进程共享内存

    在 Python 多进程中,不同进程之间的通信是常见的问题,通常的方式是使用 multiprocessing.Queue 或者 multiprocessing.Pipe,在 3.8 版本中加入了 multiprocessing.shared_memory,利用专用于共享 Python 基础对象的内存区域,为进程通信提供一个新的选择。

    from multiprocessing import Process
    from multiprocessing import shared_memory
    
    share_nums = shared_memory.ShareableList(range(5))
    
    def work1(nums):
        for i in range(5):
            nums[i] += 10
        print('work1 nums = %s'% nums)
    
    def work2(nums):
        print('work2 nums = %s'% nums)
    
    if __name__ == '__main__':
        p1 = Process(target=work1, args=(share_nums, ))
        p1.start()
        p1.join()
        p2 = Process(target=work2, args=(share_nums, ))
        p2.start()
    
    # 输出结果:
    # work1 nums = [10, 11, 12, 13, 14]
    # work2 nums = [10, 11, 12, 13, 14]
    

    以上代码中 work1 与 work2 虽然运行在两个进程中,但都可以访问和修改同一个 ShareableList 对象。

    @cached_property

    熟悉 Python Web 开发的同学,对 werkzeug.utils.cached_propertydjango.utils.functional.cached_property 这两个装饰器一定非常熟悉,它们是内置 @property 装饰器的加强版,被装饰的实例方法不仅变成了属性调用,还会自动缓存方法的返回值。

    现在官方终于加入了自己的实现:

    >>> import time
    >>> from functools import cached_property
    >>> class Example:
    ...     @cached_property
    ...     def result(self):
    ...         time.sleep(1) # 模拟计算耗时
    ...         print('work 1 sec...')
    ...         return 10
    ...
    >>> e = Example()
    >>> e.result
    work 1 sec...
    10
    >>> e.result # 第二次调用直接使用缓存,不会耗时
    10
    

    其他改进

    • PEP 587: Python 初始化配置
    • PEP 590: Vectorcall,用于 CPython 的快速调用协议
    • finally: 中现在允许使用 continue
    • typed_ast 被合并回 CPython
    • pickle 现在默认使用协议4,提高了性能
    • LOAD_GLOBAL 速度加快了 40%
    • unittest 加入了异步支持
    • 在 Windows 上,默认 asyncio 事件循环现在是 ProactorEventLoop
    • 在 macOS 上,multiprocessing 启动方法默认使用 spawn

    更多具体变化,可查看 What’s New In Python 3.8


    本文属于原创内容,首发于微信公众号「面向人生编程」,如需转载请在公众号后台留言。

    关注后回复以下信息获取更多资源
    回复【资料】获取 Python / Java 等学习资源
    回复【插件】获取爬虫常用的 Chrome 插件
    回复【知乎】获取最新知乎模拟登录

  • 相关阅读:
    提高编程能力的7条建议(转载)
    1.2、Mybatis二级缓存测试
    1.1、Mybatis一级缓存测试
    外键约束
    【转】MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突
    【转】MyBatis学习总结(三)——优化MyBatis配置文件中的配置
    【转】The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?...
    【转】MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作
    【转】MyBatis学习总结(一)——MyBatis快速入门
    java面板
  • 原文地址:https://www.cnblogs.com/zkqiang/p/11690781.html
Copyright © 2020-2023  润新知