Python NamedTuple 示例 - 如何创建和使用 NamedTuples

399 阅读6分钟

在 Python 中,你可能会使用元组来初始化一个序列,这个序列在程序的其他地方不应该被修改。这是因为元组是不可改变的

然而,使用元组可能会降低你的代码的可读性,因为你无法描述元组中的每一项所代表的内容。这就是NamedTuples可以派上用场的地方。

NamedTuple提供了元组的不可更改性,同时也使你的代码易于理解和使用。

在本教程中,你将学习如何有效地创建和使用 NamedTuples。

Python 图元--快速回顾

在进入 NamedTuples 之前,让我们快速回顾一下 Python 图元。

图ples 是 Python 中强大的内置数据结构。它们与 Python 列表相似,因为它们可以容纳不同类型的项目,而且你可以对它们进行切分:

然而,图元与列表不同,它们是不可改变的。这意味着你不能修改现有的 tuple,而且试图这样做会产生错误。

假设你今天创建了下面这个元组。这个元组house ,包含五个描述房子的项目,即城市、国家、建造年份、面积(平方英尺)和房间数。这在下面的代码片断中显示:

house = ("Bangalore","India",2020,2018,4)
  • 这个house ,位于印度的班加罗尔市。
  • 它建于2020
  • 它有4 个房间,总面积为2018 平方英尺。

假设你的朋友读了这行代码,或者你一周后回来再读你的代码。鉴于你没有添加任何注释,说明元组中的值代表什么,这当然有一个可读性的问题。

例如,你最后可能不得不猜测它是一幢面积为2018平方英尺的房子,建于2020年,还是一幢面积为2020平方英尺的房子,建于2018年。🤔

你可能会建议用一个字典来代替--你可以指定不同的值代表什么,作为字典的 ,而实际的值作为字典的

继续看下一节,对 Python 字典进行快速回顾。

Python 字典 - 快速回顾

带着提高代码可读性的动机,让我们考虑改用 Python 字典。

字典是内置的数据结构,以键值对的形式存储数值。你可以进入一个字典,并使用键来访问它的值。

所以你可以把前面的元组改写成一个字典,如下所示:

house = {"city":"Bangalore","country":"India","year":2020,"area":2018,"num_rooms":4}

在上面的代码片断中:

  • "city","country","year","area""num_rooms" 是键。
  • 而元组中的值,"Bangalore","India",2020,2018, 和4 被用来作为与键对应的值。
  • 你可以使用键来访问这些值:house["city"] 来获取"Bangalore"house["area"] 来获取2018 ,以此类推。

正如你所看到的,使用 dictionary 可以提高代码的可读性。但是,与图元不同,你总是可以修改字典中的值:

你所需要做的就是把相应的键设置为不同的值。

在上面的例子中,你可以使用house["city"] = "Delhi" 来改变你的房子所处的城市。显然,这是不允许的,因为你不希望这些值在程序的其他地方被修改。

而且,如果你需要存储许多这样的房子的描述,你将不得不创建与房子数量一样多的字典,每次都要重复键的名称。这也会使你的代码变得重复,而且不那么有趣!

使用 Python 的 NamedTuples,你可以同时拥有图元的不变性和字典的可读性。

继续看下一节,了解NamedTuples。

Python NamedTuple 语法

要使用一个NamedTuple ,你需要从 Python 内置的集合模块中导入它,如图所示:

from collections import namedtuple

创建一个 NamedTuple 的一般语法如下:

namedtuple(<Name>,<[Names of Values]>)
  • <Name> 是一个占位符,表示你想叫你的 NamedTuple,而
  • <[Names of Values]> 是一个占位符,表示包含不同值或属性 名称的列表。

现在你已经熟悉了创建 NamedTuple 的语法,让我们在我们的house 例子的基础上,尝试将其创建为一个 NamedTuple。

Python NamedTuple 示例

如前所述,第一步是导入namedtuple

from collections import namedtuple

现在,你可以使用上一节中讨论的语法来创建一个 NamedTuple:

House = namedtuple("House",["city","country","year","area","num_rooms"])

在这个例子中:

  • 你选择调用NamedTupleHouse ,并且
  • 在一个列表中提到这些值的名称,"city","country","year","area""num_rooms"

✅ 而你已经创建了你的第一个NamedTuple -House

现在,你可以使用House 创建一个具有所需规格的房子house_1 ,如下所示:

house_1 = House("Bangalore","India",2020,2018,4)

你只需要传入你的<[Names of Values]> 中的名称或属性应该采取的实际值。

要创建另一个房子,比如说house_2 ,你所需要做的就是用它的值创建一个新的House :

house_2 = House("Chennai","India",2018,2050,3)

请注意,你可以使用House 作为模板来创建你想要的房子,而不必在每次创建新房子时都要输入属性名称。

如何使用dot 符号来访问NamedTuple的值

一旦你创建了NamedTuple对象house_1house_2 ,你可以使用dot 符号来访问它们的值。语法如下所示:

<namedtuple_object>.<value_name>
  • 这里,<namedtuple_object> 表示创建的NamedTuple对象。在这个例子中,house_1house_2
  • <value_name> 表示创建NamedTuple时使用的任何有效名称。在这个例子中, , , , 和 是 的有效选择。"city" "country" "year" "area" "num_rooms" <value_name>

这在下面的代码片断中有所说明:

print(house_1.city)
print(house_1.country)
print(house_1.year)
print(house_1.area)
print(house_1.num_rooms)

image-33

同样地,你可以使用house_2.city,house_2.country, 等等来访问NamedTuplehouse_2 所对应的值。

📋自己试试吧NamedTuple实例

在本节中,你将创建一个ProblemSet NamedTuple。

请随时在你选择的任何IDE中尝试这个例子。

ProblemSet NamedTuple应该有以下值:

  • num_questions: 一个整数,表示某个特定问题集的问题数量。
  • difficulty:一个字符串,表示该问题集的难度等级,和
  • topic:该问题集涵盖的主题,例如,"Arrays""Strings""Graphs" ,等等。

这个过程与我们之前创建House NamedTuple的例子非常相似。

1️⃣从collections 模块导入namedtuple :

from collections import namedtuple

2️⃣创建一个NamedTuple并将其称为ProblemSet :

ProblemSet = namedtuple("ProblemSet",["num_questions","difficulty","topic"])

3️⃣现在你已经创建了ProblemSet ,你可以使用ProblemSet 作为模板创建任何数量的问题集。

  • 这里,problem_set1 包含5个关于Strings 的简单问题:
problem_set1 = ProblemSet(5,"Easy","Strings")
  • problem_set2 包含了3个关于Bit Manipulation 的困难问题:
problem_set2 = ProblemSet(3,"Hard","Bit Manipulation")

4️⃣和前面的例子一样,你可以使用dot 符号来访问上面创建的两个问题集的值:

print(problem_set1.topic)

# Output
Strings
print(problem_set2.difficulty)

# Output
Hard

我希望你能够完成这个练习。🎉

结语

在本教程中,你已经学会了:

  • NamedTuples如何帮助你将图元和字典的优点结合起来。
  • 如何创建NamedTuples,以及
  • 如何使用dot 符号来访问 NamedTuples 的值。

如果你熟悉Python中的OOP,你可能会发现这与Python类的工作方式相似。一个带有属性的类作为一个模板,你可以从中创建尽可能多的对象或实例--每个对象都有自己的属性值。

然而,仅仅为了提高代码的可读性而创建一个类并定义所需的属性往往是多余的,而创建 NamedTuples 则要容易得多。

在下一个教程中见,在那之前,祝大家编码愉快!