引言:今日学习字符串和常用数据结构
字符串 字符串:就是由零个或多个字符组成的有限序列,一般记为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 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()
13 Hello, world! HELLO, WORLD! 8 -1 False True True ******************hello, world!******************* hello, world! c c12 c123456 c246 ac246 654321cba 45 False False True recur799.github.io recur799.github.io
※注意※: 1.len()
用于计算字符串长度 2.capitalize()
用于将字符串首字母换成大写 3.upper()
用于将整个字符串换位大写 4.find()
用于检测字符串中是否包含指定字符,如果有就返回值,如果没有就返回-1(下标运算) 5.index()
和find()
用途一致,但检测不到就会引发异常 6.startswith()
用于检查字符串是否以指定字符开头 7.endswith()
用于检查字符串是否以指定字符结尾 8.center()
用于将字符串以指定宽度居中并在两侧填充指定字符 9.rjust()
用于将字符串以指定宽度放置左侧并在左侧填充指定字符 10.str[]
用于从字符串中去除指定位置的字符(下标运算) 11.srt[x:x+1]
x为任意数,用于从x的位置索引到x+1的位置结束 12.str[x::n]
x为任意数,n为任意数,用于从x的位置开始索引,步数为n开始索引 13.str[::n]
n为任意数,用于从从开始位置索引到结束,步数为n,若n=-1,就倒着索引该字符串 14.isdigit()
用于检查字符串是否以数字构成 15.isalpha()
用于检查字符串是否以字母构成 16.isalnum()
用于检查字符串是否以数字和字母构成 17.strip()
用于将字符串修建左右两侧空格并输出
列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def main(): list1 = [1, 3, 5, 7, 100] print(list1) list2 = ['hello'] * 5 print(list2) # 计算列表长度(元素个数) print(len(list1)) # 下标(索引)运算 print(list1[0]) print(list1[4]) # print(list1[5]) # IndexError: list index out of range print(list1[-1]) print(list1[-3]) list1[2] = 300 print(list1) # 添加元素 list1.append(200) list1.insert(1, 400) list1 += [1000, 2000] print(list1) print(len(list1)) # 删除元素 list1.remove(3) if 1234 in list1: list1.remove(1234) del list1[0] print(list1) # 清空列表元素 list1.clear() print(list1) if __name__ == '__main__': main()
[1, 3, 5, 7, 100] [‘hello’, ‘hello’, ‘hello’, ‘hello’, ‘hello’] 5 1 100 100 5 [1, 3, 300, 7, 100] [1, 400, 3, 300, 7, 100, 200, 1000, 2000] 9 [400, 300, 7, 100, 200, 1000, 2000] []
※注意※: 1.len()
用于计算元素个数 2.listn[x]
n为任意列表,x为查找第几个元素(下标运算),不存在会报错。 3.listn[x]=y
n为任意列表,x为添加在第几个元素后面,y为所添加的元素(下标运算) 4.apend()
用于在列表末尾添加新的元素 5.insert(n,x)
n为列表中任意位置,x为添加的新元素,用于在n位置后面添加新元素y 6.remove()
删除指定元素 7.del
删除变量 8.clear()
清空元素列表
解释del
1 2 3 4 5 6 a=1 # 对象 1 被 变量a引用,对象1的引用计数器为1 b=a # 对象1 被变量b引用,对象1的引用计数器加1 = 2 c=a #1对象1 被变量c引用,对象1的引用计数器加1 = 3 del a #删除变量a,解除a对1的引用 del b #删除变量b,解除b对1的引用 print(c) #最终变量c仍然引用1
1
变量a已经被del,c=a还是可以得到1的结果,所以python中del不是直接将该对象在内存中删除,二十将该对象的引用计数删除
列表切片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def main(): fruits = ['grape', 'apple', 'strawberry', 'waxberry'] fruits += ['pitaya', 'pear', 'mango'] # 循环遍历列表元素 for fruit in fruits: print(fruit.title(), end=' ') print() # 列表切片 fruits2 = fruits[1:4] print(fruits2) # fruit3 = fruits # 没有复制列表只创建了新的引用 # 可以通过完整切片操作来复制列表 fruits3 = fruits[:] print(fruits3) fruits4 = fruits[-3:-1] print(fruits4) # 可以通过反向切片操作来获得倒转后的列表的拷贝 fruits5 = fruits[::-1] print(fruits5) if __name__ == '__main__': main()
Grape Apple Strawberry Waxberry Pitaya Pear Mango [‘apple’, ‘strawberry’, ‘waxberry’] [‘grape’, ‘apple’, ‘strawberry’, ‘waxberry’, ‘pitaya’, ‘pear’, ‘mango’] [‘pitaya’, ‘pear’] [‘mango’, ‘pear’, ‘pitaya’, ‘waxberry’, ‘strawberry’, ‘apple’, ‘grape’]
※注意※: 1.title()
用于将列表中所有元素首字母改为大写 2.没有复制列表只创建了新的引用 3.列表切片操作和字符串切片操作一样
列表的排序操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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()
[‘orange’, ‘apple’, ‘zoo’, ‘internationalization’, ‘blueberry’] [‘apple’, ‘blueberry’, ‘internationalization’, ‘orange’, ‘zoo’] [‘zoo’, ‘orange’, ‘internationalization’, ‘blueberry’, ‘apple’] [‘zoo’, ‘apple’, ‘orange’, ‘blueberry’, ‘internationalization’] [‘zoo’, ‘orange’, ‘internationalization’, ‘blueberry’, ‘apple’]
※注意※: 1.sorted()
用于将列表里的元素进行按字母表或者数字从小到大的顺序进行排序 2.sorred(listn,reverse=True)
n为任意列表,reverse
为排序规则,True
就将列表进行反向排序,False
为升序,将列表按字母表顺序排序后并将其降序排列 3.sorred(listn,key=len)
n为任意列表,key=len
,通过key关键字参数指定根据字符串长度进行排序而不是默认的字母表顺序
使用列表的生成式语法来创建列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import sys def main(): f = [x for x in range(1, 10)] print(f) f = [x + y for x in 'ABCDE' for y in '1234567'] print(f) # 用列表的生成表达式语法创建列表容器 # 用这种语法创建列表之后元素已经准备就绪所以需要耗费较多的内存空间 f = [x ** 2 for x in range(1, 1000)] print(sys.getsizeof(f)) # 查看对象占用内存的字节数 print(f) # 请注意下面的代码创建的不是一个列表而是一个生成器对象 # 通过生成器可以获取到数据但它不占用额外的空间存储数据 # 每次需要数据的时候就通过内部的运算得到数据(需要花费额外的时间) f = (x ** 2 for x in range(1, 1000)) print(sys.getsizeof(f)) # 相比生成式生成器不占用存储数据的空间 print(f) for val in f: print(val) if __name__ == '__main__': main()
结果太长,不复制过来了
※注意※: 1.f = [x for x in range(1, 10)]
是用列表的生成表达式语法创建列表容器 2.用这种语法创建列表之后元素已经准备就绪所以需要耗费较多的内存空间 3.相比于f = [x ** 2 for x in range(1, 1000)]
, f = (x ** 2 for x in range(1, 1000))
后者为创建的不是一个列表而是一个生成器对象,通过生成器可以获取到数据但它不占用额外的空间存储数据 4.生成器对象相比于生成式生成器不占用储存数据的空间
通过yield
关键字将一个普通函数改为生成数函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def fib(n): a, b = 0, 1 for _ in range(n): a, b = b, a + b yield a def main(): for val in fib(20): print(val) if __name__ == '__main__': main()
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
※疑问※: 没看懂yield
元组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def main(): # 定义元组 t = ('骆昊', 38, True, '四川成都') print(t) # 获取元组中的元素 print(t[0]) print(t[3]) # 遍历元组中的值 for member in t: print(member) # 重新给元组赋值 # t[0] = '王大锤' # TypeError # 变量t重新引用了新的元组原来的元组将被垃圾回收 t = ('王大锤', 20, True, '云南昆明') print(t) # 将元组转换成列表 person = list(t) print(person) # 列表是可以修改它的元素的 person[0] = '李小龙' person[1] = 25 print(person) # 将列表转换成元组 fruits_list = ['apple', 'banana', 'orange'] fruits_tuple = tuple(fruits_list) print(fruits_tuple) if __name__ == '__main__': main()
(‘骆昊’, 38, True, ‘四川成都’) 骆昊 四川成都 骆昊 38 True 四川成都 (‘王大锤’, 20, True, ‘云南昆明’) [‘王大锤’, 20, True, ‘云南昆明’] [‘李小龙’, 25, True, ‘云南昆明’] (‘apple’, ‘banana’, ‘orange’)
**※注意※: 1.元组为n = (  )
,n为任意变量,列表为listn = [  ]
注意符号 2.元组不能修改,但列表可以 3.已经有了列表,为什么还需要元组:
元组中的元素是无法修改的,事实上我们在项目中尤其是多线程环境(后面会讲到)中可能更喜欢使用的是那些不变对象(一方面因为对象状态不能修改,所以可以避免由此引起的不必要的程序错误,简单的说就是一个不变的对象要比可变的对象更加容易维护;另一方面因为没有任何一个线程能够修改不变对象的内部状态,一个不变对象自动就是线程安全的,这样就可以省掉处理同步化的开销。一个不变对象可以方便的被共享访问)。所以结论就是:如果不需要对元素进行添加、删除、修改的时候,可以考虑使用元组,当然如果一个方法要返回多个值,使用元组也是不错的选择。
元组在创建时间和占用的空间上面都优于列表。我们可以使用sys模块的getsizeof函数来检查存储同样的元素的元组和列表各自占用了多少内存空间,这个很容易做到。我们也可以在ipython中使用魔法指令%timeit来分析创建同样内容的元组和列表所花费的时间,下图是我的macOS系统上测试的结果。
集合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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) set1.add(5) set2.update([11, 12]) print(set1) print(set2) set2.discard(5) # remove的元素如果不存在会引发KeyError 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()
{1, 2, 3} Length = 3 {1, 2, 3, 4, 5, 6, 7, 8, 9} {1, 2, 3, 4, 5} {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12} {1, 2, 3, 6, 7, 8, 9, 11, 12} 1 4 9 36 49 64 81 121 144 1 {2, 3} {1, 2, 3} {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12} {4, 5} {4, 5, 6, 7, 8, 9, 11, 12} False True False True
**※注意※: 1.set
:集合(set)是一个无序的不重复元素序列。可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典 2.add()
:方法用于给集合添加元素,如果添加的元素在集合中已存在,则不执行任何操作 3.discard()
和remove()
区别是如果容器里没有,使用remove()
会报错 4.pop()
:pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值 5.超集:如果一个集合S2中的每一个元素都在集合S1中,且集合S1中可能包含S2中没有的元素,则集合S1就是S2的一个超集,反过来,S2是S1的子集。 S1是S2的超集,若S1中一定有S2中没有的元素,则S1是S2的真超集,反过来S2是S1的真子集。 6.并集、交集、差集、对称差、超集如图所示:
字典 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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()
95 82 骆昊 —> 95 白元芳 —> 78 狄仁杰 —> 82 {‘骆昊’: 95, ‘白元芳’: 65, ‘狄仁杰’: 82, ‘诸葛王朗’: 71, ‘冷面’: 67, ‘方启鹤’: 85} None 60 (‘方启鹤’, 85) (‘冷面’, 67) 95 {}
**※注意※: 1.使用scores
来创建字典 2.get()
返回指定键的值,如果值不在字典中返回默认值 3.popitem()
和pop()
用法一致
练习 在屏幕上显示跑马灯文字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import os import time def main(): content = '北京欢迎你为你开天辟地…………' while True: # 清理屏幕上的输出 os.system('cls') # os.system('clear') print(content) # 休眠200毫秒 time.sleep(0.2) content = content[1:] + content[0] if __name__ == '__main__': main()
北京欢迎你为你开天辟地………… 京欢迎你为你开天辟地…………北 欢迎你为你开天辟地…………北京 迎你为你开天辟地…………北京欢 你为你开天辟地…………北京欢迎 为你开天辟地…………北京欢迎你 你开天辟地…………北京欢迎你为 开天辟地…………北京欢迎你为你 天辟地…………北京欢迎你为你开 辟地…………北京欢迎你为你开天 地…………北京欢迎你为你开天辟 …………北京欢迎你为你开天辟地 ………北京欢迎你为你开天辟地… ……北京欢迎你为你开天辟地……※注意※: 1.time.sleep()
:推迟调用线程的运行,secs指秒数 ※疑问※:os
模块
今日练习未做完