元组/列表的优点/缺点是什么?
#1 楼
除了元组是不可变的之外,还应有语义上的区别来指导它们的使用。元组是异构数据结构(即,它们的条目具有不同的含义),而列表是同类序列。元组具有结构,列表具有顺序。使用这种区别可以使代码更加明确和易于理解。 br />
my_location = (42, 11) # page number, line number
然后,您可以将其用作字典中的键,以在位置上存储注释。另一方面,列表可用于存储多个位置。自然地,人们可能想在列表中添加或删除位置,因此列表是可变的很有意义。另一方面,从现有位置添加或删除项目没有意义-因此,元组是不可变的。
在某些情况下,您可能想更改现有位置元组中的项目,例如遍历页面各行的示例。但是元组不变性迫使您为每个新值创建一个新的位置元组。从表面上看这很不方便,但是使用这样的不可变数据是值类型和函数式编程技术的基石,可以具有很多优势。 “ Python元组不仅仅是常量列表”或“了解Python中的元组与列表”。官方Python文档还提到了此问题
“字符串是不可变的,并且通常包含异类序列...”。类型的语言(例如Haskell),元组中的值通常具有不同的类型,并且元组的长度必须固定。在列表中,所有值都具有相同的类型,并且长度不是固定的。所以区别非常明显。
最后,Python中有一个namedtuple,这很有意义,因为一个元组应该已经具有结构。这强调了元组是类和实例的轻量级选择的思想。
评论
+1,特别是您的第二个链接,举了一个很好的例子。喜欢这句话:“此元组用作轻量级记录或结构。”
– Baltimark
09年3月9日在17:31
“列表是同质序列”-我是Python的新手,但是列表不是异构的吗?来自docs.python.org/py3k/tutorial/introduction.html:“列表项不必全部具有相同的类型。”但是也许您在谈论的是正式概念,而不是Python。
–马修·康奈尔(Matthew Cornell)
2012年9月4日14:41
“元组”的一个好的语义同义词可能是“记录”。它是按特定顺序收集的相关数据项。实际上,我觉得collections.namedtuple最好称为collections.record。例如,在客户记录中交换名称和地址是没有意义的。实际上,这样做通常是一个错误,元组的不可变性会阻止您提交。
– Kindall
13-10-28在18:58
@nikow:关于您将如何处理这样的列表,当ppl使用缺乏幻想作为参数时,我总是会发抖。使用混合类型列表效果很好,例如对于某些分层数据结构,其中每个列表都由子列表和值元素组成。
–塞巴斯蒂安·马赫
2014年12月4日在9:15
说元组是异构的并且列表是同质的,是否具有误导性?例如,列表可以包含不同数据类型的混合,即l = [1、2,'a']。我不明白你在说什么。
– Celeletas
15年8月7日在23:24
#2 楼
列表和元组之间的区别文字
someTuple = (1,2)
someList = [1,2]
大小
a = tuple(range(1000))
b = list(range(1000))
a.__sizeof__() # 8024
b.__sizeof__() # 9088
由于元组操作的大小较小,所以它变得更快一些,但是要提到的数目不多,直到您拥有大量元素为止。
允许的操作
b = [1,2]
b[0] = 3 # [3, 2]
a = (1,2)
a[0] = 3 # Error
这也意味着您不能删除元素或对元组进行排序。
但是,您可以在列表和元组中都添加一个新元素,唯一的区别是,由于元组是不可变的,因此您并不是真正在添加元素,而是要创建一个新的元组,因此id将会改变
a = (1,2)
b = [1,2]
id(a) # 140230916716520
id(b) # 748527696
a += (3,) # (1, 2, 3)
b += [3] # [1, 2, 3]
id(a) # 140230916878160
id(b) # 748527696
用法
由于列表是可变的,因此不能用作字典中的键,而可以使用元组。
a = (1,2)
b = [1,2]
c = {a: 1} # OK
c = {b: 1} # Error
评论
那么,当我尝试将列表大小调整为较大的值时会发生什么?它会更改内存地址(我相信应该更改id)。还是会抛出一个错误?
– Rambalachandran
2015年2月5日14:49在
@WanderingMind:存储列表值的内存地址与存储列表对象本身的内存地址不同。
–汤姆
15年8月13日在14:36
嗯...除3下的第一个方框外,本文中的所有代码。允许的操作首先显示元组的大小写。我知道通常会先显示成功,然后显示错误,但是这让我有些困惑。
– dmckee ---前主持人小猫
18/09/10在15:08
如第3点所示,单个元素列表可以是one_item_list = [a],但是one_tuple =(a,)是相应的元组。注意变量名后面的逗号。但还要注意two_tuple =(a,b)。这使我不止一次离开(仍然在Python 3中)。
– mjkrause
19年2月9日在16:52
@Cheng因为对元组进行排序会使其变异,即更改其项目。元组不支持这一点。在python中获取排序后的元组的最简单方法是tuple(sorted(the_unsorted_tuple))
–接近黑暗鱼
5月7日20:44
#3 楼
如果您去散步,可以随时在一个(x,y)
元组中记录您的坐标。如果您想记录自己的旅程,可以每隔几秒钟将位置附加到一个列表中。 />
,但是您无法做到这一点。
评论
此示例看起来仅是一个约定。人们可能会争辩说“如果愿意,我仍然可以使用[x,y]来标注坐标”。因此,除非另有一句话,否则认为该答案尚未完成:“请阅读@nikow的帖子,以了解为什么不应该使用列表存储坐标”
– RayLuo
13年3月29日在15:47
@Iceberg,我的回答旨在帮助发展直觉。这并不意味着探索该主题的每一个细微差别。
– dan-gph
2013年4月14日0:00,
不错的例子+1。它强调了元组元素(此处为坐标)的互补性,这就是不允许修改其中任何一个的原因-因为它更改了整个元组的含义(此处为一个点的位置)。
–王浩
15年1月4日在6:54
#4 楼
关键区别在于元组是不可变的。这意味着创建元组后就无法更改其值。因此,如果您需要更改值,请使用列表。
到元组:
性能略有改善。
由于元组是不可变的,因此可以用作字典中的键。
如果不能更改它其他人也不能,也就是说,您无需担心任何API函数等。在不询问您的情况下更改元组。
评论
请注意,只有其所有元素都为元组时,元组才是不可变的。您可以说所有不可变集合都一样,例如Frozenset或各种第三方的dict / tree / etc。类型,但这些都不允许您添加可变元素。 (当然,元组只有在其所有元素都可用的情况下才是可哈希的,这是按常规EAFP方法处理的,因此d [1,[2]]将引发TypeError:无法哈希的类型:'list'。)
–abarnert
2014年11月26日20:45
如果元组的所有元素都是不可变的,则只能将其用作字典中的键。看这里
–威尔·德勒姆(Will Dereham)
17-3-26在10:49
#5 楼
列表是可变的;元组不是。来自docs.python.org/2/tutorial/datastructures.html
元组是不可变的,并且通常包含
元素,这些元素可以通过拆包(请参阅本节后面的内容)或索引(或在namedtuple的情况下甚至通过属性)进行访问。列表
是可变的,并且它们的元素通常是同质的,并且可以通过遍历列表来访问
。
评论
我真的认为您还应该考虑语义含义(请参阅下面的答案)。
– nikow
09年3月9日在16:07
现在看来几乎不值得付出努力,但要多加注意。
–duffymo
2009年3月9日19:50
好的,这是链接-docs.python.org/2/library/stdtypes.html#mutable-sequence-types ;-)
– Alexey Kuzminich
2013年4月26日在1:07
@duffymo我认为此答案是此页面上最清晰,最简洁的答案。它指出了元组和列表之间唯一真正重要的区别,并且不会无休止地谈论这种公然错误的同质vs异质hogwash。
– antred
2015年10月20日15:15
#6 楼
有人提到,区别主要是语义上的:人们期望元组和列表表示不同的信息。但这远远超出了指导原则。有些库实际上根据传递的内容而有所不同。以NumPy为例(从另一篇文章中我希望得到更多示例):一个主要的Python库,在NumPy列表和元组中是完全不同的东西。
评论
这并不是真正有用的答案。区别在于type(a_list)!= type(a_tuple),因此基于type(x)的任何库代码分支的行为都将有所不同
–埃里克
2013年9月19日在13:14
好一点,我已经编辑了这篇文章:这实际上只是指出语义准则已硬编码到某些库中。
– Shep
2013年9月20日在7:56
使用stdlib / builtins中的示例可能比第三方库中的示例更好。您可以在许多地方使用单个值或值的元组,列表或其他序列也被视为单个值。例如,'%d%d'%[2,3]是一个TypeError,因为您试图将列表传递给第一个%d,并且没有将任何值传递给第二个%d。 (但是,也有与此相反的示例,例如max…)
–abarnert
2014年12月1日20:23
很有意思,我不知道python标准库中有任何此类示例。您说了几个地方?
– Shep
2014年12月2日在21:22
#7 楼
列表用于循环,元组用于结构,即"%s %s" %tuple
。列表通常是同质的,元组通常是异构的。
列表用于可变长度,元组用于固定长度。
#8 楼
这是Python列表的示例:my_list = [0,1,2,3,4]
top_rock_list = ["Bohemian Rhapsody","Kashmir","Sweet Emotion", "Fortunate Son"]
这是Python元组的示例:
my_tuple = (a,b,c,d,e)
celebrity_tuple = ("John", "Wayne", 90210, "Actor", "Male", "Dead")
Python列表和元组的相似之处在于它们都是有序的值集合。除了使用方括号“ [...,...]”创建列表和使用括号“(...,...)”创建元组的浅层差异外,它们之间的核心技术“用Python语法进行硬编码”差异是特定元组的元素是不可变的,而列表是可变的(...因此,仅元组是可哈希的,可以用作字典/哈希键!)。这就导致了它们的使用方式或不使用方式的差异(通过语法先验地实现)以及人们选择使用它们的方式的差异(鼓励作为“最佳实践”,后验,这就是智能程序员所做的事情)。在区分何时使用元组与何时使用列表时,后验的主要区别在于人们赋予元素顺序的含义。
对于元组,“顺序”仅表示存储信息的特定“结构”。在第一个字段中找到的值可以轻松切换到第二个字段,因为每个值都提供跨两个不同维度或比例的值。它们为不同类型的问题提供答案,并且通常采用以下形式:对于给定的对象/对象,其属性是什么?对象/对象保持不变,属性不同。
对于列表,“顺序”表示顺序或方向。第二个元素必须位于第一个元素之后,因为它基于特定且通用的比例或尺寸位于第二位。这些元素是一个整体,并且通常针对一个给定属性的形式(通常是形式)的单个问题提供答案,这些对象/对象如何比较?该属性保持不变,对象/主题有所不同。
流行文化中有无数的例子,程序员不遵循这些差异,无数人可能会在主菜上使用色叉。一天结束后,一切都很好,通常都可以完成工作。
总结一些更好的细节
相似之处:
重复项-元组和列表都允许重复项
索引,选择和切片-元组和列表索引都使用括号内的整数值进行索引。因此,如果要给定列表或元组的前3个值,语法将是相同的:
>>> my_list[0:3]
[0,1,2]
>>> my_tuple[0:3]
[a,b,c]
比较和排序-两个元组或两个列表都通过第一个元素进行比较,如果有平局,则通过第二个元素进行比较,依此类推。
>>> [0,2,0,0,0,0]>[0,0,0,0,0,500]
True
>>> (0,2,0,0,0,0)>(0,0,0,0,0,500)
True
区别:-先验,根据定义
语法-列表使用[],元组使用()
可变性-给定列表中的元素可变,给定元组中的元素不可变。
# Lists are mutable:
>>> top_rock_list
['Bohemian Rhapsody', 'Kashmir', 'Sweet Emotion', 'Fortunate Son']
>>> top_rock_list[1]
'Kashmir'
>>> top_rock_list[1] = "Stairway to Heaven"
>>> top_rock_list
['Bohemian Rhapsody', 'Stairway to Heaven', 'Sweet Emotion', 'Fortunate Son']
# Tuples are NOT mutable:
>>> celebrity_tuple
('John', 'Wayne', 90210, 'Actor', 'Male', 'Dead')
>>> celebrity_tuple[5]
'Dead'
>>> celebrity_tuple[5]="Alive"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
哈希表(字典)-由于哈希表(字典)要求其键是可哈希的,因此是不可变的,只有元组可以用作字典键,而不能列表。
#Lists CAN'T act as keys for hashtables(dictionaries)
>>> my_dict = {[a,b,c]:"some value"}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
#Tuples CAN act as keys for hashtables(dictionaries)
>>> my_dict = {("John","Wayne"): 90210}
>>> my_dict
{('John', 'Wayne'): 90210}
差异-后验,用法
元素的均质性与异质性-一般列表对象是同质的,元组对象是异质的。也就是说,列表用于相同类型的对象/对象(例如所有总统候选人,所有歌曲或所有跑步者),而尽管不是强制的,但元组更多地用于异构对象。循环与结构-尽管两者都允许循环(对于my_list中的x,...),但实际上只对列表有意义。元组更适合于结构化和表示信息(驻留在%s中的%s%s是%s,当前是%s%(“ John”,“ Wayne”,90210,“ Actor”,“ Dead”))
评论
我喜欢哈希表/可哈希示例来解释不可变性的原因-您可以使用元组(record / struct / coordinate / vector / point)作为dict中的复杂键。
–戴夫X
18年3月28日在20:13
#9 楼
list的值可以随时更改,但是元组的值不能更改。优缺点取决于用途。如果您拥有从未更改过的数据,则必须使用元组,否则list是最佳选择。
#10 楼
列表和元组之间的区别在Python中,数组和列表看起来都是相似的序列类型。
文字语法
我们使用括号(
)构造元组和方括号[ ]
以获得新列表。同样,我们可以使用适当类型的调用来获取所需的结构—元组或列表。是不可变的,而列表是可变的。这是以下几点的基础。
内存使用情况
由于可变性,您需要更多的内存用于列表,而更少的内存用于元组。扩展
您可以在元组和列表中添加一个新元素,唯一的区别是元组的ID将被更改(即,我们将有一个新对象)。 br />
散列
Tuples是可散列的,而列表则不是。这意味着您可以将元组用作字典中的键。该列表不能用作字典中的键,而可以使用元组
someTuple = (4,6)
someList = [2,6]
语义
这一点与最佳实践有关。您应该将元组用作异构数据结构,而列表则是同质序列。
评论
我在这里投票赞成对扩展和哈希的明确讨论,而在其他方面非常好的现有答案中,我没有注意到。
– dmckee ---前主持人小猫
18/09/10在15:17
#11 楼
列表旨在为同质序列,而元组为异构数据结构。评论
在这一点上,这个答案没有增加任何讨论,因为还有许多其他更好的答案。
–乔纳森·莱因哈特(Jonathon Reinhart)
13年11月25日在2:14
#12 楼
正如人们已经在这里回答的那样,tuples
是不可变的,而lists
是可变的,但是使用元组有一个重要方面,我们必须记住如果
tuple
包含list
或dictionary
,那么即使tuple
本身是不可变的,也可以更改。例如,假设我们有一个包含列表和字典的元组,如my_tuple = (10,20,30,[40,50],{ 'a' : 10})
我们可以将列表的内容更改为
my_tuple[3][0] = 400
my_tuple[3][1] = 500
,这会使新的元组看起来像
(10, 20, 30, [400, 500], {'a': 10})
我们也可以将元组中的字典更改为
my_tuple[4]['a'] = 500
,这将使整个元组看起来像
(10, 20, 30, [400, 500], {'a': 500})
list和
dictionary
是对象,并且这些对象没有更改,但是其指向的内容。评论
如果您解释说“即使元组本身是不可变的,也可以更改这些内容”,那么这篇文章将得到改善。是因为这些对象保留了自己的身份(所以元组没有更改,因为它仍然包含相同的对象...)。
– dmckee ---前主持人小猫
18/09/10在15:19
#13 楼
PEP 484-类型提示说tuple
的元素类型可以单独键入;这样你就可以说Tuple[str, int, float]
;但是带有list
类型类的List
只能使用一个类型参数:List[str]
,这暗示着2的区别实际上是前者是异质的,而后者本质上是同质的。标准库通常将元组用作此类标准函数的返回值,其中C将返回struct
。#14 楼
正如人们已经提到的差异一样,我会写为什么使用元组。为什么首选元组? />为了减少内存碎片并加快分配速度,Python重用了旧的元组。如果不再需要
元组并且少于20个项目(而不是删除
),则Python会将其永久移至空闲列表。其中每个组代表一个长度为n的0到20之间的元组列表。每个组最多可以存储2000个元组。第一个(零个)组仅包含一个元素,并且
代表一个空的元组。
>>> a = (1,2,3)
>>> id(a)
4427578104
>>> del a
>>> b = (1,2,4)
>>> id(b)
4427578104
可以看到a和b具有相同的ID。那是
,因为我们立即占据了一个被破坏的元组,该元组位于
空闲列表中。 Python使用的优化与元组不同。但是,
Python列表也有一个空闲列表,但是它仅用于空的
对象。如果GC删除了空白列表或收集了空白列表,则以后可以重新使用。
com / blog / python-lists-and-tuples /
为什么元组比列表更有效? -> https://stackoverflow.com/a/22140115
#15 楼
5.3文档中的方向引文。元组和序列:尽管元组看起来类似于列表,但它们通常用于不同的情况和不同的目的。元组是不可变的,通常包含异类元素序列,这些元素可通过拆包(请参阅本节后面)或索引(甚至在命名元组的情况下通过属性)进行访问。列表是可变的,并且它们的元素通常是同质的,可以通过遍历列表来访问。
#16 楼
最重要的区别是时间!当您不想更改列表内的数据时,最好使用元组!这是为什么使用元组的示例!import timeit
print(timeit.timeit(stmt='[1,2,3,4,5,6,7,8,9,10]', number=1000000)) #created list
print(timeit.timeit(stmt='(1,2,3,4,5,6,7,8,9,10)', number=1000000)) # created tuple
在此示例中,我们两个语句都执行了100万次
输出: 。
#17 楼
首先,它们都是Python中的非标量对象(也称为复合对象)。元素的有序序列(可以包含没有别名的任何对象)问题)
不可变(元组,整数,浮点数,str)
使用
+
串联(当然将创建全新的元组)切片单个
(3,) # -> (3)
代替(3) # -> 3
列表(其他语言的数组),值的有序序列可变
单身
[3]
克隆
new_array = origin_array[:]
列表理解
[x**2 for x in range(1,7)]
给你[1,4,9,16,25,36]
(不可读)使用列表也可能导致别名错误(两个不同的路径
指向同一对象)。
#18 楼
列表是可变的,元组是不可变的。只考虑这个例子。 >
a = ["1", "2", "ra", "sa"] #list
b = ("1", "2", "ra", "sa") #tuple
因此证明了以下代码对于元组无效,因为我们试图更新一个元组,这是不允许的。
#19 楼
只是list
与tuple
响应的快速扩展:由于动态特性,
list
分配的位存储桶数超过了所需的实际内存。这样做是为了防止将来添加额外的项目时进行昂贵的重新分配操作。另一方面,轻量级
tuple
对象是静态的,不会保留存储它们所需的额外内存。#20 楼
列表是可变的,元组是不可变的。可变项和不可变项之间的主要区别在于,尝试追加项目时的内存使用情况。创建变量时,会将一些固定内存分配给该变量。如果是列表,则分配的内存将超过实际使用的内存。例如。如果当前的内存分配为100字节,则当您要追加第101个字节时,可能会另外分配100个字节(在这种情况下,总共为200个字节)。
但是,如果您知道不经常添加新元素,则应该使用元组。元组精确分配所需的内存大小,从而节省了内存,尤其是当您使用较大的内存块时。
评论
尽管其中有些在技术上是正确的,但这并不是可变类型和不可变类型之间的关键区别。更大的区别在于,可变类型可以在构造后进行更改,而不变类型则不能。
– Roger Fan
2014年9月30日19:25在
这也不是原因。内存和可变性彼此无关。那只是列表的特定实现细节。内存也没有分配给变量,而是分配给了对象。变量只是对这些对象的引用。
– Roger Fan
2014-09-30 19:32
评论
其他人在下面回答,但我想指出的是,恕我直言,python具有完全不直观的数据类型名称。我认为其他语言都没有元组(以该名称命名),更糟糕的是,我什至无法将其翻译成我的语言。有谁知道“元组”来自哪里?荷兰语?元组是数学的基本术语,源自拉丁语(请参阅维基百科)。
对->三元组->四元组->五元组->六元组->嗯,它叫什么,啊草皮,7元组-> 8元组-> ...因此有“ tuple”作为通用名称。 >
@JohnFouhy已经过了六年了,但是:...七联,八联,九元组,十个,十个,十二个...:D
@MegaWidget我以为我们已经确定一个元组就是一个列表。 ; D