由于很快就会
停止对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)
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)
Pathlib模块(3.4+)
格式字符串是一种很棒的技术,但是已经创建了专用工具来处理某些行,例如文件路径,这大大简化了它们的操作。 Python 3具有
pathlib模块,这是使用文件路径的便捷抽象。 如果您不确定此模块对解决问题的有用性,请查看
此材料。
from pathlib import Path root = Path('post_sub_folder') print(root)
类型注释(3.5+)
哪种更好-静态或动态输入? 也许几乎每个程序员对这个难题都有自己的答案。 我留给读者看他们如何精确地代表他们的程序。 但是,我认为每个人至少知道Python 3支持
类型注释是一件好事。
def sentence_has_animal(sentence: str) -> bool: return "animal" in sentence sentence_has_animal("Donald had a farm without animals")
接送(3.4+)
多亏了
Enum
类,Python 3支持一种用于
枚举的简单机制。 枚举便于存储常量列表。 否则,常量将随机分散在代码中。
from enum import Enum, auto class Monster(Enum): ZOMBIE = auto() WARRIOR = auto() BEAR = auto() print(Monster.ZOMBIE)
从Python 3
文档中 ,您可以发现枚举是与唯一,不变值绑定的符号名(成员)的集合。 可以比较单个列表的成员的身份。 枚举可以绕过。
for monster in Monster: print(monster)
内置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')
现在,我们使用
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')
打开可迭代对象的包装(3.0+)
解压缩可迭代对象时,可以使用名称前带有星号的变量。 所有不适合其他变量的内容都将进入此类变量。 因此,在以下示例中,由
range(5)
命令形成的列表的第一个和最后一个值落入变量
head
和
tail
。 第一个值和最后一个值之间的所有内容都将进入
body
变量。
head, *body, tail = range(5) print(head, body, tail)
数据类(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()
这是相同的,但是已经使用
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()
不含__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的哪些功能添加到列表中?
