213 lines
8.2 KiB
Markdown
213 lines
8.2 KiB
Markdown
# Python 元组:如何创建、使用和转换
|
||
|
||
> 原文:[https://python.land/python-data-types/python-tuple](https://python.land/python-data-types/python-tuple)
|
||
|
||
Python tuple 是 Python 三种内置的[序列数据类型](https://docs.python.org/3.9/library/stdtypes.html?highlight=tuple#sequence-types-list-tuple-range)之一,另外两种是列表和范围对象。Python 元组与更常见的 [Python 列表](https://python.land/python-data-types/python-list)共享许多属性:
|
||
|
||
* 它可以在一个变量中保存多个值
|
||
* 它是有序的:项目的顺序被保留
|
||
* 元组可以有重复的值
|
||
* 它是有索引的:你可以用数字来访问项目
|
||
* 元组可以具有任意长度
|
||
|
||
但是有显著的不同:
|
||
|
||
* 元组是不可变的;一旦定义,就不能更改。
|
||
* 使用*可选的*括号()而不是方括号[]来定义元组
|
||
* 因为元组是不可变的,所以它可以被散列,因此它可以充当字典中的键
|
||
|
||
目录
|
||
|
||
|
||
|
||
* [创建一个 Python 元组](#Creating_a_Python_tuple "Creating a Python tuple")
|
||
* [使用 Python 元组的多重赋值](#Multiple_assignment_using_a_Python_tuple "Multiple assignment using a Python tuple")
|
||
* [索引访问](#Indexed_access "Indexed access")
|
||
* [追加到一个 Python 元组](#Append_to_a_Python_Tuple "Append to a Python Tuple")
|
||
* [获取元组长度](#Get_tuple_length "Get tuple length")
|
||
* [Python 元组 vs 列表](#Python_Tuple_vs_List "Python Tuple vs List")
|
||
* [Python 元组 vs 集合](#Python_Tuple_vs_Set "Python Tuple vs Set")
|
||
* [转换 Python 元组](#Converting_Python_tuples "Converting Python tuples")
|
||
|
||
|
||
|
||
## 创建一个 Python 元组
|
||
|
||
我们使用可选的括号(圆括号)从单个值创建元组,如下所示:
|
||
|
||
```py
|
||
>>> my_numbers = (1, 2, 3)
|
||
>>> the_same = 1, 2, 3
|
||
>>> my_strings = ('Hello', 'World')
|
||
>>> my_mixed_tuple = ('Hello', 123, True)
|
||
```
|
||
|
||
像 Python 中的所有东西一样,元组是对象,并且有一个定义它们的类。我们还可以通过使用该类的`tuple()`构造函数来创建一个元组。它允许任何 Python 可迭代的 T2 类型作为参数。在下面的例子中,我们从一个列表中创建一个元组:
|
||
|
||
```py
|
||
>>> tuple([0,1,2])
|
||
(0, 1, 2)
|
||
>>>
|
||
```
|
||
|
||
现在您也知道如何将 Python 列表转换成元组了!
|
||
|
||
### 哪种方法最好?
|
||
|
||
Python 并不总是很容易推断出您是在使用常规括号还是在尝试创建元组。为了演示,让我们定义一个仅包含一项的元组:
|
||
|
||
```py
|
||
>>> t = (1)
|
||
1
|
||
>>> t = (1, )
|
||
(1,)
|
||
```
|
||
|
||
Python 在第一次尝试时看到数字 1,它被无用的括号包围,因此 Python 将表达式分解为数字 1。然而,我们在第二次尝试中添加了一个逗号,明确地向 Python 发出信号,表明我们正在创建一个只有一个元素的元组。
|
||
|
||
只有一个条目的元组对于大多数用例来说是无用的,但是它演示了 Python 如何识别元组:因为有逗号。
|
||
|
||
如果我们可以使用`tuple()`,为什么还有第二种方法呢?另一种符号更简洁,但也有它的价值,因为您可以使用它以这种简洁的方式将多个列表解包到一个元组中:
|
||
|
||
```py
|
||
>>> l1 = [1, 2, 3]
|
||
>>> l2 = [4, 5, 6]
|
||
>>> t = (*l1, *l2)
|
||
>>> t
|
||
(1, 2, 3, 4, 5, 6)
|
||
```
|
||
|
||
第一个`*`操作符将列表分解成单独的元素。就好像你会在那个地方把它们一个一个地打出来。如果您想知道,这个解包技巧适用于所有的可迭代类型!
|
||
|
||
Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these *free* articles, I hope you understand! **Support me by disabling your adblocker on my website** or, alternatively, **[buy me some coffee](https://www.buymeacoffee.com/pythonland)**. It's much appreciated and allows me to keep working on this site!
|
||
|
||
## 使用 Python 元组的多重赋值
|
||
|
||
在前面的主题中,您已经看到了称为元组解包的东西。还有另一种解包元组的方法,叫做多重赋值。这是一个经常使用的东西,尤其是当从函数返回数据时,所以值得一看。
|
||
|
||
多重赋值是这样工作的:
|
||
|
||
```py
|
||
>>> person = ('Erik', 38, True)
|
||
>>> name, age, registered = person
|
||
>>> name
|
||
'Erik'
|
||
>>> _
|
||
```
|
||
|
||
像使用*一样,这种类型的解包适用于 Python 中的所有可迭代类型,包括列表和字符串。
|
||
|
||
正如我在关于从 Python 函数返回多个值的 [Python 技巧中解释的那样,](https://python.land/return-multiple-values-from-function)解包元组在与返回多个值的函数结合使用时效果很好。这是一种返回多个值的简洁方法,无需求助于[数据类](https://python.land/python-data-classes)或[字典](https://python.land/python-datatypes/dictionaries):
|
||
|
||
```py
|
||
def get_user_by_id(userid):
|
||
# fetch user from database
|
||
# ....
|
||
return name, age
|
||
|
||
name, age = get_user_by_id(4)
|
||
```
|
||
|
||
## 索引访问
|
||
|
||
我们可以使用像`[0]`和`[1]`这样的索引号来访问一个元组:
|
||
|
||
```py
|
||
>>> my_mixed_tuple = 'Hello', 123, True
|
||
>>> my_mixed_tuple[0]
|
||
'Hello'
|
||
>>> my_mixed_tuple[2]
|
||
True
|
||
>>> _
|
||
```
|
||
|
||
## 追加到一个 Python 元组
|
||
|
||
因为 tuple 是不可变的,**你不能在创建 tuple 之后把数据追加到它上面**。出于同样的原因,您也不能从元组中删除数据。当然,您可以从旧的元组创建一个新的元组,并将额外的项附加到它上面,方法如下:
|
||
|
||
```py
|
||
>>> t1 = (1, 2, 3)
|
||
>>> t = (*t1, 'Extra', 'Items')
|
||
>>> t
|
||
(1, 2, 3, 'Extra', 'Items')
|
||
```
|
||
|
||
我们所做的是解包`t1`,用解包的值和两个不同的字符串创建一个新的元组,并再次将结果赋给`t`。
|
||
|
||
## 获取元组长度
|
||
|
||
`len()`函数作用于 Python 元组就像它作用于列表和字符串等所有其他可迭代类型一样:
|
||
|
||
```py
|
||
>>> t = 1, 2, 3
|
||
>>> len(t)
|
||
3
|
||
```
|
||
|
||
## Python 元组 vs 列表
|
||
|
||
Python 元组和 Python 列表之间最显著的区别是,列表是可变的,而元组不是。定义元组后,不能添加或删除值。相比之下,列表允许您随意添加或删除值。这一特性可能是一个优势;你可以把它看作写保护。如果一段数据不打算改变,使用元组可以防止错误。毕竟,六个月后,您可能会忘记不应该更改数据。使用元组可以防止错误。
|
||
|
||
另一个好处是元组更快,或者至少人们是这么说的。我没有看到证据,但这是有道理的。因为它是不可变的数据类型,所以元组的内部实现可以比列表简单。毕竟,它们不需要扩大或在随机位置插入元素的方法,这通常是作为一个[链表](https://en.wikipedia.org/wiki/Linked_list)来实现的。根据我的理解,在 CPython 实现中,tuple 使用简单的类似数组的结构。
|
||
|
||
## Python 元组 vs 集合
|
||
|
||
元组和 [Python 集合](https://python.land/python-data-types/python-set-the-why-and-how-with-example-code)之间最显著的区别是元组可以有重复,而集合不能。集合的全部目的是它不能包含重复。这是消除重复数据的绝佳工具。
|
||
|
||
## 转换 Python 元组
|
||
|
||
### 将元组转换为列表
|
||
|
||
Python 列表是可变的,而元组不是。如果需要,可以用下列方法之一将元组转换为列表。
|
||
|
||
最干净、可读性最强的方法是使用`list()`构造函数:
|
||
|
||
```py
|
||
>>> t = 1, 2, 3
|
||
>>> list(t)
|
||
[1, 2, 3]
|
||
```
|
||
|
||
更简洁但可读性较差的方法是使用解包。这种解包有时会很方便,因为它允许您将多个元组解包到一个列表中,或者添加一些额外的值:
|
||
|
||
```py
|
||
>>> t = 1, 2, 3
|
||
>>> l = [*t]
|
||
>>> l
|
||
[1, 2, 3]
|
||
>>> l = [*t, 4, 5, 6]
|
||
>>> l
|
||
[1, 2, 3, 4, 5, 6]
|
||
```
|
||
|
||
### 将元组转换为集合
|
||
|
||
类似于列表的转换,我们可以使用`set()`将元组转换为集合:
|
||
|
||
```py
|
||
>>> t = (1, 2, 3)
|
||
>>> s = set(t)
|
||
>>> s
|
||
{1, 2, 3}
|
||
```
|
||
|
||
在这里,我们也可以使用解包:
|
||
|
||
```py
|
||
>>> s = {*t}
|
||
>>> s
|
||
{1, 2, 3}
|
||
```
|
||
|
||
### 将元组转换为字符串
|
||
|
||
像 Python 中的大多数对象一样,tuple 有一个所谓的 dunder 方法,称为`__str__`,它将 tuple 转换为一个字符串。当您想要打印一个元组时,您不需要显式地这样做。 [Python 的打印函数](https://python.land/introduction-to-python/python-print)会在任何不是字符串的对象上调用这个方法。在其他情况下,您可以使用`str()`构造函数来获取元组的字符串表示:
|
||
|
||
```py
|
||
>>> t = (1, 2, 3)
|
||
>>> print(t)
|
||
(1, 2, 3)
|
||
>>> str(t)
|
||
'(1, 2, 3)'
|
||
|
||
``` |