zoukankan      html  css  js  c++  java
  • 你不得不了解的Python3.x新特性

      从 3.0 到 3.8,Python 3 已经更新了一波又一波,但似乎我们用起来和 2.7 没有太大区别?以前该怎么写 2.7 的代码现在就怎么写,只不过少数表达方式变了而已。在这篇文章中,作者介绍了 3.0 以来真正 Amazing 的新函数与新方法,也许这些方法我们都不太熟,但它们确实在实践中非常重要。

    一、格式化字符串f-string

    在任何的编程语言中,不使用字符串都是寸步难行的。而为了保持思路清晰,你会希望有一种结构化的方法来处理字符串。Python中格式化字符串目前有四种方法,大家可以参见我的这篇博客:https://www.cnblogs.com/zhangyafei/p/9837602.html

    大多数使用 Python 的人会偏向于使用「format」方法。

    # format
    user = "Jane Doe"
    action = "buy"
    log_message = 'User {} has logged in and did an action {}.'.format(
      user,
      action
    )
    print(log_message)
    # User Jane Doe has logged in and did an action buy.
    

    除了「format」,Python 3 还提供了一种通过「f-string」进行字符串插入的灵活方法。使用「f-string」编写的与上面功能相同的代码是这样的:

    # f-string
    user = "Jane Doe"
    action = "buy"
    log_message = f'User {user} has logged in and did an action {action}.'
    print(log_message)
    # User Jane Doe has logged in and did an action buy.
    

    相比于常见的字符串格式符 %s 或 format 方法,f-strings 直接在占位符中插入变量显得更加方便,也更好理解。

    二、路径管理库 Pathlib(最低 Python 版本为 3.4)  

      f-string 非常强大,但是有些像文件路径这样的字符串有他们自己的库,这些库使得对它们的操作更加容易。Python 3 提供了一种处理文件路径的抽象库「pathlib」。如果你不知道为什么应该使用 pathlib,请参阅下面这篇 Trey Hunner 编写的炒鸡棒的博文:「https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/」

    from pathlib import Path
    
    root = Path('post_sub_folder')
    print(root)
    # post_sub_folder
    
    path = root / 'happy_user'
    
    # Make the path absolute
    print(path.resolve())
    # /home/weenkus/Workspace/Projects/DataWhatNow-Codes/how_your_python3_should_look_like/post_sub_folder/happy_user
    

    如上所示,我们可以直接对路径的字符串进行「/」操作,并在绝对与相对地址间做转换。

    三、类型提示 Type hinting(最低 Python 版本为 3.5)

      静态和动态类型是软件工程中一个热门的话题,几乎每个人 对此有自己的看法。读者应该自己决定何时应该编写何种类型,因此你至少需要知道 Python 3 是支持类型提示的。

    def sentence_has_animal(sentence: str) -> bool:
      return "animal" in sentence
    
    sentence_has_animal("Donald had a farm without animals")
    # True

    四、枚举(最低 Python 版本为 3.4)

    Python 3 支持通过「Enum」类编写枚举的简单方法。枚举是一种封装常量列表的便捷方法,因此这些列表不会在结构性不强的情况下随机分布在代码中。

    from enum import Enum, auto
    
    class Monster(Enum):
        ZOMBIE = auto()
        WARRIOR = auto()
        BEAR = auto()
    
    print(Monster.ZOMBIE)
    # Monster.ZOMBIE
    

    枚举是符号名称(成员)的集合,这些符号名称与唯一的常量值绑定在一起。在枚举中,可以通过标识对成员进行比较操作,枚举本身也可以被遍历。

    参考:https://docs.python.org/3/library/enum.html

    for monster in Monster:
        print(monster)
    
    # Monster.ZOMBIE
    # Monster.WARRIOR
    # Monster.BEAR

    五、原生 LRU 缓存(最低 Python 版本为 3.2)

      目前,几乎所有层面上的软件和硬件中都需要缓存。Python 3 将 LRU(最近最少使用算法)缓存作为一个名为「lru_cache」的装饰器,使得对缓存的使用非常简单。

      下面是一个简单的斐波那契函数,我们知道使用缓存将有助于该函数的计算,因为它会通过递归多次执行相同的工作。

     

    import time
    
    def fib(number: int) -> int:
        if number == 0: return 0
        if number == 1: return 1
    
        return fib(number-1) + fib(number-2)
    
    start = time.time()
    fib(40)
    print(f'Duration: {time.time() - start}s')
    # Duration: 59.59635329246521s

    现在,我们可以使用「lru_cache」来优化它(这种优化技术被称为「memoization」)。通过这种优化,我们将执行时间从几十秒降低到了几纳秒。

    from functools import lru_cache
    
    @lru_cache(maxsize=512)
    def fib_memoization(number: int) -> int:
        if number == 0: return 0
        if number == 1: return 1
    
        return fib_memoization(number-1) + fib_memoization(number-2)
    
    start = time.time()
    fib_memoization(40)
    print(f'Duration: {time.time() - start}s')
    # Duration: 0.0s

    六、扩展的可迭代对象解包(最低 Python 版本为 3.0)

    对于这个特性,代码就说明了一切。

    参考:https://www.python.org/dev/peps/pep-3132/

    head, *body, tail = range(5)
    print(head, body, tail)
    # 0 [1, 2, 3] 4
    
    py, filename, *cmds = "python3.7 script.py -n 5 -l 15".split()
    print(py)
    print(filename)
    print(cmds)
    # python3.7
    # script.py
    # ['-n', '5', '-l', '15']
    
    first, _, third, *_ = range(10)
    print(first, third)
    # 0 2

    七、Data class 装饰器(最低 Python 版本为 3.7)

    Python 3 引入了「data class」,它们没有太多的限制,可以用来减少对样板代码的使用,因为装饰器会自动生成诸如「__init__()」和「__repr()__」这样的特殊方法。在官方的文档中,它们被描述为「带有缺省值的可变命名元组」。

    class Armor:
    
        def __init__(self, armor: float, description: str, level: int = 1):
            self.armor = armor
            self.level = level
            self.description = description
    
        def power(self) -> float:
            return self.armor * self.level
    
    armor = Armor(5.2, "Common armor.", 2)
    armor.power()
    # 10.4
    
    print(armor)
    # <__main__.Armor object at 0x7fc4800e2cf8>
    

    使用「Data class」实现相同的 Armor 类。

    from dataclasses import dataclass
    
    
    @dataclass
    class Armor:
        armor: float
        description: str
        level: int = 1
    
        def power(self) -> float:
            return self.armor * self.level
    
    
    armor = Armor(5.2, "Common armor.", 2)
    result = armor.power()
    
    print(armor)
    print(result)
    
    # Armor(armor=5.2, description='Common armor.', level=2)
    # 10.4
    
  • 相关阅读:
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark RDD(Resilient Distributed Datasets)论文
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    【机器学习实战】第10章 K-Means(K-均值)聚类算法
    [译]flexbox全揭秘
  • 原文地址:https://www.cnblogs.com/zhangyafei/p/10905849.html
Copyright © 2011-2022 走看看