值得使用的Python 3功能

由于很快就会停止对Python 2的支持,许多程序员开始从第二个版本的Python切换到第三个版本。 该文章的作者(我们将其翻译发表)指出,他看到的大部分Python 3代码看起来都像是用Python 2编写的带方括号的代码。据他说,他本人也犯了类似的错误 。 在这里,他列举了一些仅适用于使用Python 3的人可用的出色功能的示例。他希望这些功能将使那些了解它们的人生活变得更加轻松。



本文中的所有示例均使用Python 3.7编写。 每个功能的描述均包含有关使用该功能所必需的最低Python版本的信息。

格式字符串(3.6+)


没有字符串,很难用任何编程语言编写有用的东西。 但是为了有效地处理字符串,开发人员需要方便的工具。 此类工具使您可以在复杂的结构下运行而不会失去内心的平静。 大多数Python开发人员都使用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. 

Python 3和format方法一起支持格式字符串( f-strings ,f-strings)。 它们是用于执行各种字符串操作的灵活工具。 这是使用格式字符串重写的上一示例:

 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. 

Pathlib模块(3.4+)


格式字符串是一种很棒的技术,但是已经创建了专用工具来处理某些行,例如文件路径,这大大简化了它们的操作。 Python 3具有pathlib模块,这是使用文件路径的便捷抽象。 如果您不确定此模块对解决问题的有用性,请查看材料。

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

类型注释(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 

接送(3.4+)


多亏了Enum类,Python 3支持一种用于枚举的简单机制。 枚举便于存储常量列表。 否则,常量将随机分散在代码中。

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

从Python 3 文档中 ,您可以发现枚举是与唯一,不变值绑定的符号名(成员)的集合。 可以比较单个列表的成员的身份。 枚举可以绕过。

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

内置LRU缓存(3.2+)


如今,几乎所有的软件和硬件系统都使用了缓存机制。 Python 3使用lru_cache装饰器大大简化了缓存,该装饰器实现了LRU缓存算法( 最近最少使用 )。

下面是一个计算斐波纳契数的函数。 递归调用期间多次强制执行此功能以执行相同的操作。 结果,事实证明可以通过缓存来提高其性能。

 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: 30.684099674224854s 

现在,我们使用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: 6.866455078125e-05s 

打开可迭代对象的包装(3.0+)


压缩可迭代对象时,可以使用名称前带有星号的变量。 所有不适合其他变量的内容都将进入此类变量。 因此,在以下示例中,由range(5)命令形成的列表的第一个和最后一个值落入变量headtail 。 第一个值和最后一个值之间的所有内容都将进入body变量。

 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 

数据类(3.7+)


Python 3引入了数据类 。 它们给程序员很大的自由度。 它们可用于减少样板代码的数量。 事实是, dataclass修饰器会自动生成特殊方法,例如__init__()__repr__() 。 在相应提案的正式文本中它们被描述为“具有默认值的可变命名元组”。 这是不使用dataclass装饰器创建类的示例:

 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> 

这是相同的,但是已经使用dataclass编写了:

 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) armor.power() # 10.4 print(armor) # Armor(armor=5.2, description='Common armor.', level=2) 

不含__init__.py文件的软件包文件夹支持(3.3+)


构造Python代码的一种方法是使用程序包 (程序包放置在包含__init__.py文件的文件夹中)。 这是官方文档中的示例:

 sound/                                 __init__.py                 sound     formats/                                   __init__.py             wavread.py             wavwrite.py             aiffread.py             aiffwrite.py             auread.py             auwrite.py             ...     effects/                                  __init__.py             echo.py             surround.py             reverse.py             ...     filters/                                 __init__.py             equalizer.py             vocoder.py             karaoke.py             ... 

使用Python 2时,示例中提到的每个文件夹都应具有__init__.py文件。 由于有了此文件,该文件夹被视为Python软件包。 在Python 3中,随着隐式命名空间包功能的出现,不再需要此类文件夹。

 sound/                                 __init__.py                 sound     formats/                                   wavread.py             wavwrite.py             aiffread.py             aiffwrite.py             auread.py             auwrite.py             ...     effects/                                  echo.py             surround.py             reverse.py             ...     filters/                                 equalizer.py             vocoder.py             karaoke.py             ... 

应该指出的是,实际上,并不是所有事情都那么简单。 即,根据官方规范,常规软件包仍需要__init__.py文件。 如果从文件夹中将其删除,则该程序包将变成所谓的名称空间程序包 ,对其施加其他限制。

总结


本文并未涵盖Python 3的所有有趣功能,但我们希望您在这里找到有用的东西。 可以在存储库中找到示例代码。

亲爱的读者们! 您将在此处将Python 3的哪些功能添加到列表中?

Source: https://habr.com/ru/post/zh-CN452564/


All Articles