在 Python 中,我可以使用 append() 函数将值附加到列表中,但是对于元组,这一切都会发生变化,它们的处理方式也不同。它的结构似乎与列表的结构非常相似,我想知道它的用处或用途。
Python 中的元组具有以下结构:
a = (1,2,3,4)
虽然列表是另一个:
b = [1,2,3,4]
如果有人能向我解释为什么 Python 中需要元组以及在什么情况下应该使用它们,我将不胜感激。
在 Python 中,我可以使用 append() 函数将值附加到列表中,但是对于元组,这一切都会发生变化,它们的处理方式也不同。它的结构似乎与列表的结构非常相似,我想知道它的用处或用途。
Python 中的元组具有以下结构:
a = (1,2,3,4)
虽然列表是另一个:
b = [1,2,3,4]
如果有人能向我解释为什么 Python 中需要元组以及在什么情况下应该使用它们,我将不胜感激。
主要区别在于元组是不可变的(它们不能被修改)而列表不是。这种不变性使得对其应用散列函数成为可能。
另一个非常重要的问题是元组比列表更有效。因此,除非您需要数据结构的可变性,否则使用元组而不是列表更方便。让我们详细看看为什么。
1. 编译
Python 在编译时而不是在执行时将元组识别和评估为常量表达式,这被称为常量折叠。
disassembly
我可以用python模块向你展示这一点离开
实际上,Python 已将元组评估为常量表达式并返回它,但是在列表中,它必须将列表中的每个元素评估为常量,然后构建列表并最终返回它。这当然需要时间让我们看看
离开:
一个元组大约快 10 倍
警告
发生这种行为是因为我们创建了具有不可变元素的元组,如果只有一个元素是 mutable,则 Python 将以与列表相同的方式评估该元组,并且时间将相似。
2.复制
当你想要复制一个列表时,Python 会再次分配内存来创建一个新列表。在元组的情况下,由于它们的不变性,它们不会被复制,只是创建了一个浅拷贝引用 。让我们证明一下:
离开:
复制列表时,它们位于不同的内存位置,但是元组位于相同的内存位置。
这也会影响执行时间:
离开
请注意,我从 tuple 复制了列表,以避免包括列表具有的额外创建时间(我们在第 1 点中看到),因此我们只关注副本,这是一个公平的比较。
3.存储
元组的存储是精确的,也就是说,Python 保留了存储元组所需的空间,因为它是不可变的。在列表中不同的是,Python 为列表保留了比所需空间更多的空间,这称为过度分配和预分配,目的是优化所述列表中元素的条目。如果您想了解更多,可以查看动态数组。让我们看看这个:
离开:
实际上,元组总是保留 8 个字节并为元素占用足够的空间,但是列表占用更多空间并进行不同的内存保留。
这是因为,当保留比必要更多的内存时,Python 使用一种算法,查看列表的大小,计算它将保留多少空间。因此,例如,如果我们使用
.append()
并且列表增长,我们避免必须重新保留空间来输入元素,因为所述空间是先前保留的。奖金
另一个相关但可以忽略的问题是,由于它是不可变的,因此可以保持顺序,也就是说,在 tuples中,元素出现的顺序是有意义的。
唯一的区别是元组是不可变的,而列表不是。
这种区别可能很重要,原因有两个:
您可能希望有一个“组”值作为参数传递给函数,但您希望确保该函数不会修改组中的任何值。由于在 python 中一切都是引用,一旦函数接收到对“组”(列表、对象)的引用,它就可以更改其值。解决它的唯一方法是使该组成为一个元组。事实上,我建议你也研究一下那些
namedtuples
创建看起来像对象(带有其命名字段)但实际上在内部作为元组实现的机制的机制,因此它是不可变的。这个用例比乍看起来更重要。我已经疯狂地调试代码,最终导致错误是因为数据列表没有我加载到其中的数据,而是其他数据,因为接收它作为参数的多个函数之一修改了它。最后,我通过将所有列表更改为元组并查看当函数尝试修改数据时程序在哪里中断来解决它。
感谢元组,
namedtuples
我能够重构程序,使所有函数都是纯函数(它们不会对不属于函数的变量造成二次影响)。这更容易调试和维护。几乎更重要的是,它们是不可变的,它们也是可散列的。也就是说,函数可以应用于它们
hash()
并且结果将始终相同。在列表中,如果列表的元素发生了变化,那么哈希值显然会发生变化。散列数据很重要,因为只有散列数据可以存储在集合中(
set()
)或可以用作字典键(因为这些数据结构基本上是散列表)。因此,如果您发现自己需要使用列表作为字典中的键,您会发现自己做不到。将其转换为元组,您就可以开始了。
根据resourcespython.com。
列表与元组不同,两者都是有序的值集合,后者可以是任何对象:数字、字符串、函数、类、实例等。
不同之处在于列表具有一系列附加功能,可以广泛处理它们包含的值。根据这个定义,可以说列表是动态的,而元组是静态的。