6.1组合数据类型概述
组合数据类型为多个同类型或不同类型数据提供单一表示。
组合数据类型分3类:序列类型、集合类型和映射类型。
-
序列类型:一个元素向量,元素之间存在先后关系,通过序号访问,元素之间不排他。
-
集合类型:一个元素集合,元素之间无序,相同元素在集合中唯一存在。
-
映射类型:“键-值”数据项的组合,每个元素是一个键值对,表示为(key,value)。
6.1.1 序列类型
序列类型是一位元素向量,元素之间存在先后关系,通过序号访问。本思想和表示方法均来源于数学概念。
由于元素之间存在顺序关系,所以序列中可以存在数值相同但位置不同的元素。序列类型支持成员关系操作符(in)、长度计算函数(len())、分片([]),元素本身也可以是序列类型。
Python语言中有很多数据类型都是序列类型,其中比较重要的是str(字符串)、tuple(元组)和list(列表)
-
字串符(str):可以看成是单一字符的有序组合,属于序列类型。同时,由于字符串类型十分常用且单一字符串只表达一个含义,也被看作是基本数据类型。
-
元组(tuple): 包含0个或多个数据项的不可变序列类型。元组生成后是固定的,其中任何数据项不能替换和删除。
-
列表(list): 是一个可以修改数据项的序列类型,使用也最灵活。
无论哪种具体数据类型,只要它是序列类型,都可以使用相同的索引体系,即正向递增序号和反向递减序号,如图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hj5vg7KY-1593708813494)(第6章组合数据类型/1.jpg)]
序列类型有12个通用的操作符和函数:
操作符 | 描述 |
---|---|
x in s | 如果x是s的元素,返回True,否则返回False |
x not in s | 如果x不是s的元素,返回True,否则返回False |
s+t | 连接s和t |
s * n 或 n * s | 将序列s复制n次 |
s[i] | 索引,返回序列的第一个元素 |
s[i:j] | 分片,返回包含序列s第i到j个元素的子序列(不包含第j个元素) |
s[i:j:k] | 步骤分片,返回包含序列s第i到j个元素以k为步数的子序列 |
len(s) | 序列s的元素个数(长度) |
min(s) | 序列s中的最小元素 |
max(s) | 序列s中的最大元素 |
s.index(x[,i[,j]]) | 序列s中从i开始到j位置中第一次出现元素x的位置 |
s.count(x) | 序列s中出现x的总次数 |
元组(tuple):它一旦创建就不能被修改。元组类型在表达固定数据项、函数多返回值、多变量同步赋值、循环遍历等情况下十分有用。Python中元组采用逗号和圆括号(可选)来表示。一个元组可以作为另外一个元组的元素,可以采用多级索引获取信息。例如:
>>>creature = "cat", "dog", "tiger", "human"
>>>creature
('cat', 'dog', 'tiger', 'human')
>>>color = ("red", 0x001100, "blue", creature)
>>>color
('red', 4352, 'blue', ('cat', 'dog', 'tiger', 'human'))
>>>color[2]
'blue'
>>>color[-1][2]
'tiger'
元组除了用于表达固定数据项外,还常用于如下3种情况:函数多返回值、多变量同步赋值、循环遍历。例如:
>>>def func(x): #函数多返回值
return x, x**3
>>>a, b = 'dog', 'tiger' #多变量同步赋值
>>>a, b = 'b, a' #多变量同步赋值,括号可省略
>>>import math
>>>for x,y in ((1,0),(2,5),(3,8)): #循环遍历
print(math.hypot(x,y)) #求多个坐标值到原点的距离
6.1.2 集合类型
集合类型与数学中集合的概念一致,即包含0个或多个数据项的无序组合。集合中的元素不可重复,元素类型只能是固定数据类型,例如整数、浮点数、字符串、元组等,列表、字典和集合类型本身都是可变数据类型,不能作为集合的元素出现。Python编译器中界定固定数据类型与否主要考察类型是否能够进行哈希运算。能够进行哈希运算的类型都可以作为集合元素。Python提供了一种同名的具体数据类型——集合(set)。
** 哈希运算 **可以将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制称为哈希值。哈希值是对数据的一张有损且紧凑的表示形式。Python提供了一个内置的哈希运算函数hash()
,它可以对大多数数据类型产生一个哈希值。哈希是数据在另一个数据维度的体现,例如:
>>>hash("PYTHON")
-924726778
>>>hash("lS")
1964309299
>>>hash("GOOD")
1808989930
>>>hash("PYTHON IS GOOD")
-775775176
由于集合是无序组合,它没有索引和位置的概念,不能分片,集中元素可以动态增加或删除。集合用大括号({})表示,可以用赋值语句生成一个集合。由于集合元素是无序的,集合的打印效果与定义顺序可以不一致。由于集合元素独一无二,使用集合类型能够过滤掉重复元素。例如:
>>>S = {425, "BIT", (10, "CS"), 424}
>>>S
{424, 425, (10, 'CS'), 'BIT'}
>>>T = {425, "BIT", (10, "CS"), 424, 425, "BIT"}
>>>T
{424, 425, (10, 'CS'), 'BIT'}
set(x)
函数可以用于生成集合,输入的参数可以是任何组合数据类型,返回结果是一个无重复且排序任意的集合,例如:
>>>W = set("apple")
{'e', 'p', 'a', '1'}
>>>V = set(("cat", "dog", "tiger", "human"))
{'cat', 'human', 'dog', 'tiger'}
集合类型有10个操作符,如表6.2所示:
操作符 | 描述 |
---|---|
S-T 或 S.difference(T) | 返回一个新集合,包括在集合S中但不在集合T中的元素 |
S-=T 或 S.difference_update(T) | 更新集合S,包括在集合S中但不在集合T中的元素 |
S&=T 或 S.intersection_update(T) | 更新集合S,包括同时在集合S和T中的元素 |
S^T 或 s.symmetric_difference(T) | 返回一个新集合,包括集合S和T中的元素,但不包括同时在其中的元素 |
S^=T 或 s.symmetric_difference_update(T) | 更新集合S,包括集合S和T中的元素,但不包括同时在其中的元素 |
S|T 或 S.union(T) | 返回一个新集合,包括集合S和T中的所有元素 |
S=T 或 S.update(T) | 更新集合S,包括集合S和T中的所有元素 |
S<=T 或 S.issubset(T) | 如果S与T相同或S是T的子集,返回True,否则返回False,可以用S<T判断S是否是T的真子集 |
S>=T 或 S.issuperset(T) | 如果S与T相同或S是T的超集,返回True,否则返回False,可以用S>T判断S是否是T的真超集 |
上述操作符表达了集合类型的4种基本操作:交集(&)、并集(|)、差集(-)、补集(^),操作逻辑与数学定义相同。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g87rnjFd-1593708813496)(第6章组合数据类型/2.png)]
集合类型有10个操作函数或方法,如表6.3所示
操作函数或方法 | 描述 |
---|---|
S.add(x) | 如果数据项x不在集合S中,将x增加到s |
S.clear() | 移除S中的所有数据项 |
S.copy() | 返回集合S的一个副本 |
S.pop() | 随机返回集合S中的一个元素,如果S为空,产生KeyError异常 |
S.discard(x) | 如果x在集合S中,移除该元素;如果x不在集合S中,不报错 |
S.remove(x) | 如果x在集合S,移除该元素;不在则产生KeyError异常 |
S.isdisjoint(T) | 如果集合S与T没有相同元素,返回True |
len(S) | 返回集合S的元素个数 |
x in S | 如果x是S的元素,返回True,否则返回False |
x not in S | 如果x不是S的元素,返回True,否则返回False |
集合类型主要用于3个场景:成员关系测试、元素去重和删除数据项,例如:
>>>"BIT" in {"PYTHON", "BIT", 123, "GOOD"} # 成员关系测试
True
>>>tup = ("PYTHON", "BIT", 123, "GOOD", 123) # 元素去重
>>>set(tup)
{123, 'GOOD', 'BIT', 'PYTHON'}
>>>newup = tuple(set(tup)-{'PYTHON'}) # 去重同时删除数据项
{'GOOD', 123, 'BIT'}
集合类型与其他类型最大的不同在于它不包含重复元素,因此,当需要对一维数据进行去重或进行数据重复处理时,一般通过集合来完成。
6.1.3 映射类型
映射类型是“键-值”数据项的组合,每个元素是一个键值对,即元素是(key,value),元素之间是无序的。键值对(key,value)是一种二元关系,源于属性和值得映射关系,对应实例
6.2.2 列表类型的操作
函数或方法 | 描述 |
---|---|
ls[i]=x | 替换列表ls第i数据项为x |
ls[i:j]=lt | 用列表lt替换列表ls中第i到第j项数据**(不含第j项,下同)** |
ls[i:j:k]=lt | 用列表lt替换列表ls中第i到第j项以k为步数的数据 |
del ls[i:j] | 删除列表ls第i到第j项数据,等价于ls[i:j]=[] |
del ls[i:j:k] | 删除列表ls第i到第j项以k为步数的数据 |
ls+=lt 或 ls.extend(lt) | 将列表lt元素增加到列表ls中 |
ls * = n | 更新列表ls,其元素重复n次 |
ls.append(x) | 在列表ls最后增加一个元素x |
ls.clear() | 删除ls中的所有元素 |
ls.copy() | 生成一个新列表,复制ls中的所有元素 |
ls.insert(i.x) | 在列表ls的第i位置增加元素x |
ls.pop(i) | 将列表ls中的第i项元素取出并删除该元素 |
ls.remove(x) | 将列表中出现的第一个元素x删除 |
ls.reverse() | 列表ls中的元素反转 |
>>> vlist = list(range(5))
>>> vlist
[0, 1, 2, 3, 4]
>>> len(vlist[2:]) # 计算从第3个位置开始到结尾的子串长度
3
>>> 2 in vlist # 判断2是否在列表vlist中
True
>>> vlist[3]="PYTHON" # 修改序号3的元素值和类型
>>> vlist
[0, 1, 2, 'PYTHON', 4]
>>> vlist[1:3]=["bit","computer"]
>>> vlist
[0, 'bit', 'computer', 'PYTHON', 4]
# 当使用一个列表改变另一个列表值时,python不要求两个列表长度一样,但遵循”多增少减“的原则
>>> vlist[1:3]=["new_bit","new_computer",123]
>>> vlist
[0, 'new_bit', 'new_computer', 123, 'PYTHON', 4]
>>> vlist[1:3]=["fewer"]
>>> vlist
[0, 'fewer', 123, 'PYTHON', 4]
与元组一样,列表可以通过for-in语句对其元素进行遍历,基本语法结构如下:
for <任意变量名> in <列表名>:
<语句块>
>>>for e in vlist:
print(e,end="")
0 fewer 123 python 4
6.4 字典类型和操作
要点: 字典是包含0个或多个键值对的集合,没有长度限制,可以根据检索引值的内容。
6.4.1 字典类型的概念
- 字典是Python中唯一内建的映射类型,可以用来实现通过数据查找关联数据的功能。
- Python字典中的值没有特殊的顺序,是无序集合,不能像序列那样通过位置索引来查找成员数据。
- 字典的显示次序由字典在内部的存储结构决定
- 字典每一值都有一个对应的键。字典的用法是通过键key来访问相应的值value。
列表是存储和检索数据的有序序列。当访问列表中的元素时,可以通过整数索引来查找它,这个索引是元素在列表中的序号,列表的索引模式是“<整数序号>查找<被索引内容>”。
在编程术语中,根据一个信息查找另一个信息的方式构成了“键值对”,它表示索引用的键和对应的值构成的成对关系,即通过一个特定的键(身份证号码)来访问值(学生信息)。实际应用中有很多“键值对”的例子,例如,姓名和电话号码、用户名和密码、邮政编码和运输成本、国家名称和首都等。由于键不是序号,无法使用列表类型进行有效存储和索引。
通过任意键信息查找一组数据中值信息的过程叫映射,Python语言中通过字典实现映射。Python语言中的字典可以通过大括号({})建立,建立模式如下:
键和值通过冒号连接,不同键值对通过逗号隔开。从Python设计角度考虑,由于大括号{}可以表示集合,因此字典类型也具有和集合类似的性质,即键值对之间没有顺序且不能重复。简单说,可以吧字典看成元素是键值对的集合。
- 键可以是任何不可修改类型的数据,如数值、字符串和元组等,键要唯一;
- 键对应的值,可以是任何类型的数据。
>>>Dcountry={"中国":"北京","美国":"华盛顿","法国":"巴黎"}
>>>print(Dcountry)
{'中国':'北京','美国':'华盛顿','法国':'巴黎'}
字典打印出来的顺序与创作之初的顺序不同,这不是错误。字典是集合类型的延续,所以各个元素并没有顺序之分。如果想要保持一个集合元素的顺序,需要使用列表,而不是字典。
字典最主要的用法是查找与特定键相对应的值,这通过索引符号来实现。例如:
>>>Dcountry["中国"]
'北京'
一般来说,字典中键值对的访问模式如下,采用中括号格式:
>>>Dcountry["中国"]='大北京'
>>>print(Dcountry)
{'中国': '大北京','法国': '巴黎','美国': '华盛顿'}
Python语言中,字符串、列表、元组等都采用数字索引,字典采用字符索引。
>>> country={12:'Australia',(2,3):'China','DE':'Germany','SG':"Singapore"}
>>> country
{12: 'Australia', (2, 3): 'China', 'DE': 'Germany', 'SG': 'Singapore'}
>>> country={}
>>> country
{}
用dict函数创建:
dict([(键1,值1),(键2,值2),...])
>>> a=dict([("name","limin"),("age",18)])
>>> a
{'name': 'limin', 'age': 18}
6.4.2 字典类型的操作
- 字典最主要的用法是查找与特定键相对应的值,这通过索引符号来实现。
- 变量[键]:查找与特定键相关联的值。如果指定的键在字典中不存在,则报错。
- 对变量[键]赋值,修改字典中的数据,若指定的键不存在,相当于向字典中添加新的键值对。
与列表相似,Python字典也有非常灵活的操作方法。使用大括号可以创建字典,并指定初始值,通过中括号可以增加新的元素,例如:
>>>Dcountry=["中国":"北京", "美国": "华盛顿", "法国": "巴黎"]
>>>Dcountry=["英国"]="伦敦"
print(Dcountry)
{"中国":"北京","法国": "巴黎","美国": "华盛顿", '英国',"伦敦"}
>>>Dcounty["日本"]
报错
直接使用大括号({})可以创建一个空的字典,并通过中括号([])向其增加元素,例如:
>>>Dp={}
>>>Dp['2^10']=1024
>>>print(Dp)
{'2^10': 1024}
需要注意的是,尽管集合类型也是有用大括号表示,直接使用大括号({})生成一个空的字典,而不是集合。生成空集合需要使用函数set()。
函数和方法 | 描述 |
---|---|
<d>.keys() | 返回所有的键信息 |
<d>.values() | 返回所有的值信息 |
<d>.items() | 返回所有键值对 |
<d>.get(<key>,<default>) | 键存在则返回相应值,否则返回默认值 |
<d>.setdefault(<key>,<value>) | 键存在返回相应值,否则添加元素 |
<d>.pop(<key>,<default>) | 键存在则返回相应值,同时删除键值对,否则返回默认值 |
<d>.popitem() | 随机从字典中取出一个键值对,以元组(key,value)形式返回 |
<d>.clear() | 删除所有的键值对 |
del <d>[<key>] | 删除字典中某个键值对 |
<key> in <d> | 如果键在字典中则返回True,否则返回False |
如果希望keys()、values()、items()方法返回列表类型,可以采用list()函数将返回值转换成列表:
>>>Dcountry={"中国":"北京","美国":"华盛顿","法国":"巴黎"}
>>>Dcountry.keys()
dict_keys(['中国', '美国', '法国'])
>>> list(Dcountry.values())
['北京', '华盛顿', '巴黎']
>>> Dcountry.items()
dict_items([('中国', '北京'), ('美国', '华盛顿'), ('法国', '巴黎')])
>>> '中国' in Dcountry #只对键进行判断
True
>>> Dcountry.get('美国','悉尼') #'美国'在字典中存在
'华盛顿'
>>> Dcountry.get('澳大利亚','悉尼') # '澳大利亚'在字典中不存在则返回后面那个
'悉尼'
>>> Dcountry.setdefault('英国','伦敦') # 键存在返回相应值,否则添加元素
'伦敦'
>>> Dcountry
{'中国': '北京', '美国': '华盛顿', '法国': '巴黎', '英国': '伦敦'}
>>> Dcountry.pop('英国')
'伦敦'
>>> Dcountry.popitem()
('法国', '巴黎')
>>> Dcountry
{'中国': '北京', '美国': '华盛顿'}
>>> del Dcountry['美国']
>>> Dcountry
{'中国': '北京'}
>>> Dcountry.clear()
>>> Dcountry
{}
>>> del Dcountry
于其他组合数类型一样,字典可以通过for...in
语句对其元素进行遍历,基本语法结构如下:
for <变量名> in <字典名>:
语句块
例如:
a={"中国":"北京","美国":"华盛顿","法国":"巴黎"}
for i in a:
print(i)
###运行结果:
中国
美国
法国
思考:si6_4:
编写程序,输入两个分别包含若干整数的列表list1和list2。用list1元素作为键,用list2作为值,产生一个字典。该字典的元素个数为list1和list2元素较少的那个列表长度,输出该字典。
请输入list1:3,5,6,2,7,346
请输入list2:4,6,345,65,54,5,2,7
{3:4,5:6,6:345,2:65,7:54,346:5}
解:
list1=eval(input("请输入list1:"))
list2=eval(input("请输入list2:"))
c=dict(zip(list1,list2))
print(c)
思考si6_5.py
文件里dict1变量保存的是学生健康打卡信息,请在##==之间输入代码。
dict1={'张三三':[{'日期':'4月30日','省份':'福建','城市':'福州','是否健康':'是','是否接触过疑似病例':'否'},\
{'日期':'5月1日','省份':'福建','城市':'福州','是否健康':'是','是否接触过疑似病例':'否'}], \
'李四四':[{'日期':'4月30日','省份':'福建','城市':'三明','是否健康':'是','是否接触过疑似病例':'否'},\
{'日期':'5月1日','省份':'福建','城市':'三明','是否健康':'是','是否接触过疑似病例':'否'}],
'王五五':[{'日期':'4月30日','省份':'福建','城市':'泉州','是否健康':'是','是否接触过疑似病例':'否'},\
{'日期':'5月1日','省份':'福建','城市':'泉州','是否健康':'是','是否接触过疑似病例':'否'}], \
}
name=input('请输入姓名:')
date=input('请输入日期:')
tempdata=dict1.get(name,'不存在')
if tempdata=='不存在':
print(name+'不存在')
else:
for i in tempdata:
if i['日期']==date:
print(i)
break
else:
print("今日未打卡")
6.5 模块4: jieba库的使用
6.5.1 jieba库概述
对于一段英文文本,例如“China is a great country”,如果希望提取其中的单词,只需要使用字符串处理的split()方法即可,例如:
>>> "China is a great country".split()
['China', 'is', 'a', 'great', 'country']
然而,对于一段中文文本,例如“中国是一个伟大的国家”,获得其中的单词(不是字符)十分困难,因为英文文本可以通过空格或标点符号分隔,而中文单词之前缺少分隔符,这是中文及类似语言独有的“分词”问题。上例中,分词能够将”中国是一个伟大的国家“分为”中国“、”是”、“一个“、”伟大“、”的“、”国家“等一系列词语。
jieba(”结巴“)是Python中一个重要的第三方中文分词函数库,例如:
>>> import jieba
>>> jieba.lcut("中国是一个伟大的国家")
['中国', '是', '一个', '伟大', '的', '国家']