# 1.1.3 数据结构 数据结构:即人们抽象出来的描述现实世界实体的数学模型(非数值计算)及其上的操作(运算),在计算机上的表示和实现。 数据结构就是指按一定的逻辑结构组成的一批数据,使用某种存储结构将这批数据存储于计算机中,并在这些数据上定义了一个运算集合。 `Python`中内置了`4`种常用的数据结构,分别为:列表,元组,集合,字典。 ## 列表 ### 什么是列表 列表是最常用的`Python`数据类型,它可以作为一个方括号内的逗号分隔值出现。列表的数据项不需要具有相同的类型创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。 简单来说列表是由一系列元素按特定顺序排列组成。你可以创建包含字母表中所有字母、数字或一些字符串的列表;可以将其他数据类型放入列表中,甚至可以将另一个列表放在列表中。 在`Python`中,用方括号`[]`来表示列表,并用逗号来分隔其中的元素。例如: ```python >>>a = [] #创建一个空的列表 >>>b = [1,2,3,4] #创建一个含数字的大小为 4 的列表 >>>c = [1,'a',2,'b',3,'c',4,'d'] #创建包含多种数据类型的列表 >>>a = [b,c] #创建包含其他列表的列表 >>>print(a) [[1,2,3,4],[1,'a',2,'b',3,'c',4,'d']] ``` ### 如何访问列表中的元素 先可以考虑前面所学的字符串类型的数据访问,例如有一字符串:`"abcd"`。如果我们需要看它的某个特定位置上的字符是什么,则只要知道它的索引位置就行了,索引位置如下图: | 字符串 |a | b | c | d | | :-: | :-: | :-: | :-: | :-: | | 索引 -> | 0 | 1 | 2 | 3 | |索引 <-|0|-3|-2|-1| 计算机存储数据的位置都是从`0`号位置开始存储的,习惯使用从左往右进行访问,特殊情况可从右往左访问,即从`0`号位置开始,到`-1`号位置在最右边(最后)往左(前)访问。要访问上面那个字符串`"abcd"`中的字符`b`的话,我们可以用这样一种形式: ```python "abcd"[1] #或 "abcd"[-3] ``` 字符`b`的索引位置在字符串`"abcd"`中为`1`(或`-3`),所以可以通过加中括号`"[]"`(中括号内为索引位置)的形式访问。 通常我们习惯将这个字符串赋值给一个变量然后通过变量名进行操作: ```python >>> a = "abcd" >>> print(a[1]) #输出变量a储存的字符串索引位置为2的字符 b ``` 与字符串的索引一样,列表索引从`0`开始。列表可以进行截取、组合等。使用索引位置来访问列表中的值,同样你也可以使用方括号的形式访问索引位置,如下所示: ```python >>> list = ['physics', 'chemistry', 1997, 2000] >>> print(list[0]) physics >>> print(['physics', 'chemistry', 1997, 2000][0]) physics ``` 以上两种形式都可以访问列表`list`索引位置为`0`的数据`physics`,第一个通过变量间接访问,第二个是直接访问,形式均为: ``` 列表[索引位置] ``` 可见当一个变量被赋值为某种数据类型时,该变量就相应变为了赋值的数据类型。例如: ```python >>> a = 10 #此时a的数据类型为整数类型 >>> a = ['physics', 'chemistry'] #此时变为列表 >>> a[1] #对应 列表[索引位置] 的形式来访问特定位置 ``` 若要继续访问列表`['physics', 'chemistry']`中元素字符串`physics`的某个位置上的字符,可继续采用后面加`[]`的形式,例如: ```python >>> a = 10 #此时a的数据类型为整数类型 >>> a = ['physics', 'chemistry'] #此时变为列表 >>> print(a[0]) #打印第一个元素(这里为字符串) physics >>> print(a[0][1]) #打印第一个元素的第二个位置上的字符 h ``` 注意`[]`内的索引数字大小必须小于要访问元素长度,例如:`a = ['physics', 'chemistry']` 以`a[x]`访问列表元素,则`x`要小于列表元素个数`2`并且要大于`-3`,以`a[x][y]`访问列表元素(这里是字符串,单个数据元素不用此操作)内的元素时,则`y`要小于列表元素里的元素长度,例如列表`0`号元素`physics`长度为`7`,则`y`小于`7`,且大于`-8`依次类推。 ### 列表的相关操作 列表的相关操作有以下几种:增加元素、删除元素、替换元素、列表运算符、列表内置函数 #### 增加元素 通过使用`append()`函数来在列表末尾处添加列表元素: ```python >>> list = [] #创建空列表 >>> list.append('Google') #使用append()添加元素 >>> list.append('Runoob') >>> print(list) ['Google', 'Runoob'] #结果 ``` 添加的元素按`append()`函数从上到下的先后顺序在列表中从左至右的顺序存放。 #### 删除元素 通过使用`pop()`函数来删除列表末尾处的列表元素: ```python >>> list = ['Google', 'Runoob'] >>> list.pop() >>> print(list) ['Google'] ``` 这里需要注意的是`pop()`函数也可以通过指定索引位置来删除列表特定位置的数据,例如: ```python >>> list = ['Google', 'Runoob'] >>> list.pop(0) >>> print(list) ['Runoob'] ``` 还可以使用`remove()`函数来删除指定的内容: ```python >>> list = ['Google', 'Runoob'] >>> list.remove('Google') >>> print(list) ['Runoob'] ``` 两种方式都可以将列表中的元素删除,可在不同情形下使用。 #### 替换元素 如果想要改变一个有数据的列表某个特定位置上的数据,我们可以通过类似赋值的方式进行: ```python >>> list = ['Google', 'Runoob'] >>> list[0] = "Baidu" >>> print(list) ['Baidu', 'Runoob'] ``` #### 列表运算符 与字符串一样,列表之间可以使用 + 号和 * 号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的列表。 |Python 表达式| 结果| 描述| | :-: | :-: | :-: | |len([1, 2, 3])| 3| 计算元素个数| |[1, 2, 3] + [4, 5, 6]| [1, 2, 3, 4, 5, 6]| 连接| |['Hi!',] * 4| ['Hi!', 'Hi!', 'Hi!', 'Hi!']| 复制| |3 in [1, 2, 3]| True| 元素是否存在| #### 列表内置函数 `Python`列表包含了以下内置函数 | 函数名 | 描述 | | :-: | :-: | | len(list)|计算列表元素个数。| | max(list)|返回列表中元素最大值。| | min(list)|返回列表中元素最小值。| | list(str)|将字符串转换为列表。| ```python #使用逗号运算符给多个变量赋值 t1,t2 = [10,30,50],[20,30,50] print(len(t1)) print(min(t2)) print(max(t1)) #创建一个字符串a a = "abcd" print(list(a)) ``` 以上实例输出结果: ```pyhton 3 20 50 ['a','b','c','d'] ``` ## 元组 `Python`的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。 ### 创建元组 ```python tup1 = () ``` 元组中只包含一个元素时,需要在元素后面添加逗号,避免与括号运算符混淆。 ```python tup1 = (50,) ``` 与列表一样,元组的创建也可以嵌套进行。 ```pyhton tup = (1,2,3,"abc",(1,2,3,"abc"),[1,2,3,"abc"]) ``` ### 访问元组 与列表一样元组可以使用索引位置来访问元组中的值,如下实例: ```python tup1 = ('physics', 'chemistry', 1997, 2000) tup2 = (1, 2, 3, 4, 5, 6, 7 ) print("tup1[0]: ", tup1[0]) print("tup2[-1]: ",tup2[-1]) ``` 以上实例输出结果: ```python tup1[0]: physics tup2[-1]: 7 ``` 嵌套的元组访问元素与列表一样,通过再后面添加中括号的形式。 ```python tup = (1,2,3,"abc",(10,20,30)) print("tup[3][1]: ",tup[3][1]) print("tup[4][0]: ",tup[4][0]) ``` 以上实例输出结果: ```python tup[3][1]: b tup[4][0]: 10 ``` ### 修改元组 元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,如下实例: ```python tup1 = (12, 34.56) tup2 = ('abc', 'xyz') # 以下修改元组元素操作是非法的。 # tup1[0] = 100 # 创建一个新的元组 tup3 = tup1 + tup2 print(tup3) ``` 以上实例输出结果: `(12, 34.56, 'abc', 'xyz')` ### 元组运算符 与列表一样,元组之间可以使用`+`号和`*`号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。 |Python 表达式| 结果| 描述| | :-: | :-: | :-: | |len((1, 2, 3))| 3| 计算元素个数| |(1, 2, 3) + (4, 5, 6)| (1, 2, 3, 4, 5, 6)| 连接| |('Hi!',) * 4| ('Hi!', 'Hi!', 'Hi!', 'Hi!')| 复制| |3 in (1, 2, 3)| True| 元素是否存在| ### 元组内置函数 `Python`元组包含了以下内置函数 | 函数名 | 描述 | | :-: | :-: | | len(tuple)|计算元组元素个数。| | max(tuple)|返回元组中元素最大值。| | min(tuple)|返回元组中元素最小值。| | tuple(list)|将列表转换为元组。| ```python #使用逗号运算符给多个变量赋值 t1,t2 = (10,30,50),(20,30,50) print(len(t1)) print(min(t2)) print(max(t1)) #创建一个列表a a = [1,2,3] print(tuple(a)) ``` 以上实例输出结果: ```pyhton 3 20 50 (1,2,3) ``` ## 集合 集合(`set`)与数学意义相同,是一个无序的元素不重复的序列。 我们可以使用大括号 `{ }` 或者`set()`函数创建集合,注意:创建一个空集合必须用`set()`而不是 `{ }`,因为 `{ }` 是用来创建一个空字典。 创建格式: `parame = {value01,value02,...}` 或者: `set(value)` ```python >>> a = {'apple', 'orange', 'pear'} >>> a {'apple', 'orange', 'pear'} >>> s = set() #使用set()创建一个空的集合 ``` ### 集合去重 重复元素在`set`中自动被过滤,即去重功能: ```python >>> fruit = {'apple', 'orange', 'apple', 'pear'} >>> print(basket) {'orange', 'pear', 'apple'} #集合是无序的 >>> s = set([1, 1, 2, 2, 3, 3]) #对列表去重 >>> s {1, 2, 3} ``` ###添加元素 通过`add(key)`方法可以添加元素到`set`中,可以重复添加,但不会有效果: ```python >>> s = {1,2,3,4} >>> s {1, 2, 3, 4} >>> s.add(4) #添加重复元素 4 >>> s {1, 2, 3, 4} ``` ###删除元素 通过`remove(key)`方法可以删除元素: ```python >>> s.remove(4) #删除元素 4而不是索引位置 4 >>> s {1, 2, 3} ``` ### 集合运算 两个`set`可以做数学意义上的交集、并集等运算: ```python >>> a = {1,2,3,4} >>> b = {4,5,6,7} >>> a - b # 只在集合a中包含元素 {1,2,3} >>> a | b # 集合a或b中包含的所有元素 {1,2,3,4,5,6,7} >>> a & b # 集合a和b中都包含了的元素 {4} >>> a ^ b # 不同时包含于a和b的元素 {1,2,3,5,6,7} ``` ### 常用操作 计算集合的大小可使用函数`len()` ```python >>> thisset = {"Google", "Runoob", "Taobao"} >>> len(thisset) 3 ``` 使用`in`判断元素是否在集合中: ```python >>>thisset = {"Google", "Runoob", "Taobao"} >>> "Runoob" in thisset True >>> "Facebook" in thisset False ``` ## 字典 字典是`Python`最强大的数据类型之一,通过`键-值(key-value)对`的方式建立数据对象之间的映射关系。字典的每个键-值对用冒号`:`分割,每个`键-值对`间用逗号`,`分隔开,字典是包含在`{}`中。 每个**键**都与一个值相关联,我们可以使用键来访问与之相关联的值。与**键**相关联的值可以是数字、字符串、列表乃至字典。事实上,可将任何`Python`对象用作字典中的值。 ### 创建字典 字典的创建格式如下所示: `d = {key1 : value1, key2 : value2 }` **键**必须是唯一的,但值则不必。 值可以取任何数据类型,但`键`必须是不可变的,如字符串,数字或元组。 一个简单的字典实例: ```python >>> dict = {'Alice': '2341', 'Beth': '9102'} >>> print(dict) {'Alice': '2341', 'Beth': '9102'} ``` ### 访问字典中的值 要获取与`键`相关联的值,可依次指定字典名和放在方括号内的`键`。我们访问列表等其他类型是通过方括号`[]`内添加索引位置的形式,这里字典我们把索引位置用字典中的`键(key)`来代替。 把相应的键放入到方括号中(`name[key]`): ```python >>> dict = {'Name': 'Runoob', 'Age': 7} >>> print ("dict['Name']: ", dict['Name']) dict['Name']: Runoob >>> print ("dict['Age']: ", dict['Age']) dict['Age']: 7 ``` ### 添加元素 字典是一种动态数据结构,可随时在字典中添加**键—值对**。要添加**键—值对**时,可依次指定字典名、**键**和**键**对应的值。 下面在字典`menu`中添加两道菜的菜名和价格: ```python >>> #coding=utf-8 #创建并初始化menu字典 >>> menu = {'鱼':40, '猪肉':30, '番茄':15, '拉面':10} #向menu字典中添加菜名和价格 >>> menu['果汁'] = 12 >>> menu['煎蛋'] = 2 ######输出新的menu >>> print(menu) {'鱼': 40,'猪肉': 30,'番茄': 15,'拉面': 10, '果汁': 12,'煎蛋': 2} ``` 新的`menu`字典包含`6`个`键-值对`,新增加的两个`键-值对`(菜名和对应价格)添加在了原有`键-值对`的后面,注意字典中`键-值对`的排列顺序和添加顺序没有必然联系,Python 不关心字典中`键-值对`的排列顺序,而只关心键与值得对应关系。 同理,字典和列表一样,可以先创建一个空字典,然后可以不断向里面添加新的键-值对。 ### 修改元素 字典和列表一样,里面的值都是可以修改的。要修改字典中的值,可直接指定字典中的键所对应的新值。例如,将`menu`中的`fish`价格改为`50`。 ```python >>> #coding = utf-8 #创建并初始化menu字典 >>> menu = {'鱼':40, '猪肉':30, '番茄':15, '拉面':10} # 修改menu字典中菜fish的价格 >>> menu['鱼'] = 50 # 打印输出新的menu >>> print(menu) {'鱼': 50, '猪肉': 30, '番茄': 15, '拉面': 10} ``` ### 删除元素 我们可以通过`del`方法删除字典中不需要的`键-值对`,使用`del`方法时,要指定字典名和要删除的`键`。 例如,在`menu`菜单中删除键`noodles`和它的值。 ```python ###### 创建并初始化menu字典 >>> menu = {'鱼':40, '猪肉':30, '番茄':15, '拉面':10} ###### 删除noodles键值对 >>> del menu['拉面'] ###### 打印输出新的menu >>> print(menu) {'鱼':40, '猪肉':30, '番茄':15} ```