列表和元组有什么区别?
- 2024-11-27 10:43:00
- admin 原创
- 17
问题描述:
元组/列表之间有什么区别以及它们的优点/缺点是什么?
解决方案 1:
除了元组是不可变的之外,还有一个语义上的区别可以指导它们的使用。元组是异构数据结构(即,它们的条目具有不同的含义),而列表是同质序列。元组有结构,列表有顺序。
使用这种区别使得代码更加明确和易于理解。
一个例子是使用页码和行号来引用书中的位置,例如:
my_location = (42, 11) # page number, line number
然后,您可以将其用作字典中的键来存储位置注释。另一方面,列表可用于存储多个位置。自然地,人们可能希望从列表中添加或删除位置,因此列表可变是有意义的。另一方面,从现有位置添加或删除项目是没有意义的 - 因此元组是不可变的。
在某些情况下,您可能想要更改现有位置元组中的项目,例如在遍历页面的行时。但元组不可变性迫使您为每个新值创建一个新的位置元组。这表面上似乎不方便,但使用这样的不可变数据是值类型和函数式编程技术的基石,可以带来巨大的优势。
关于这个问题有一些有趣的文章,例如“Python 元组不仅仅是常量列表”或“理解 Python 中的元组与列表”。官方 Python 文档也提到了这一点
“元组是不可变的,并且通常包含异构序列...”。
在Haskell这样的静态类型语言中,元组中的值通常具有不同的类型,并且元组的长度必须是固定的。在列表中,所有值都具有相同的类型,并且长度不固定。因此差异非常明显。
最后,Python 中还有命名元组,这是有道理的,因为元组本来就应该具有结构。这强调了元组是类和实例的轻量级替代方案这一理念。
解决方案 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
解决方案 3:
如果你出去散步,你可以随时在(x,y)
元组中记录你的坐标。
如果您想记录您的旅程,您可以每隔几秒钟将您的位置附加到列表中。
但你不能反过来做。
解决方案 4:
关键区别在于元组是不可变的。这意味着一旦创建了元组,就无法更改其中的值。
因此如果您需要更改值,请使用列表。
元组的好处:
性能略有提升。
由于元组是不可变的,因此它可以用作字典中的键。
如果您不能更改它,那么其他人也不能更改它,也就是说,您不必担心任何 API 函数等在未经要求的情况下更改您的元组。
解决方案 5:
列表是可变的;元组不是。
来自docs.python.org/2/tutorial/datastructures.html
元组是不可变的,通常包含一个异构元素序列,可通过解包(请参阅本节后面的内容)或索引(或者在命名元组的情况下甚至通过属性)访问。列表是可变的,其元素通常是同构的,可通过迭代列表来访问。
解决方案 6:
这是 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}
差异——事后使用
元素的同质性与异质性 - 通常列表对象是同质的,而元组对象是异质的。也就是说,列表用于相同类型的对象/主题(例如所有总统候选人、所有歌曲或所有参赛者),而元组则更多地用于异质对象。
循环与结构 - 虽然两者都允许循环(for x in my_list...),但只有对列表进行循环才有意义。元组更适合构造和呈现信息(%s %s 驻留在 %s 中,是 %s,目前是 %s % ("John","Wayne",90210, "Actor","Dead"))
解决方案 7:
有人提到,差异主要是语义上的:人们期望元组和列表代表不同的信息。但这不仅仅是一个指导方针;一些库实际上根据传递的内容而表现不同。以 NumPy 为例(从另一篇我要求提供更多示例的帖子中复制而来):
>>> import numpy as np
>>> a = np.arange(9).reshape(3,3)
>>> a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> idx = (1,1)
>>> a[idx]
4
>>> idx = [1,1]
>>> a[idx]
array([[3, 4, 5],
[3, 4, 5]])
重点是,虽然 NumPy 可能不是标准库的一部分,但它是一个主要的Python 库,并且在 NumPy 中列表和元组是完全不同的东西。
解决方案 8:
列表用于循环,元组用于结构,即"%s %s" %tuple
。
列表通常是同质的,元组通常是异构的。
列表是可变长度,元组是固定长度。
解决方案 9:
列表和元组之间的区别
元组和列表都是 Python 中看似相似的序列类型。
文字语法
我们使用括号 ( ) 构造元组,使用方括号[ ]
获取新列表。此外,我们还可以使用适当类型的调用来获取所需的结构 — 元组或列表。
someTuple = (4,6)
someList = [2,6]
可变性
元组是不可变的,而列表是可变的。这一点是以下内容的基础。
内存使用情况
由于可变性,列表需要更多的内存,而元组需要更少的内存。
扩展
您可以向元组和列表添加新元素,唯一的区别是元组的 id 会被改变(即,我们将有一个新的对象)。
哈希
元组是可哈希的,而列表不是。这意味着你可以将元组用作字典中的键。列表不能用作字典中的键,而元组可以
tup = (1,2)
list_ = [1,2]
c = {tup : 1} # ok
c = {list_ : 1} # error
语义
这一点更多的是关于最佳实践。您应该使用元组作为异构数据结构,而列表是同质序列。
解决方案 10:
列表的值可以随时改变,但元组的值不能改变。
优点和缺点取决于用途。如果你有这样的数据,你永远不想改变,那么你应该使用元组,否则列表是最好的选择。
解决方案 11:
列表旨在成为同质序列,而元组是异构数据结构。
解决方案 12:
由于人们已经提到了差异,我将写一下为什么是元组。
为什么元组更受青睐?
小元组的分配优化
为了减少内存碎片并加快分配速度,Python 会重用旧元组。如果不再需要某个元组且其项数少于 20 个,Python 不会将其永久删除,而是将其移至空闲列表。
空闲列表分为 20 个组,每个组代表一个长度为 n(介于 0 和 20 之间)的元组列表。每个组最多可存储 2 000 个元组。第一个(零)组仅包含 1 个元素,表示一个空元组。
>>> a = (1,2,3)
>>> id(a)
4427578104
>>> del a
>>> b = (1,2,4)
>>> id(b)
4427578104
在上面的例子中,我们可以看到 a 和 b 有相同的 id。这是因为我们立即占用了空闲列表中一个被销毁的 tuple。
列表的分配优化
由于列表可以修改,因此 Python 不会使用与元组相同的优化。但是,Python 列表也有一个空闲列表,但它仅用于空对象。如果空列表被删除或被 GC 收集,则可以稍后重新使用。
>>> a = []
>>> id(a)
4465566792
>>> del a
>>> b = []
>>> id(b)
4465566792
来源:https://rushter.com/blog/python-lists-and-tuples/
为什么元组比列表更有效率? -> https://stackoverflow.com/a/22140115
解决方案 13:
PEP 484 -- 类型提示表示,a 的元素类型tuple
可以单独输入;因此您可以说Tuple[str, int, float]
;但是list
,具有List
类型类的 a 只能采用一个类型参数:List[str]
,这暗示两者的区别实际上在于前者是异构的,而后者本质上是同质的。
此外,标准库主要使用元组作为标准函数的返回值,而 C 将返回struct
。
解决方案 14:
正如人们已经在这里回答的那样,它们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
是对象,并且这些对象没有改变,而是它指向的内容改变了。
因此tuple
保持不变,无一例外
解决方案 15:
最重要的区别是时间!当你不想更改列表内的数据时,最好使用元组!以下是使用元组的示例!
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 万次
输出 :
0.136621
0.013722200000000018
任何人都可以清楚地注意到时差。
解决方案 16:
list
对vs 响应进行快速扩展tuple
:
由于动态特性,
list
分配的位存储桶比实际所需的内存更多。这样做是为了防止将来添加额外项目时进行昂贵的重新分配操作。另一方面,作为静态的,轻量级
tuple
对象不会保留存储它们所需的额外内存。
解决方案 17:
来自5.3. 元组和序列文档的一个方向引用:
尽管元组看起来与列表相似,但它们通常用于不同的情况和目的。元组是不可变的,通常包含一个异构元素序列,可通过解包(请参阅本节后面的内容)或索引(或者在命名元组的情况下甚至通过属性)访问。列表是可变的,其元素通常是同质的,可通过迭代列表来访问。
解决方案 18:
首先,它们都是Python中的非标量对象(也称为复合对象)。
元组,元素的有序序列(可以包含任何对象而没有别名问题)
+ 不可变(元组,整数,浮点数,字符串)
+ 使用连接`+`(当然会创建全新的元组)
+ 索引
+ 切片
+ 单例`(3,) # -> (3)`模式`(3) # -> 3`
列表(其他语言中为数组),值的有序序列
+ 可变
+ 单例`[3]`
+ 克隆`new_array = origin_array[:]`
+ 列表推导`[x**2 for x in range(1,7)]`给你
`[1,4,9,16,25,36]`(不可读)
使用列表也可能导致别名错误(两个不同的路径指向同一个对象)。
解决方案 19:
列表是可变的,而元组是不可变的。请考虑这个例子。
a = ["1", "2", "ra", "sa"] #list
b = ("1", "2", "ra", "sa") #tuple
现在改变列表和元组的索引值。
a[2] = 1000
print a #output : ['1', '2', 1000, 'sa']
b[2] = 1000
print b #output : TypeError: 'tuple' object does not support item assignment.
因此证明以下代码对于元组无效,因为我们试图更新元组,这是不允许的。
解决方案 20:
列表是可变的。而元组是不可变的。使用索引访问元组中的偏移元素比列表更有意义,因为元素及其索引无法更改。
解决方案 21:
换句话说,TUPLES 用于存储元素组,其中组的内容/成员不会改变,而 LISTS 用于存储元素组,其中组的成员可以改变。
例如,如果我想将我的网络 IP 存储在变量中,最好使用元组,因为 IP 是固定的。像这样my_ip = ('192.168.0.15', 33, 60)
。但是,如果我想存储我将在未来 6 个月内访问的地方的 IP 组,那么我应该使用 LIST,因为我会不断更新并将新 IP 添加到该组中。像这样
places_to_visit = [
('192.168.0.15', 33, 60),
('192.168.0.22', 34, 60),
('192.168.0.1', 34, 60),
('192.168.0.2', 34, 60),
('192.168.0.8', 34, 60),
('192.168.0.11', 34, 60)
]
解决方案 22:
列表是可变的,而元组是不可变的。可变和不可变之间的主要区别在于当您尝试附加项目时内存的使用情况。
创建变量时,会为该变量分配一些固定内存。如果是列表,则分配的内存比实际使用的内存多。例如,如果当前内存分配为 100 字节,当您想要附加第 101 个字节时,可能会分配另外 100 字节(在这种情况下总共 200 字节)。
但是,如果你知道你不会经常添加新元素,那么你应该使用元组。元组会分配所需的内存大小,因此可以节省内存,尤其是当你使用大块内存时。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件