在Python中,什么时候应该使用列表,什么时候使用元组?
有时候你没有选择,比如你有选择
"hello %s you are %s years old" % x
那么x一定是一个元组。
但如果我是设计API并选择数据类型的人,那么指导原则是什么?
在Python中,什么时候应该使用列表,什么时候使用元组?
有时候你没有选择,比如你有选择
"hello %s you are %s years old" % x
那么x一定是一个元组。
但如果我是设计API并选择数据类型的人,那么指导原则是什么?
当前回答
您需要决定的第一件事是数据结构是否需要可变。如前所述,列表是可变的,元组不是。这也意味着元组可以用于字典键,而列表不能。
根据我的经验,元组通常用于顺序和位置有意义且一致的地方。例如,在为“选择你自己的冒险游戏”创建数据结构时,我选择使用元组而不是列表,因为元组中的位置是有意义的。下面是该数据结构的一个例子:
pages = {'foyer': {'text' : "some text",
'choices' : [('open the door', 'rainbow'),
('go left into the kitchen', 'bottomless pit'),
('stay put','foyer2')]},}
元组中的第一个位置是在用户玩游戏时显示给他们的选择,第二个位置是选择指向的页面的键,这对所有页面都是一致的。
元组的内存效率也比列表高,不过我不确定这种好处什么时候会显现出来。
也可以查看Think Python中关于列表和元组的章节。
其他回答
有一种很强的文化,即元组用于异构集合,类似于在C中使用结构体的目的,而列表用于同构集合,类似于使用数组的目的。但我从来没有把这个问题与其他答案中提到的可变性问题联系起来。可变性很重要(您实际上不能更改元组),而同质性并不是强制的,因此似乎不是一个有趣得多的区别。
但如果我是设计API并选择数据类型的人,那么指导原则是什么?
对于输入参数,最好接受最通用的接口来满足您的需要。它很少只是一个元组或列表——更多的是序列,可切片甚至可迭代。Python的duck类型通常是免费的,除非显式检查输入类型。除非不可避免,否则不要那样做。
对于你生成的数据(输出参数),只返回对你来说最方便的,例如,返回你保留的任何数据类型或你的helper函数返回的任何数据类型。
要记住的一件事是避免返回作为你状态一部分的列表(或任何其他可变的)。
class ThingsKeeper
def __init__(self):
self.__things = []
def things(self):
return self.__things #outside objects can now modify your state
def safer(self):
return self.__things[:] #it's copy-on-write, shouldn't hurt performance
它必须是可变的吗?使用列表。 它必须是不可变的吗?使用元组。
否则,这是一个选择的问题。
对于异构对象的集合(如地址分解为名称、街道、城市、州和zip),我更喜欢使用元组。它们总是可以很容易地提升为命名元组。
同样地,如果集合将被迭代,我更喜欢使用列表。如果它只是一个容器,以容纳多个对象为一个,我更喜欢元组。
列表相对于元组的一个次要但值得注意的优点是列表往往更易于移植。标准工具不太可能支持元组。例如,JSON没有元组类型。YAML是这样的,但是它的语法与它的列表语法相比是丑陋的,而列表语法是相当不错的。
在这些情况下,您可能希望在内部使用元组,然后将其转换为列表作为导出过程的一部分。另外,为了保持一致性,您可能希望在任何地方都使用列表。
您需要决定的第一件事是数据结构是否需要可变。如前所述,列表是可变的,元组不是。这也意味着元组可以用于字典键,而列表不能。
根据我的经验,元组通常用于顺序和位置有意义且一致的地方。例如,在为“选择你自己的冒险游戏”创建数据结构时,我选择使用元组而不是列表,因为元组中的位置是有意义的。下面是该数据结构的一个例子:
pages = {'foyer': {'text' : "some text",
'choices' : [('open the door', 'rainbow'),
('go left into the kitchen', 'bottomless pit'),
('stay put','foyer2')]},}
元组中的第一个位置是在用户玩游戏时显示给他们的选择,第二个位置是选择指向的页面的键,这对所有页面都是一致的。
元组的内存效率也比列表高,不过我不确定这种好处什么时候会显现出来。
也可以查看Think Python中关于列表和元组的章节。