4.常用数据结构-字符串、元组、列表、字典、集合
一、序列(sequence)
- 序列是Python中最基本的一种数据结构
- 数据结构指计算机中数据存储的方式
- 序列用于保存一组有序的数据,所有的数据在序列当中都有一个唯一的位置(索引)
- 并且序列中的数据会按照添加的顺序来分配索引
- 序列都可以进行的操作包括索引,切片,加,乘,检查成员。
- Python已经内置确定序列的长度以及确定最大和最小的元素的方法。
- 序列的分类:
- 可变序列(序列中的元素可以改变):
- > 列表(list)
- 不可变序列(序列中的元素不能改变):
- > 字符串(str)
- > 元组(tuple)
- 可变序列(序列中的元素可以改变):
二、字符串
2.1 创建字符串
创建字符串很简单,只要为变量分配一个值即可
var1 = 'Hello World!' var2 = "Runoob"
2.2 字符串切片
通过字符串索引下标来进行访问
#!/usr/bin/python3 var1 = 'Hello World!' var2 = "Runoob" print ("var1[0]: ", var1[0]) print ("var2[1:5]: ", var2[1:5]) #结果 var1[0]: H var2[1:5]: unoo
2.3 字符串运算符
2.4 字符串格式化
常用几种方式:
①字符串格式化符号
②format格式化
例如:
#!/usr/bin/python3 #①字符串格式化 print ("我叫 %s 今年 %d 岁!" % ('小明', 10)) #②.format() print("我叫 {0} 今年 {1} 岁!" .format ('小明', 10)) #结果 #我叫 小明 今年 10 岁!
2.5 字符串常用内建函数
菜鸟教程:https://www.runoob.com/python3/python3-string.html
常用的:strip()、split()、join()、find()
def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的拷贝 print(str1.capitalize()) # Hello, world! # 获得字符串变大写后的拷贝 print(str1.upper()) # HELLO, WORLD! # 从字符串中查找子串所在位置 print(str1.find('or')) # 8 print(str1.find('shit')) # -1 # 与find类似但找不到子串时会引发异常 # print(str1.index('or')) # print(str1.index('shit')) # 检查字符串是否以指定的字符串开头 print(str1.startswith('He')) # False print(str1.startswith('hel')) # True # 检查字符串是否以指定的字符串结尾 print(str1.endswith('!')) # True # 将字符串以指定的宽度居中并在两侧填充指定的字符 print(str1.center(50, '*')) # 将字符串以指定的宽度靠右放置左侧填充指定的字符 print(str1.rjust(50, ' ')) str2 = 'abc123456' # 从字符串中取出指定位置的字符(下标运算) print(str2[2]) # c # 字符串切片(从指定的开始索引到指定的结束索引) print(str2[2:5]) # c12 print(str2[2:]) # c123456 print(str2[2::2]) # c246 print(str2[::2]) # ac246 print(str2[::-1]) # 654321cba print(str2[-3:-1]) # 45 # 检查字符串是否由数字构成 print(str2.isdigit()) # False # 检查字符串是否以字母构成 print(str2.isalpha()) # False # 检查字符串是否以数字和字母构成 print(str2.isalnum()) # True str3 = ' jackfrued@126.com ' print(str3) # 获得字符串修剪左右两侧空格的拷贝 print(str3.strip()) if __name__ == '__main__': main()
三、元组
- Python 的元组与列表类似,不同之处在于元组的元素不能修改。
- 元组使用小括号,列表使用方括号。
3.1 创建元组
元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。
tup1 = ('Google', 'Runoob', 1997, 2000) #可创建不同类型的元素 tup2 = (1, 2, 3, 4, 5 ) tup3 = () #空元组 tup4 = (50,) #创建只有一个元素的元组,需要加逗号
3.2 元组 切片、索引
tup1 = ('Google', 'Runoob', 1997, 2000) tup2 = (1, 2, 3, 4, 5, 6, 7 ) print ("tup1[0]: ", tup1[0]) print ("tup2[1:5]: ", tup2[1:5])
3.3 序列通用运算符
3.4 元组内置函数
菜鸟教程:https://www.runoob.com/python3/python3-tuple.html
元组就4个,前3个是序列通用的。
四、列表
- 列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现。
- 列表的数据项不需要具有相同的类型
- 可以随时添加和删除其中的元素。
4.1 创建列表
创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可,列表中的对象都会按照插入的顺序存储到列表中。
list0 = [] #空列表 list1 = ['Google', 'Runoob', 1997, 2000] #存储不同类型的数据 list2 = [1, 2, 3, 4, 5 ] list3 = ["a", "b", "c", "d"]
4.2 切片、索引读取列表指定元素
切片指从现有列表中,获取一个子列表。
语法:列表[起始:结束:步长]
- 步长表示,每次获取元素的间隔,默认值是1
- 步长不能是0,但是可以是负数
- 通过切片获取元素时,会包括起始位置的元素,不会包括结束位置的元素
- 做切片操作时,总会返回一个新的列表,不会影响原来的列表
- 起始和结束位置的索引都可以省略不写
- 如果省略结束位置,则会一直截取到最后
- 如果省略起始位置,则会从第一个元素开始截取
- 如果起始位置和结束位置全部省略,则相当于创建了一个列表的副本
#!/usr/bin/python3 list1 = ['Google', 'Runoob', 1997, 2000]; list2 = [1, 2, 3, 4, 5, 6, 7 ]; print ("list1[0]: ", list1[0]) print ("list2[1:5]: ", list2[1:5])
#结果
list1[0]: Google
list2[1:5]: [2, 3, 4, 5]
4.3 新增列表元素、删除列表元素
新增:
append()
向列表的最后添加一个元素
insert()
向列表的指定位置插入一个元素
参数:
1.要插入的位置
2.要插入的元素
extend()
使用新的序列来扩展当前序列
需要一个序列作为参数,它会将该序列中的元素添加到当前列表中
stus.append('唐僧') stus.insert(2,'唐僧') stus.extend(['唐僧','白骨精']) stus += ['唐僧','白骨精']
删除:
pop()
根据索引删除并返回被删除的元素
remove()
删除指定值得元素,如果相同值得元素有多个,只会删除第一个
result = stus.pop(2) # 删除索引为2的元素 result = stus.pop() # 删除最后一个 print('result =',result)
stus.remove('猪八戒')
4.4 列表函数和方法
菜鸟教程:https://www.runoob.com/python3/python3-list.html
主要使用的:len()、count()、index()、sort()、append()、insert()、remove()、pop()
#只写一种 排序,其他的看菜鸟
def main(): list1 = ['orange', 'apple', 'zoo', 'internationalization', 'blueberry'] list2 = sorted(list1) # sorted函数返回列表排序后的拷贝不会修改传入的列表 # 函数的设计就应该像sorted函数一样尽可能不产生副作用 list3 = sorted(list1, reverse=True) # 通过key关键字参数指定根据字符串长度进行排序而不是默认的字母表顺序 list4 = sorted(list1, key=len) print(list1) print(list2) print(list3) print(list4) # 给列表对象发出排序消息直接在列表对象上进行排序 list1.sort(reverse=True) print(list1) if __name__ == '__main__': main()
我们已经有了列表这种数据结构,为什么还需要元组这样的类型呢?
- 元组中的元素是无法修改的,事实上我们在项目中尤其是多线程环境(后面会讲到)中可能更喜欢使用的是那些不变对象(一方面因为对象状态不能修改,所以可以避免由此引起的不必要的程序错误,简单的说就是一个不变的对象要比可变的对象更加容易维护;另一方面因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以方便的被共享访问)。所以结论就是:如果不需要对元素进行添加、删除、修改的时候,可以考虑使用元组,当然如果一个方法要返回多个值,使用元组也是不错的选择。
- 元组在创建时间和占用的空间上面都优于列表。我们可以使用sys模块的getsizeof函数来检查存储同样的元素的元组和列表各自占用了多少内存空间,这个很容易做到。
五、字典
- 字典属于一种新的数据结构,称为映射(mapping)
- 字典的作用和列表类似,都是用来存储对象的容器
- 列表存储数据的性能很好,但是查询数据的性能的很差
- 在字典中每一个元素都有一个唯一的名字,通过这个唯一的名字可以快速的查找到指定的元素
- 在查询元素时,字典的效率是非常快的
- 在字典中可以保存多个对象,每个对象都会有一个唯一的名字
- 这个唯一的名字,我们称其为键(key),通过key可以快速的查询value
- 这个对象,我们称其为值(value)
- 所以字典,我们也称为叫做键值对(key-value)结构
- 每个字典中都可以有多个键值对,而每一个键值对我们称其为一项(item)
5.1 创建字典
方法一:创建一个保护有数据的字典 语法: {key:value,key:value,key:value} 字典的值可以是任意对象 字典的键可以是任意的不可变对象(int、str、bool、tuple ...),但是一般我们都会使用str 字典的键是不能重复的,如果出现重复的后边的会替换到前边的
dict1 = { 'abc': 456 } dict2 = { 'abc': 123, 98.6: 37 }
方法二:使用 dict()函数来创建字典 每一个参数都是一个键值对,参数名就是键,参数名就是值(这种方式创建的字典,key都是字符串) d = dict(name='孙悟空',age=18,gender='男') 方法三:也可以将一个包含有双值子序列的序列转换为字典 双值序列,序列中只有两个值,[1,2] ('a',3) 'ab' 子序列,如果序列中的元素也是序列,那么我们就称这个元素为子序列 [(1,2),(3,5)] d = dict([('name','孙悟饭'),('age',18)]) d = dict(name='孙悟空',age=18,gender='男')
5.2 访问字典的值
方法一:通过键名获取对应的值,如果不存在该键会报错
方法二:get(key[, default]) 该方法用来根据键来获取字典中的值,如果获取的键在字典中不存在,会返回None
获取字典的键值对:dict.iteams()
获取字典的所有键:dict.keys()
获取自定的所有值:dict.values()
in 判断的是键是否存在字典中,不是值: key in dict
5.3 添加键值对
方法一:直接添加键值对,
方法二:setdefault(key[, default]) 可以用来向字典中添加key-value,如果key已经存在于字典中,则返回key的值,不会对字典做任何操作,如果key不存在,则向字典中添加这个key,并设置value
5.4 删除字典元素
方法一:del删除
方法二:clear()
5.5 字典内置函数和方法:
菜鸟教程:https://www.runoob.com/python3/python3-dictionary.html
def main(): scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82} # 通过键可以获取字典中对应的值 print(scores['骆昊']) print(scores['狄仁杰']) # 对字典进行遍历(遍历的其实是键再通过键取对应的值) for elem in scores: print('%s\t--->\t%d' % (elem, scores[elem])) # 更新字典中的元素 scores['白元芳'] = 65 scores['诸葛王朗'] = 71 scores.update(冷面=67, 方启鹤=85) print(scores) if '武则天' in scores: print(scores['武则天']) print(scores.get('武则天')) # get方法也是通过键获取对应的值但是可以设置默认值 print(scores.get('武则天', 60)) # 删除字典中的元素 print(scores.popitem()) print(scores.popitem()) print(scores.pop('骆昊', 100)) # 清空字典 scores.clear() print(scores) if __name__ == '__main__': main()
5.6 字典与列表的区别
dict内部存放的顺序和key放入的顺序是没有关系的。
和list比较,dict有以下几个特点:
- 查找和插入的速度极快,不会随着key的增加而变慢;
- 需要占用大量的内存,内存浪费多。
而list相反:
- 查找和插入的时间随着元素的增加而增加;
- 占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。
dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。
这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key
六、集合
- 集合和列表非常相似
- 不同点:
- 1.集合中只能存储不可变对象
- 2.集合中存储的对象是无序(不是按照元素的插入顺序保存)
- 3.集合中不能出现重复的元素
- 集合(set)是一个无序的不重复元素序列。
6.1 创建集合
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
parame = {value01,value02,...} 或者 set(value) #重复元素,自动过滤
6.2 集合的函数
Python中的集合跟数学上的集合是一致的,不允许有重复元素,而且可以进行交集、并集、差集等运算。
菜鸟教程:https://www.runoob.com/python3/python3-set.html
def main(): set1 = {1, 2, 3, 3, 3, 2} print(set1) print('Length =', len(set1)) set2 = set(range(1, 10)) print(set2) set1.add(4) #添加元素:set会自动过滤重复元素 set1.add(5) set2.update([11, 12]) # 另一个添加元素方法 print(set1) print(set2) set2.discard(5) #移除元素,如果元素不存在,不会发生错误 # remove的元素如果不存在会引发KeyError 移除元素,pop()随机移除元素 if 4 in set2: set2.remove(4) print(set2) # 遍历集合容器 for elem in set2: print(elem ** 2, end=' ') print() # 将元组转换成集合 set3 = set((1, 2, 3, 3, 2, 1)) print(set3.pop()) #随机移除元素 print(set3) # 集合的交集、并集、差集、对称差运算 print(set1 & set2) # print(set1.intersection(set2)) print(set1 | set2) # print(set1.union(set2)) print(set1 - set2) # print(set1.difference(set2)) print(set1 ^ set2) # print(set1.symmetric_difference(set2)) # 判断子集和超集 print(set2 <= set1) # print(set2.issubset(set1)) print(set3 <= set1) # print(set3.issubset(set1)) print(set1 >= set2) # print(set1.issuperset(set2)) print(set1 >= set3) # print(set1.issuperset(set3)) if __name__ == '__main__': main()