元组功能多样且实用,但在生产代码中我却不怎么常见到它们。以下是一些原因:
为元组编写类型提示可能不够清晰明确 假设我们有一个执行某些操作并返回元组的函数。
def do_stuff() -> tuple[str, int, int]:
"""
一些文档字符串
"""
fruit_name: str = get_fruit_name()
price: int = get_price()
quantity: int = get_quantity()
return fruit_name, price, quantity
^注意,当我们尝试编写类型提示时,我们使用了 tuple[str, int, int]
。
这仅仅意味着我们的函数旨在返回一个长度为3的元组——第一个元素是字符串,另外两个是整数。
这不是很简单明了吗?
这样做存在的问题
乍一看,我们知道返回的是 tuple[str, int, int]
,但乍一看,我们并不知道这个 tuple[str, int, int]
应该表示什么。
我们需要阅读代码才能推断出它表示的是 (fruit_name, price, quantity)
。
在大型代码库中,由于代码众多,要推断这类内容可能会花费相当长的时间。
我的同事们(我也认同)似乎更倾向的做法
typing.NamedTuple
命名元组就是一种我们可以通过两种方式访问的元组。我们可以像普通元组那样通过索引来访问它:
from typing import NamedTuple
class FruitInfo(NamedTuple):
fruit: str
price: int
quantity: int
info = FruitInfo(fruit="apple", price=5, quantity=100)
print(info) # FruitInfo(fruit='apple', price=5, quantity=100)
print(info[0]) # apple
print(info[1]) # 5
print(info[2]) # 100
或者我们可以像访问对象那样来访问它。
from typing import NamedTuple
class FruitInfo(NamedTuple):
fruit: str
price: int
quantity: int
info = FruitInfo(fruit="apple", price=5, quantity=100)
print(info) # FruitInfo(fruit='apple', price=5, quantity=100)
print(info.fruit) # apple
print(info.price) # 5
print(info.quantity) # 100
我们更倾向于像访问对象的属性那样来访问这些值。
这主要是因为这样做能让我们的代码更加清晰明确。
在类型提示中使用命名元组 使用元组时:
def do_stuff() -> tuple[str, int, int]:
"""
一些文档字符串
"""
fruit: str = get_fruit_name()
price: int = get_price()
quantity: int = get_quantity()
return fruit, price, quantity
使用命名元组时:
from typing import NamedTuple
class FruitInfo(NamedTuple):
fruit: str
price: int
quantity: int
def do_stuff() -> FruitInfo:
"""
一些文档字符串
"""
fruit: str = get_fruit_name()
price: int = get_price()
quantity: int = get_quotity()
return FruitInfo(
fruit=fruit,
price=price,
quantity=quantity
)
从可读性角度看命名元组的优势
乍一看,我们就能确定返回的是 FruitInfo
。
乍一看,我们就知道 FruitInfo
包含3个属性——fruit
、price
和 quantity
。
乍一看,我们还知道 fruit
应该是一个字符串,而 price
和 quantity
应该是整数。
而且我们仍然可以像对待普通元组那样对待命名元组。
info = FruitInfo(fruit="apple", price=5, quantity=100)
f, p, q = info
print(f, p, q) # apple 5 100
** 定义一个命名元组可能要多写几行代码,但它能让我们的代码可读性更强、更加清晰。