• Python3.9 新特性note


    Python语法官方文档

    背景

    偶然在网上看到一篇文章Python 疑难问题:[] 与 list() 哪个快?为什么快?快多少呢?提到python3.9为list()实现了更快的vectorcall协议,提升了使用list()创建列表的速度,恍然:啊!python都更新到3.9了呀。想起昨天看到的一篇文章,java都已经更新到14了。技术更新是如此之快,我的学习进度如此之慢!

    概述

    通过研究3.9新特性,了解下之前没有了解/使用的基础知识。

    特性一:字典合并与更新运算符

    旧:
    Python3字典合并的几种方法

    dict.update and {**d1,**d2}

    use:

    >>> d1 = {"user":"12311"}
    >>> d2 = {"name":"lalalala"}
    >>> d3 = {}
    >>> d3.update(d1)
    >>> print(d3)
    {'user': '12311'}
    >>> d3.update(d2)
    >>> print(d3)
    {'user': '12311', 'name': 'lalalala'}
    >>> d4 = dict(d1,**d2)
    >>> print(d4)
    {'user': '12311', 'name': 'lalalala'}
    
    

    新:

    合并(|) 更新(|=)

    use:

    >>> x = {"key1": "value1 from x", "key2": "value2 from x"}
    >>> y = {"key2": "value2 from y", "key3": "value3 from y"}
    >>> x | y
    {'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
    >>> y | x
    {'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'}
    
    

    特性二:新增用于移除前缀和后缀的字符串方法

    增加了 str.removeprefix(prefix)str.removesuffix(suffix) 用于方便地从字符串移除不需要的前缀或后缀。

    如何理解?看代码实现清晰明了

    def removeprefix(self: str, prefix: str, /) -> str:
        if self.startswith(prefix):
            return self[len(prefix):]
        else:
            return self[:]
    
    def removesuffix(self: str, suffix: str, /) -> str:
        # suffix='' should not call self[:-0].
        if suffix and self.endswith(suffix):
            return self[:-len(suffix)]
        else:
            return self[:]
    

    endwith(suffix[, start[, end]])可传入元组

    PEP 616 -- String methods to remove prefixes and suffixes中提到suffix参数可为元组

    suffix 为字符串:

    name = "123nanana"
    print(name.endwith("na"))
    >>>True
    

    suffix 为元组:

    >>> name3 = "fsdsfs"
    >>> if name3.endswith(("mixin","test")): print("123333")
    ... else: print("4444444444444")
    ...
    4444444444444
    

    特性三:标准多项集中的类型标注泛型

    了解这个特性之前,我们先了解以下type hint是什么?先看下这篇文章全面理解Python中的类型提示(Type Hints),python其实和php有点像,都是弱类型语言,不像java必须指定类型(变量,返回值,传入值等)

    type hint总结

    可添加的类型,参阅官方文档

    优点

    1. 易于理解代码,在调用函数时能更快知道输入和输出的数据类型
    2. 易于重构
    3. 易于使用库
    4. Type Linters尽早捕获错误,但是在更复杂的情况(如 嵌套函数)是检测不出来的
    5. 验证运行数据 可使用pydantic在业务逻辑运行之前自动检查,而不需要type assert
    from datetime import datetime
    from typing import List
    from pydantic import BaseModel, ValidationError
    
    class User(BaseModel):
        id: int
        name = 'John Doe'
        signup_ts: datetime = None
        friends: List[int] = []
    
    external_data = {'id': '123', 'signup_ts': '2017-06-01 12:22',
                     'friends': [1, 2, 3]}
    user = User(**external_data)
    
    try:
        User(signup_ts='broken', friends=[1, 2, 'not number'])
    except ValidationError as e:
        print(e.json())
    

    使用

    Python 3.5+版本
    通用标准:

    • 使用语句将信息附加到变量或函数参数中。
    • ->运算符用于将信息附加到函数/方法的返回值中。

    Python 3.6示例

    from typing import List
    
    class A(object):
        def __init__() -> None:
             self.elements : List[int] = []
    
       def add(element: int) -> None:
             self.elements.append(element)
    
    1. 强制你导入所有类型依赖项,即使它们根本不在运行时使用。
    2. 在类型提示中,会使用到复合类型,例如List[int]。而为了构造这些复杂类型,解释器在首次加载此文件时需要执行一些操作。

    这两个问题在Python 3.7中得到解决!

    from __future__ import annotations---加入该语句,将不再构造复合类型

    Python2.7+版本

    由于作者没用过2.7版本,本文不作赘述。

    1. 可用类型注释
    2. 类型库可作为pypi包使用

    缺点: 长度限制;可能会与typelint产生冲突(通过引入typed-ast parser解决)

    重点来啦

    到这里,我们已经了解了type hint ,而 标准多项集中的类型标注泛型指的是什么呢?

    我们不需要再导入typing的大多数类型(List,Dict),内置多项集类型如list和dict作为通用类型

    tuple # typing.Tuple
    list # typing.List
    dict # typing.Dict
    set # typing.Set
    frozenset # typing.FrozenSet
    type # typing.Type
    collections.deque
    collections.defaultdict
    collections.OrderedDict
    collections.Counter
    collections.ChainMap
    collections.abc.Awaitable
    collections.abc.Coroutine
    collections.abc.AsyncIterable
    collections.abc.AsyncIterator
    collections.abc.AsyncGenerator
    collections.abc.Iterable
    collections.abc.Iterator
    collections.abc.Generator
    collections.abc.Reversible
    collections.abc.Container
    collections.abc.Collection
    collections.abc.Callable
    collections.abc.Set # typing.AbstractSet
    collections.abc.MutableSet
    collections.abc.Mapping
    collections.abc.MutableMapping
    collections.abc.Sequence
    collections.abc.MutableSequence
    collections.abc.ByteString
    collections.abc.MappingView
    collections.abc.KeysView
    collections.abc.ItemsView
    collections.abc.ValuesView
    contextlib.AbstractContextManager # typing.ContextManager
    contextlib.AbstractAsyncContextManager # typing.AsyncContextManager
    re.Pattern # typing.Pattern, typing.re.Pattern
    re.Match # typing.Match, typing.re.Match
    

    题外话: ...这个是啥?

    原文: Python 为什么会有个奇怪的“...”对象?
    使用场景:

    1. 扩展切片语法(?不懂,没有示例)
    2. 代替pass
    3. 在type hint中的用法

    代表不定长的参数,如Tuple[int,...]表示一个元组,元素是int类型但数量不限
    代表不确定的变量类型,如下例子

    from typing import TypeVar, Generic
    
    T = TypeVar('T')
    
    def fun_1(x: T) -> T: ...  # T here
    def fun_2(x: T) -> T: ...  # and here could be different
    
    fun_1(1)                   # This is OK, T is inferred to be int
    fun_2('a')                 # This is also OK, now T is str
    
    1. 无限循环
      对于列表和字典这样的容器,如果其内部元素是可变对象的话,则存储的是对可变对象的引用。那么,当其内部元素又引用容器自身时,就会递归地出现无限循环引用。
    >>> mydict = {"name":"test"}
    >>> mydict["name"] = mydict
    >>> mydict
    {'name': {...}}
    >>> mylist = [1,2,3,]
    >>> mylist[0] = mylist
    >>> mylist
    [[...], 2, 3]
    

    特性四: 新的解析器

    旧的:LL(1)

    新的:基于PEG的新解析器

    在 Python 3.10 中,旧解析器将被移除,依赖于它的所有功能也将被移除(主要是 parser 模块,它早已被弃用)。 只有 在 Python 3.9 中,你可以使用命令行开关 (-X oldparser) 或环境变量 (PYTHONOLDPARSER=1) 切换回 LL(1) 解析器。

    特性五: 新增zoneinfo模块

    在了解这个模块之前,我们有必要深入了解一下datetime---基本的日期和时间类型;而datetime和time之间的关联与区别可以理解为datetime基于time进行了封装;

    特点: 引入IANA时区数据库

    简介: zoneinfo 模块添加了 zoneinfo.ZoneInfo,这是一个基于系统时区数据的实体 datetime.tzinfo 实现。

    特性六: 新增 graphlib模块

    用于操作图表结构

    其他特性

    ast 模块新增 ast.unparse()

    ast.unparse() 用于反解析ast.AST对象并产生响应的代码字符串;
    ast常用于静态代码检查,代码生成等,如pylint就会用到;

    asyncio模块 - 多进程线程

    添加了coroutinu shutdown_default_executor(),可为等待 ThreadPoolExecutor 结束关闭的默认执行器安排关闭日程操作;

    添加了asyncio.PidfdChildWatcher ,linux专属子监视器实现;

    添加了 coroutine asyncio.to_thread()。 它主要被用于在单独线程中运行 IO 密集型函数以避免阻塞事件循环,实质上就相当于是 run_in_executor() 的高层级版本

    random 模块

    添加了random.Random.randbytes方法生成随机字节串;

    结语

    大概浏览了3.9的变更,发现有些东西根本没接触过(可能未来会有接触吧...)也不知道作为测试工程师 会应用在什么场景,因此不作记录。

  • 相关阅读:
    docker 删除所有的 docker ps -a 记录
    使用ES6的Promise完美解决回调地狱
    linux查看历史命令history
    linux命令补全 忘记命令只记得开头
    linux更改shell
    java信号量PV操作 解决生产者-消费者问题
    eclipse代码自动提示功能设置
    linux下mysql修改数据库账户root密码
    IntelliJ Idea12 破解码与中文乱码配置
    linux usermod修改用户所在组方法
  • 原文地址:https://www.cnblogs.com/Tester_Dolores/p/13926241.html
Copyright © 2020-2023  润新知