#9 Python列表和元组
前言
python中有6种序列:列表、元组、字符串、unicode字符串、buffer对象和xrange对象。序列通用操作包括:索引、切片、长度、加、乘、最大值、最小值,遍历和检查成员。虽然python有6中内置序列,但是最常用的是列表和元组。所有本博文将深入列表和元组,掌握其方法!
一、列表(list)
看了上面说的,现在是不是一头雾水,其实上面提到的操作无非不过一些方法而已,熟练应用就掌握了,那先来看看列表的方法吧:
in [3]: dir(list) out[3]: ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
补充:有些方法有两个前导下划线和两个后置下划线,这是特殊方法的意思,应用于特殊函数,实际应用中很少用到,常用的是普通方法。
可以看到,列表的方法其实不是很多,但是使用技巧却很灵活,盘它!
1.初始化列表
列表的初始化前面已经说过了,这里再来复习一下,被一对方括号括住,元素用逗号隔开就是列表:
in [4]: systems = ['centos','windows', 'ubuntu'] # 元素全是字符串的列表 in [5]: systems = ['centos','windows', 'ubuntu', 666] # 元素既有字符串又有数字 in [6]: systems = ['centos','windows', 'ubuntu', 666, ['macos']] #列表包含列表 in [7]: systems = ['centos','windows', 'ubuntu', 666, ['macos'],{'phone':'ios'}] # 列表还可以包含字典
2.列表索引
列表中每个元素都会被分配一个数字,这个数字就是对应元素的位置,称为索引。第一个元素的索引为0,第二个元素的索引为1,第三个元素的索引为2,依此类推。
注意:计算机中,几乎所有的索引都是从0开始的,在涉及索引操作时,一定要注意这一点
通过索引访问列表元素:
in [8]: systems = ['centos','windows', 'ubuntu'] in [9]: systems[0] out[9]: 'centos' in [10]: systems[1] out[10]: 'windows' in [11]: systems[2] out[11]: 'ubuntu'
上面说到列表使用技巧灵活,是有道理的:可以使用 索引为-1 来直接获取最后一个元素,也就是说,列表的索引可以倒着来:
in [12]: systems = ['centos','windows', 'ubuntu'] in [13]: systems[-1] # 直接获取最后一个元素 out[13]: 'ubuntu' in [14]: systems[-2] out[14]: 'windows' in [15]: systems[-3] out[15]: 'centos' in [16]: systems[-4] # 没有索引-4,会抛出超出范围的异常 --------------------------------------------------------------------------- indexerror traceback (most recent call last) <ipython-input-16-2b502eee5f42> in <module> ----> 1 systems[-4] indexerror: list index out of range
通过元素获取索引:
in [17]: systems = ['centos','windows', 'ubuntu'] in [18]: systems.index('windows') out[18]: 1
3.列表切片
要说列表玩的6不6,就看切片熟不熟。切片其实就是一次性获取多个元素:
in [19]: systems = ['centos','windows', 'ubuntu'] in [20]: systems[0:2] out[20]: ['centos', 'windows']
如上面代码所示,切片的操作为:列表[开始:结束:间隔] ,间隔默认为1,可以省略不写。
注意:切片的两个索引取左不取右,也就是是说,左闭右开
来看更灵活的使用方法:
in [21]: systems = ['centos','windows', 'ubuntu', 'ios', 'android'] in [22]: systems[2:5] # 获取索引为2到5的元素,不包括5 out[22]: ['ubuntu', 'ios', 'android'] in [24]: systems[2:-1] # 获取索引为2到-1的元素,不包括-1 out[24]: ['ubuntu', 'ios'] in [25]: systems[0:5] # 获取开头元素到索引为5的元素,不包括5 out[25]: ['centos', 'windows', 'ubuntu', 'ios', 'android'] in [26]: systems[:5] # 从开头取的话可以将0忽略,效果与上句一样 out[26]: ['centos', 'windows', 'ubuntu', 'ios', 'android'] in [28]: systems[2:] # 结尾是列表的最后一个元素时,必须省略不写,写-1的话就取不到最后一个元素了 out[28]: ['ubuntu', 'ios', 'android'] in [29]: systems[:] # 获取全部元素 out[29]: ['centos', 'windows', 'ubuntu', 'ios', 'android'] in [30]: systems[1:5:2] # 获取索引为1到5的元素,并且每隔一个元素取一个,不包括5 out[30]: ['windows', 'ios'] in [31]: systems[::2] # 从全部元素中每隔一个取一个 out[31]: ['centos', 'ubuntu', 'android']
一定要熟练掌握上述方法
4.列表组合
列表相加:将不同的列表用 + 号加起来,效果如下:
in [32]: name1 = ['minutesheep','mike'] in [33]: name2 = ['bigban', 'heenoor'] in [34]: name1 + name2 out[34]: ['minutesheep', 'mike', 'bigban', 'heenoor']
列表扩展:上面列表相加并没有改变原有列表的元素,name1 + name2 是一个新的列表,可以传给变量 name3;而列表的扩展将直接改变被扩展列表:
in [35]: name3 = name1 + name2 # 将name1+name2传给变量name3 in [36]: name3 # 可以看到name3是一个新列表 out[36]: ['minutesheep', 'mike', 'bigban', 'heenoor'] in [37]: name1 # name1列表并没有被改变 out[37]: ['minutesheep', 'mike'] in [38]: name2 # name2列表并没有被改变 out[38]: ['bigban', 'heenoor'] in [39]: name1.extend(name2) # 用name2扩展name1,使用extemd()方法 in [40]: name1 # 可以看到name1列表被改变,因为name1是被扩展列表 out[40]: ['minutesheep', 'mike', 'bigban', 'heenoor'] in [41]: name2 # name2列表并没有被改变或者删除 out[41]: ['bigban', 'heenoor']
列表乘法:将一个列表与一个数字 n 相乘,得到一个 n 倍元素的新列表:
in [44]: systems out[44]: ['centos', 'windows', 'ubuntu', 'ios', 'android'] in [45]: systems * 3 out[45]: ['centos', 'windows', 'ubuntu', 'ios', 'android', 'centos', 'windows', 'ubuntu', 'ios', 'android', 'centos', 'windows', 'ubuntu', 'ios', 'android']
5.插入元素
追加:在列表末尾插入一个新的元素:
in [46]: systems out[46]: ['centos', 'windows', 'ubuntu', 'ios', 'android'] in [47]: systems.append('unix') # 使用append()方法追加 in [48]: systems out[48]: ['centos', 'windows', 'ubuntu', 'ios', 'android', 'unix']
任意位置插入:在列表的任意位置插入新元素,之前存在元素的位置向后加一:
in [48]: systems out[48]: ['centos', 'windows', 'ubuntu', 'ios', 'android', 'unix'] in [49]: systems.insert(3,'dos') # 使用 insert(位置,新元素名称) 方法插入新元素 in [50]: systems out[50]: ['centos', 'windows', 'ubuntu', 'dos', 'ios', 'android', 'unix']
6.修改列表
直接将被修改的元素重新赋值即可:
in [50]: systems out[50]: ['centos', 'windows', 'ubuntu', 'dos', 'ios', 'android', 'unix'] in [51]: systems[3] out[51]: 'dos' in [52]: systems[3]= '我是之前的dos,我被修改了' # 直接将被修改元素重新赋值即可 in [53]: systems out[53]: ['centos', 'windows', 'ubuntu', '我是之前的dos,我被修改了', 'ios', 'android', 'unix']
7.删除元素
删除最后一个元素:将列表的末尾元素删除:
in [53]: systems out[53]: ['centos', 'windows', 'ubuntu', '我是之前的dos,我被修改了', 'ios', 'android', 'unix'] in [54]: systems.pop() # 使用pop()方法删除末尾元素,并且返回末尾元素 out[54]: 'unix' in [55]: systems out[55]: ['centos', 'windows', 'ubuntu', '我是之前的dos,我被修改了', 'ios', 'android']
删除任意位置元素:将列表中任意位置的元素删除:
in [55]: systems out[55]: ['centos', 'windows', 'ubuntu', '我是之前的dos,我被修改了', 'ios', 'android'] in [56]: del systems[3] # 使用 del 命令删除元素 in [57]: systems out[57]: ['centos', 'windows', 'ubuntu', 'ios', 'android']
删除指定元素:删除列表中指定的元素,不通过索引删除,直接通过元素的名称删除:
in [57]: systems out[57]: ['centos', 'windows', 'ubuntu', 'ios', 'android'] in [58]: systems.remove('ios') # 使用remove()方法删除指定元素 in [59]: systems out[59]: ['centos', 'windows', 'ubuntu', 'android']
列表清空:将列表清空,列表依然存在,直是没有元素而已,是一个空列表:
in [59]: systems out[59]: ['centos', 'windows', 'ubuntu', 'android'] in [60]: systems.clear() # 使用clear()方法将列表清空 in [61]: systems out[61]: []
8.列表统计
统计列表长度:使用len()统计列表中元素的个数:
in [62]: systems = ['centos','windows', 'ubuntu', 'ios', 'android'] in [63]: len(systems) # 统计个数 out[63]: 5
统计列表中某个元素的个数:使用count()方法统计指定元素的个数:
in [64]: systems = ['centos','windows', 'ubuntu', 'ios', 'android','ios','windows','ios'] in [65]: systems.count('centos') # 使用count()方法计数 out[65]: 1 in [66]: systems.count('ios') out[66]: 3
正排序:按照asc码进行从小到大的排序:
in [67]: systems out[67]: ['centos', 'windows', 'ubuntu', 'ios', 'android', 'ios', 'windows', 'ios'] in [68]: systems.sort() # 使用sort()方法,从小到大排序 in [69]: systems out[69]: ['android', 'centos', 'ios', 'ios', 'ios', 'ubuntu', 'windows', 'windows']
逆排序:按照asc码进行从大到小的排序:
in [69]: systems out[69]: ['android', 'centos', 'ios', 'ios', 'ios', 'ubuntu', 'windows', 'windows'] in [70]: systems.reverse() #使用reverse()方法,从大到小排序 in [71]: systems out[71]: ['windows', 'windows', 'ubuntu', 'ios', 'ios', 'ios', 'centos', 'android']
注意:python3中,列表例的数据类型一致才可以排序,否则会报错
9.列表拷贝
关于列表的拷贝,有好多种方法,每一种方法都有差别,一起来看下:
方法1: b = a # a是一个列表
in [87]: a = [1,2,3] in [88]: b = a # 把a拷贝给b in [89]: id(a) # 可以看到a和b的地址相同,指向同一块地址 out[89]: 2762625492040 in [90]: id(b) out[90]: 2762625492040 in [91]: a.append(5) # 列表a追加元素 in [92]: a out[92]: [1, 2, 3, 5] in [93]: b # 列表b也改变了,还记得第五节在讲变量时化的那个图吗? out[93]: [1, 2, 3, 5]
方法二: b = a[:]
in [94]: a = [1,2,3] in [95]: b = a[:] # 把a列表拷贝给b in [96]: a.append(5) in [97]: a out[97]: [1, 2, 3, 5] in [98]: b # 可以看到,b并没有跟着改变 out[98]: [1, 2, 3] in [99]: id(a) # 说明a和b指向不同的地址 out[99]: 2762624748936 in [100]: id(b) out[100]: 2762626722504
但是~~
in [107]: a = [1,2,[3]] # a列表里面包含了一个新的列表 in [108]: b = a[:] in [109]: a[-1].append(5) # 子列表追缴一个新的元素 in [110]: a.append(6) # a列表追加一个新的元素 in [111]: a out[111]: [1, 2, [3, 5], 6] # a变成了这样 in [112]: b # 但是b的子列表却跟着改变了,见鬼了! out[112]: [1, 2, [3, 5]] in [113]: id(a) # a和b指向的地址并不一样 out[113]: 2762626869896 in [114]: id(b) out[114]: 2762602977160
虽然b = a[:] 这种方式可以拷贝出一个新的列表,但是当列表中包含子列表的时候,拷贝出来的新列表中的子列表会跟着改变╮(╯▽╰)╭,应用的时候一定要注意呐
方式三: b = list(a)
in [115]: a = [1,2,3] in [116]: b = list(a) in [117]: a.append(5) in [118]: a out[118]: [1, 2, 3, 5] in [119]: b out[119]: [1, 2, 3] in [120]: a = [1,2,[3]] in [121]: b = list(a) in [122]: a[-1].append(5) in [123]: a.append(6) in [124]: a out[124]: [1, 2, [3, 5], 6] in [125]: b out[125]: [1, 2, [3, 5]] in [126]: id(a) out[126]: 2762627298696 in [127]: id(b) out[127]: 2762627301000
可以看到与方法二大同小异=====( ̄▽ ̄*)b
方法四: b = a * 1 # a为列表
in [128]: a = [1,2,3] in [129]: b = a * 1 in [130]: a.append(5) in [131]: a out[131]: [1, 2, 3, 5] in [132]: b out[132]: [1, 2, 3] in [133]: a = [1,2,[3]] in [134]: b = a * 1 in [135]: a[-1].append(5) in [136]: a.append(6) in [137]: a out[137]: [1, 2, [3, 5], 6] in [138]: b out[138]: [1, 2, [3, 5]] in [139]: id(a) out[139]: 2762627326280 in [140]: id(b) out[140]: 2762627611016
可以看到,与方法二、方法三大同小异,,ծㅂծ,,
方法五: b = a.copy() # a是列表
in [170]: a = [1,2,3] in [171]: b = a.copy() in [172]: a.append(5) in [173]: a out[173]: [1, 2, 3, 5] in [174]: b out[174]: [1, 2, 3] in [175]: a = [1,2,[3]] in [176]: b = a.copy() in [177]: a[-1].append(5) in [178]: a.append(6) in [179]: a out[179]: [1, 2, [3, 5], 6] in [180]: b out[180]: [1, 2, [3, 5]] in [181]: id(a) out[181]: 2762628171912 in [182]: id(b) out[182]: 2762628181320
可以看到,与方法二、方法三、方法四大同小异(ˉ▽ˉ;)...
方法六: b = copy.copy(a) # a为列表
in [141]: import copy # 需要导入 copy 模块 in [142]: a = [1,2,3] in [143]: b = copy.copy(a) in [144]: a.append(5) in [145]: a out[145]: [1, 2, 3, 5] in [146]: b out[146]: [1, 2, 3] in [147]: a = [1,2,[3]] in [148]: b = copy.copy(a) in [149]: a[-1].append(5) in [150]: a.append(6) in [151]: a out[151]: [1, 2, [3, 5], 6] in [152]: b out[152]: [1, 2, [3, 5]] in [153]: id(a) out[153]: 2762602926984 in [154]: id(b) out[154]: 2762627609608
可以看到,与方法二、方法三、方法四、方法五大同小异(ˉ▽ˉ;)...
方法七: b = copy.deepcopy(a) # a为列表
in [155]: import copy in [156]: a = [1,2,3] in [157]: b = copy.deepcopy(a) in [158]: a.append(5) in [159]: a out[159]: [1, 2, 3, 5] in [160]: b out[160]: [1, 2, 3] in [161]: a = [1,2,[3]] in [162]: b = copy.deepcopy(a) in [163]: a[-1].append(5) in [164]: a.append(6) in [165]: a out[165]: [1, 2, [3, 5], 6] in [166]: b # 这次b终于没有被改变 out[166]: [1, 2, [3]] in [167]: id(a) out[167]: 2762627600712 in [168]: id(b) out[168]: 2762625604936
哇~~这一次b列表终于没有跟着改变ヾ(≧▽≦*)o
从以上七种方法可以看到,方法一最不推荐使用,方法二、方法三、方法四、方法五、方法六大同小异,都是复制列表后得到一个新的列表,但是一点列表中含有子列表,复制过来的列表中的子列表还是会跟着改变,方法七才会真正的做到完全复制且不是任何影响。
来一个列表的总结:
a.append(x) # 列表a追加元素x a.clear() # 将列表a清空 a.copy() # 拷贝列表a a.count(x) # 对a列表的元素x计数 a.extend(b) # 把b列表扩展到a列表中 a.index(x) # 查询a列表中x元素的索引 a.insert(n,x) # 在列表a的第n个位置处插入元素x a.pop() # 将列表a的末尾元素删除,并返回这个元素 a.remove(x) # 将列表a的元素x删除 a.reverse() # 按asc码进行从大到小的排序 a.sort() # 按asc码进行从小到大的排序
二、元组
元组与列表相似,只不过元组不能修改其内部元素。列表使用方括号,而元组使用圆括号。
in [193]: dir(tuple) out[193]: ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
可以看到,元组的方法少的可怜,只有 count 和 index 方法
1.初始化元组
与列表类似,用一对圆括号括起来,元素之间用逗号分隔开,需要注意的是元组最后一定要加逗号:
in [184]: systems = ('linux', 'windows', 'unix',) in [185]: systems = ('linux', 'windows', 'unix', 666,) in [186]: systems = ('linux', 'windows', 'unix', 666, [1, 3,5],) in [187]: systems = ('linux', 'windows', 'unix', 666, [1, 3,5], (2,4,6),) in [188]: systems = ('linux', 'windows', 'unix', 666, [1, 3,5], (2,4,6), {'a':250},) # 与列表极为相似
2.元组索引
同列表一样
in [189]: systems = ('linux', 'windows', 'unix',) in [190]: systems[1] out[190]: 'windows'
3.元组切片
同列表一样
in [191]: systems = ('linux', 'windows', 'unix',) in [192]: systems[2:] out[192]: ('unix',)
4.元组组合
同列表一样
in [194]: systems out[194]: ('linux', 'windows', 'unix',) in [197]: systems1 = ('ios',) in [198]: systems + systems1 out[198]: ('linux', 'windows', 'unix', 'ios',) in [200]: systems * 3 out[200]: ('linux', 'windows', 'unix', 'linux', 'windows', 'unix', 'linux', 'windows', 'unix',)
5.元组统计
同列表一样
in [202]: systems = ('linux', 'windows', 'unix',) in [203]: systems.count('linux') out[203]: 1
in [204]: len(systems)
out[204]: 3
元组就这么多o_o ....
上一篇: 京东无货源店群如何运营可以月入2w+?
下一篇: Feign源码解析系列-最佳实践