6. 数据类型 —— 元组

元组属于容器存储、不可变、顺序访问的数据类型。元组可以看作是不可变的列表,除了这一点外元组和列表的特征十分相似。

1. 创建元组

元组使用 ( ) 来定义,直接把一个被 ( ) 包含,由 , 分隔的数据赋值给一个变量即可创建元组对象。

>>> tup = (1, 2, 3)                                 # 通过直接将由圆括号 () 括起来的对象赋值给变量创建元组
>>> tup
(1, 2, 3)
>>> tup = (1, )                                     # 如果元组对象中只有一个元素时,必须在元素后添加一个 ',' 否则不会创建元组
>>> tup
(1, )
>>> tup = (1, 'a', [1])                             # 和列表一样,元组的元素可以是任何数据类型
>>> tup
(1, 'a', [1])

元组同样可以使用 tuple() 函数来创建元组对象

>>> tup = tuple([1, 2, 3])
>>> tup
(1, 2, 3)

2. 元组的基本操作

  • 访问元组中的元素

    元素属于顺序访问的序列类型,因此可以通过索引和切片操作对元组中的元素进行访问

tup = (1, 2, 3, 4, 5, 6, 7)
tup[0] # 元组索引和字符串一样,从 0 开始,最大为列表的长度 - 1
1
tup[-1] # 使用负索引访问元组元素
7
tup[1:3] # 元组的切片操作返回一个包含元组部分元素的新的元组
(2, 3)
tup[::-1] # 反序访问元组
(7, 6, 5, 4, 3, 2, 1)
tup = ([1, 2, 3],)
tup[0][1] # 元组中嵌套的任意序列数据类型的访问,注意元组中只有一个元素时,元素后边要加 ','
2
```

  • 元组不可变性

    元组中的元素一般来说是不可以改变的,但由于元组中可以包含列表、字典等其他数据类型,而这些数据类型中的元素是可以改变的,因此在这种情况下元组发生了 "改变"。元组的不可变性仅适用于元组本身元素顶层,而非其元素的内容

>>> tup = ([1, 2, 3], )
>>> tup[0][1] = 7                                    # 改变元组中列表元素的值,可以在 "改变" 元组
>>> tup
([1, 7, 3])
>>> tup[0] = 1                                       # 如果直接更改元组的元素会引发一个 TypeError 异常
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

3. 元组的一些操作符和函数

元组属于序列数据类型,因此大部分序列操作和函数适用于元组,但由于元组的不可变性,一些需要对序列对中元素进行修改的函数并未对元组进行实现。

操作符
  • + 操作符:对元组使用 + 操作符可以将两个元组连接在一起创建一个新的元组

(1, 2) + (3, 4)
(1, 2, 3, 4) # 直接生成一个新的元组而并非对原元组进行修改
```

  • * 操作符:使用 * 操作符可以将元组重复 N 次

(1, ) * 7
(1, 1, 1, 1, 1, 1, 1)
```

  • innot in:成员关系操作,测试对象是否是元组的元素

tup = (1, 2, 3)
1 not in tup
False
1 in tup
True
```

函数

元组很像列表,但由于元组的不可变性,因此在进行绝大多数函数操作时,首先将元组转换为列表,然后继续后边的操作。

>>> tup = (3, 1, 2)
>>> li = list(tup)                                    # 首先将元组转换为列表
>>> li.sort()                                         # 对列表进行排序
>>> tup = tuple(li)                                   # 将排好序的列表转化为元组
>>> tup
(1, 2, 3) 

元组仅有的两个方法 indexcount,这两个方法对元组跟对列表一样

>>> tup = (1, 2, 3, 1)
>>> tup.index(1)
0
>>> tup.count(1)
2

4. 元组的意义

元组的意义在于它的不可变性。一个元组对象的值不会发生改变,也就意味着它们可以通过 hash 算法得到的值时固定的。因此元组可以作为字典的键。这是元组的一个典型应用场景,通常来说,元组用在需要确保数据不会被修改的时候。

参考:
Tuple

复制对象 —— 浅复制和深复制

当我们为变量进行赋值时,只是创建了对对象的引用,而不是将对象进行复制。当将其赋值给另外一个变量时,也并没有复制这个对象,而是复制了引用。

>>> a = 1
>>> id(a)
8109160
>>> b = a
>>> id(b)
8109160                             # 变量 a 和变量 b 指向同一个对象 

使用切片操作和函数进行对象的复制

>>> li = [1, [2, 3]]
>>> a = li[:]                      # 使用切片操作对 li 进行复制
>>> b = list(li)                   # 使用 list() 函数对 li 进行复制
>>> a[0] = 7                    
>>> a
[7, [2, 3]]                        # 修改了 a 的第一个元素
>>> b 
[1, [2, 3]]                        # 并没有对 b 造成改变
>>> a[1][0] = 8
>>> a
[7, [8, 3]]                        # 将 a 中的列表元素中的元素值进行修改
>>> b
[1, [8, 3]]                        # b 中列表元素同样发生了改变

发生上述情况的原因在于浅复制。对一个对象进行浅复制创建了一个新的对象,但对象的内容是对原来对象内容的引用。

>>> id(a[1])
139969576313056
>>> id(b[1])
139969576313056                    # 变量 a 和 b 对应的列表元素指向同一个对象,因此同时发生了改变
>>> id(a[0])
8109016
>>> id(b[0])
8109160                           # 由于数字、字符串等是不可变类型,因此改变该元素即赋值了一个新的对象 

使用浅复制的方法:1)切片操作 [:];2)list()、dict() 等函数;3)使用 copy 模块中的 copy 函数

如果需要得到一个完全不同的复制,需要使用 copy 的 copy.deepcopy() 函数,即深复制

>>> import copy
>>> a = li
>>> b = copy.deepcopy(li)
>>> id(a[1])
139969576313056
>>> id(b[1])
139969576369112                    # a、b 中的列表元素为不同的引用
  • 浅复制和深复制只是针对除元组以外的容器数据类型。

你可能感兴趣的:(6. 数据类型 —— 元组)