在 Python 中,什么时候应该使用列表,什么时候应该使用元组?
有时您别无选择,例如,如果您有
"hello %s you are %s years old" % x
那么 x 必须是一个元组。
但是,如果我是设计 API 并选择数据类型的人,那么指导方针是什么?
元组本质上是固定大小的,而列表是动态的。
换句话说, atuple
是不可变的,而 alist
是可变的。
in
运算符检查元组中是否存在元素。元组比列表快。如果您要定义一组常量值,并且您要做的只是遍历它,请使用元组而不是列表。
如果您“写保护”不需要更改的数据,它会使您的代码更安全。使用元组而不是列表就像有一个隐含的断言声明该数据是恒定的,并且需要特殊的想法(和特定的函数)来覆盖它。
一些元组可以用作字典键(特别是包含不可变值的元组,如字符串、数字和其他元组)。列表永远不能用作字典键,因为列表不是不可变的。
资料来源:深入 Python 3
元组用于异类集合的文化很浓厚,类似于您struct
在 C 中使用 s 的内容,而列表用于同类集合,类似于您使用数组的内容。但是我从来没有将这与其他答案中提到的可变性问题完全吻合。可变性对它有影响(实际上你不能改变一个元组),而同质性并没有被强制执行,因此似乎是一个不那么有趣的区别。
我相信(而且我几乎不精通 Python)主要区别在于元组是不可变的(分配后不能就地更改)而列表是可变的(您可以追加、更改、减去等)。
所以,我倾向于让我的元组在分配后不应该改变的东西,我列出可以改变的东西。
它必须是可变的吗?使用列表。它必须是不可变的吗?使用元组。
否则,这是一个选择问题。
对于异构对象的集合(例如分解为名称、街道、城市、州和邮编的地址),我更喜欢使用元组。它们总是可以很容易地提升为命名元组。
同样,如果要迭代集合,我更喜欢列表。如果它只是一个容器来容纳多个对象,我更喜欢一个元组。
您需要决定的第一件事是数据结构是否需要可变。如前所述,列表是可变的,元组不是。这也意味着元组可以用于字典键,而列表不能。
根据我的经验,元组通常用于顺序和位置有意义且一致的情况。例如,在为选择你自己的冒险游戏创建数据结构时,我选择使用元组而不是列表,因为元组中的位置是有意义的。这是该数据结构的一个示例:
pages = {'foyer': {'text' : "some text",
'choices' : [('open the door', 'rainbow'),
('go left into the kitchen', 'bottomless pit'),
('stay put','foyer2')]},}
元组中的第一个位置是在用户玩游戏时显示给用户的选项,第二个位置是该选项进入的页面的键,这对于所有页面都是一致的。
元组也比列表更节省内存,尽管我不确定这种好处何时会变得明显。
还可以查看Think Python中关于列表和元组的章节。
但是,如果我是设计 API 并选择数据类型的人,那么指导方针是什么?
对于输入参数,最好接受最通用的接口来满足您的需求。它很少只是一个元组或列表——更常见的是它是序列、可切片甚至可迭代的。Python 的鸭子类型通常是免费的,除非你明确地检查输入类型。除非绝对不可避免,否则不要这样做。
对于您生成的数据(输出参数),只需返回对您最方便的数据,例如返回您保留的任何数据类型或您的辅助函数返回的任何数据。
要记住的一件事是避免返回属于您的状态的列表(或任何其他可变的),例如
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
与元组相比,列表的一个次要但显着的优势是列表往往更易于移植。标准工具不太可能支持元组。例如,JSON 没有元组类型。YAML 可以,但它的语法与它的列表语法相比是丑陋的,这非常好。
在这些情况下,您可能希望在内部使用元组,然后在导出过程中转换为列表。或者,您可能希望在任何地方都使用列表以保持一致性。