【问题标题】:What is the difference between lists and tuples in Python?Python中的列表和元组有什么区别?
【发布时间】:2010-07-28 22:13:58
【问题描述】:

哪个更有效率?每个的典型用途是什么?

【问题讨论】:

标签: python list tuples


【解决方案1】:

列表是可变序列,有很多方法(包括可变的和非可变的),最常用作通用容器(它们的项目可以是任何类型的对象,尽管有时它被认为更好列表样式以具有相同类型的项目或等效使用的类型)。

元组是不可变的序列,只有很少的方法(所有非变异的特殊方法),当您需要不可变性以将容器用作集合中的项目或字典中的键时,最常使用这些方法(尽管这些项目也必须是不可变的——例如字符串、数字或其他嵌套元组,才能正常工作)。它们的项可以是任何类型的对象,元组拥有许多不同类型的项是完全正常的。

在少数情况下,元组或列表同样适用,在这种情况下,元组更小且构建速度更快的事实可用于影响有利于元组的决定.比如一个函数需要返回多个结果的时候,最正常的使用方式

return fee, fie, foo, fum

即返回一个包含有问题的四个项目的元组,而不是

return [fee, fie, foo, fum]

即,返回一个包含四个项目的列表——除了(小幅提升)性能之外,“返回一个元组”的常用习语还处理返回的多个结果通常不是 相同且不可互换的类型,因此,从风格上讲,无论如何,使用列表可能被认为是一个更可疑的选择。

tuple 的一个有用变体是它的子类型collections.namedtuple(需要 Python 2.6 或更高版本),它允许您按名称(使用属性语法)以及按索引(正常方式)访问项目。例如,模块顶部有一个import collections,上面的return 语句可能会变成...

freturn = collections.namedtuple('freturn', 'fee fie foo fum')

def f():
  ...
return freturn(fee, fie, foo, fum)

现在,f() 的调用者可以像以前一样将其返回值用作元组,但会获得不错的替代方案,例如...:

r = f()
print r.fie

代替不那么直接清晰和可读的

print r[1]

重要的是要注意,与直接使用元组相比,使用 collections.namedtuple 生成的命名元组子类基本上没有额外的开销,或者,正如文档所说,

它们很轻,不需要 比常规元组更多的内存。

【讨论】:

  • 我认为文档必须掩盖这一点,在命名元组的许多实例中进行了详细说明,没有额外的开销,但是使用了一定的额外内存,因为您正在有效地动态创建一个新的类型(当然有一些,虽然很小,内存占用)。 (顺便说一句,对于一个非常彻底的答案,仍然得到了 +1)。
【解决方案2】:

列表是可变的,你可以给它添加元素。元组不是,这意味着它(稍微)更有效率。元组也是 hashable,因此可以用作例如字典中的键。

阅读this

【讨论】:

  • 该链接完全忽略了 set (以及其他不太常用的集合,它们基本上是其他集合的变体 - freezeset 是一个不可变集合,字节它是一个列表(带有一点语法糖)等。 ..)。还是 +1
  • set 没有在问题中提及,那么为什么要在答案中提及?是的,setfrozensetlisttuple 之间有相当的差异。虽然我使用sets 的频率不如lists 和tuples 那样频繁,但它们是我工具箱中非常宝贵的工具。
  • 我在吹毛求疵,但不变性并不意味着可散列性,就像可变性意味着某些东西不可散列一样。例如,用户定义类的实例默认情况下是可散列的,但这并不意味着它们是不可变的。不可否认,不可变类型不可散列是不寻常的,但它肯定是可能的。
【解决方案3】:

列表是可变的(可以更改),元组是不可变的。典型用途:这听起来很陈词滥调,但当您需要更改值时,您会使用列表。由于元组的不变性,元组通常效率更高一些(除非您像列表一样使用它们并重复它们很多......)

【讨论】:

    【解决方案4】:

    在阅读了Python doc. on Built-in types 之后,我创建了下表来显示六个可迭代容器之间的主要区别。

    <pre>
    Container   Notation     Index [n:m]   Mutable   Hashable
    =========   ==========   ===========   =======   ========
    String      ' ' or " "    position     Immutable    Yes
    Range       range(,,)     position     Immutable    Yes
    Tuple       (,)           position     Immutable    Yes
    List        [,]           position     Yes          No
    Set         {,}           No           Yes          No
    Dict        {k:v,k:v}     by key       Yes          No
    </pre>
    

    set 和 dict 的搜索速度更快,因为它们是散列而不是排序的,因此与大小无关。元组和列表是相同的,除了元组是不可变的,它的方法比列表少,因此它不支持通过项分配来改变其内容。但是可以连接两个元组来实现“追加”功能,即t1 += t2

    由于只有不可变序列类型支持 hash(),所以 list、set 和 dict 不能用作 dict 键。这可以很容易地在下面看到,其中 'a' 是一个 dict 序列,其中包含 int、float、str、range 和 tuple 的异类不可变键类型:

    >>> a
    {range(2, 5, 2): 'range', 3: 15, 4.5: 16, 'llmjxm': 'c', -555: 666, -4.5: -25, (5, 6, 7): 'blue', 'abc3': 215, (1, 2, 3): 'red'}
    >>> for item in a.keys():
    ...     print(item, '\t\t==>>', a[item])
    ... 
    range(2, 5, 2)      ==>> range
    3       ==>> 15
    4.5         ==>> 16
    llmjxm      ==>> c
    -555        ==>> 666
    -4.5        ==>> -25
    (5, 6, 7)       ==>> blue
    abc3        ==>> 215
    (1, 2, 3)       ==>> red
    >>> 
    

    而可变类型的键会导致 TypeError:

    >>> a[{5}] = 56
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'set'
    >>> a[[5]] = 56
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> a[{5:6}] = 56
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'dict'
    >>> a[-555] = 666
    >>> 
    

    请参阅link1link2 了解更多详情。

    【讨论】:

      猜你喜欢
      • 2022-12-17
      • 2022-12-28
      • 2010-10-12
      相关资源
      最近更新 更多