zoukankan      html  css  js  c++  java
  • Python在2020的新增功能:第1部分

    自从很久以前改用了python3,语言层面的特征变化就相对较小了,然而对于每一个版本,Python都会添加一些新函数。
    随着Python3.8于2019年10月发布,我发现自己使用的是这种语言的一些特性,关于Python每个版本新增的特性,有如下

    3.5-类型注解
    3.6-异步
    3.7-数据类
    3.8-海象算子
    3.9-字典联合运算符和泛型类型提示
    以上所有的这些,我都会在代码库中使用到。
    oapbox演讲:如果你仍在工作或项目中使用旧版本的Python,不要害怕升级!你的旧代码仍然可以工作,而且你将从Python的新特性中获益!
    免责声明:如果你仍然使用Python2.7,在这种情况下,我知道你很有可能不会升级。
    下面我将回顾(快速)我最喜欢的一些特性,我希望你可以在你的代码中使用。
    它们是:类型注解、数据类、字典联合运算符、海象算子。
    在这第一部分,我主要介绍:类型注解,海象算子。
    Python 3.5
    从Python 3开始,Typing就成为了一个特性。因为我们是开发人员,而不是历史学家,所以Typing将提供类型注解和类型提示。
    Python不需要为变量指定类型,这是我如此热爱这门语言的部分原因。清晰易读的语法,可以用20多种不同的方法编写一个解决方案,但仍能得到相同的结果。
    但后来随着应用程序的增长,或者回头看看你几个月或几年没碰过的代码,或者去阅读别人写的代码。
    这种情况下,你就会意识到变量不指定类型对你来说没有啥好处。
    Typing 可以帮助你解决这个问题,这也是TypeScript如此流行的原因。

    from typing import List

    def print_cats(cats: List[str]) -> None:
    for cat in cats:
    print(f"{cat} has a name with {len(cat)} letters.")

    class Cat(object):
    def init(self, name: str, age: int, **attrs):
    self.cattributes = {
    "name": name,
    "age": age,
    **attrs
    }

    cats = "this still works w/o type annotation!"
    cats: List[str] = ["Meowie", "Fluffy", "Deathspawn"]

    不是字符串列表,Python不会检查

    cats2: List[str] = [Cat("Meowie", 2), Cat("Deathspawn", 8)]

    print_cats(cats)
    print_cats(cats2) # 失败
    这将返回:

    Meowie has a name with 6 letters.
    Fluffy has a name with 6 letters.
    Deathspawn has a name with 10 letters.

    ...
    TypeError: object of type 'Cat' has no len()
    类型注解在这里并没有起到任何作用,那为什么要使用它们呢?因为在创建变量cats并用List[str]时,很明显分配的数据应该与该结构相匹配,因此对于具有复杂类型的可维护代码来说,这将变得更加有用。

    from typing import List

    class Cat(object):
    def init(self, name: str, age: int, **attrs):
    self.cattributes = {
    "name": name,
    "age": age,
    **attrs
    }

    创建类型变量

    Cats: type = List[Cat]

    def print_cats(cats: Cats) -> None:
    for cat in cats:
    name: str = cat.cattributes.get("name")
    print(f"{name} has a name with {len(name)} letters.")

    cats = [Cat("Meowie", 2), Cat("Deathspawn", 8)]

    print_cats(cats)
    输出:

    Meowie has a name with 6 letters.
    Deathspawn has a name with 10 letters.
    在函数/方法定义中键入参数称为类型暗示,而且类型甚至不必是Python数据类型或来自typing模块。例如最后一行提示性字符串是完全合法的:

    import pandas as pd

    cols = ["name", "age", "gender"]
    data = [["Meowie", 2, "female"],
    ["Fluffy", 5, "male"],
    ["Deathspawn", 8, "rather not say"]]
    df: pd.DataFrame = pd.DataFrame()
    df: "name (string), age (integer), gender (string)" =
    pd.DataFrame(data, columns=cols)
    在数据处理管道中,如果有很多复杂类型的变量,那这样的操作可能会很有用,因为你可能搞不清楚读取的数据是什么结构,你会试图把它们弄清楚。在IDE上鼠标悬停在变量上会有类型提示的信息,而不是一个简单的pandas.DataFrame提示。
    额外的好处是:在python4中,前向引用可以开箱即用,这意味着你可以对尚未定义的类型进行注解。我们现在仍然可以利用这种优势,在文件顶部编写from future import annotations,然后执行以下操作:

    from future import annotations

    class Food:
    """
    Food是合法的,即使没有类别的定义。
    """
    def init(self, ingred_1: Food, ingred_2: Food) -> None:
    self.ingred_1 = ingred_1
    self.ingred_2 = ingred_2
    原生类型注解-3.9
    内置泛型类型是3.9中的一个特性,我们不需要从typing中导入以向泛型数据类型添加参数。从3.7版开始,使用from futures import annotations就可以使用这种方法,但这是因为它阻止了在运行时计算类型引用。
    这个功能让我很兴奋。在3.8中我将typing导入每个模块,或者导入在公共模块中。
    示例(信贷:PEP 585):

    l = liststr
    []

    list is list[str]
    False

    list == list[str]
    False

    list[str] == list[str]
    True

    list[str] == list[int]
    False

    isinstance([1, 2, 3], list[str])
    TypeError: isinstance() arg 2 cannot be a parameterized generic

    issubclass(list, list[str])
    TypeError: issubclass() arg 2 cannot be a parameterized generic

    isinstance(list[str], types.GenericAlias)
    True
    def find(haystack: dict[str, list[int]]) -> int:
    ...
    海象算子-3.8
    海象有眼睛:,然后有牙齿=。
    :=是Python3.8中新增的赋值表达式。

    complicated = {
    "data": {
    "list": [1,2,3],
    "other": "stuff"
    }
    }

    if (nums := complicated.get('data').get('list')):
    print(nums)
    结果:

    1
    2
    3
    如果没有海象,会有更多的代码行。

    ...

    nums = complicated.get('data').get('list')
    if nums:
    print(nums)
    由于控制流语句在编程中经常使用,使用海象算子可以简化代码。
    来自PEP 572:
    这样的命名表达式的值与合并表达式的值的结果是相同的,但附加的作用是目标被赋给了该值
    换言之,用一个表达式表达了两个语句。
    在我复制/粘贴PEP指南的同时,这里还有一些规范中的示例,我认为它们是很好的示例。迫不及待地想尝试一下海象算子来理解列表。

    #处理匹配正则表达式

    if (match := pattern.search(data)) is not None:
    # 匹配后...

    一个更直观易写的循环

    while chunk := file.read(8192):
    process(chunk)

    重用一个计算成本很高的值

    [y := f(x), y2, y3]

    在理解filter语句及其输出之间共享子表达式

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

  • 相关阅读:
    迭代器接口
    实现Promise
    学学springboot吧!!!!
    了解一下连接池!!!!
    Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules ???报错!!!
    requset和response的区别????
    百度也太神奇了吧
    这个svn啊,真的是有点看不懂
    BootStrap???确实厉害
    突然看到原来除了jar包还有war包啊?????
  • 原文地址:https://www.cnblogs.com/wang1018-kuiying/p/14233540.html
Copyright © 2011-2022 走看看