列表与元组
列表是用于存储任意数目、任意类型的数据的一种数据结构,它是内置可变序列,是包含多个元素的有序连续内存空间。
若:a=[10, 20, 30, 40],则a是列表的引用,a[0]是10的引用,如图:
>>> a = [10, 2.5, 'Jim'] # 可以将不同类型的对象放到同一个列表中
>>> b = [] # 创建一个空列表
>>> type(range(4)) # range()返回的是一个 range 对象,而不是列表。
<class 'range'>
>>> list(range(4))
[0, 1, 2, 3]
>>> list('abcd')
['a', 'b', 'c', 'd']
形式为:[参数表达式 for语句],for语句表示参数如何取
>>> a = [x*2 for x in range(5)] # 循环创建多个元素,for语句表示参数如何取
>>> a
[0, 2, 4, 6, 8]
>>> a = [x*2 for x in range(100) if x%9==0] # 通过 if 过滤元素
>>> a
[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
>>> [x*x for x in range(1,11)] # 生成1-10的平方
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
range函数也有类似于切片的功能,range([start,] end [,step]) 生成一个数字序列(range对象,不是列表),用法与字符串切片类似。
>>> a = [20,40]
>>> a.append(50)
>>> a
[20, 40, 50]
>>> a = [10,20,30]
>>> a.insert(2,100)
>>> a
[10, 20, 100, 30]
>>> a = [10,20,30,40,50]
>>> a.pop()
>>> a = [100,200,888,300,400]
>>> del a[1]
>>> a
[100,200,300,400]
>>> a = [10,20,30,40,50,20,30,20,30]
>>> a.remove(20) # 删除列表中的第一个20,后面的20不删除
>>> a
[10, 30, 40, 50, 20, 30, 20, 30]
除非必要,我们一般只在列表的尾部添加元素或删除元素,因为不需要移动元素,可以大大提高列表的操作效率,也就是说,推荐使用append和pop。
start 和 end 指定了搜索的范围,返回待查元素在列表中首次出现的索引,没查到则报错。
>>> a = [10,20,30,40,50,20,30,20,30]
>>> a.index(20)
1 >
>> a.index(20,3)
5 >
>> a.index(20,3) #从索引位置 3 开始往后搜索的第一个 20
5 >
>> a.index(30,5,7) #从索引位置 5 到 7 这个区间,第一次出现 30 元素的位置
6
>>> a = [10,20,30,40,50,20,30,20,30]
>>> a.count(20)
3
a.直接用加号(+)拼接,生成新的列表
>>> a = [20,40]
>>> id(a)
46016072
>>> a = a+[50]
>>> id(a)
46015432
b.使用extend()方法,原地操作,不创建新的列表对象,推荐使用。
>>> a = [20,40]
>>> id(a)
46016072
>>> a.extend([50,60])
>>> id(a)
46016072
>>> a = [10, 20, 30, 40]
>>> id(a)
47203584
>>> a[1] # 直接通过索引来访问
20
>>> a[2] = 55 # 直接通过索引来修改
>>> a
[10, 20, 55, 40]
>>> id(a)
47203584
访问的时候,可以通过索引访问任意元素,直接修改中间某个元素,并不会生成新的列表,因为仅仅是修改列表元素的指向地址。
与字符串切片完全相同,都是 start:end:step形式
>>> a = [20,10,30,40]
>>> id(a)
46017416
>>> a.sort() # 默认是升序排列
>>> a
[10, 20, 30, 40]
>>> a = [10,20,30,40]
>>> a.sort(reverse=True) # 降序排列
>>> a
[40, 30, 20, 10]
>>> import random # 导入random模块
>>> random.shuffle(a) # 打乱顺序
>>> a
[20, 40, 30, 10]
>>> a = [20,10,30,40]
>>> id(a)
40632704
>>> b = sorted(a) # 默认升序
>>> b
[10, 20, 30, 40]
>>> id(b)
47203840
>>> c = sorted(a, reverse=True) # 降序
>>> c
[40, 30, 20, 10]
>>> id(c)
40634688
可以看到,生成的列表对象 b 和 c 都是完全新的列表对象。
min求列表最小值,max求最大值。(这两个函数也能对字符串使用,比较的是对应Unicode码)
len求长,len对可迭代对象都能使用。
sum求和,只能对数值型列表使用,对非数值型列表运算则会报错。
>>> a = [2, 1, 3, 5, 7]
>>> min(a)
1
>>> max(a)
7
>>> len(a)
5
>>> sum(a)
18
列表中的元素,可以是任意类型的对象,因此列表中的元素也可以是列表类型,这就是多维列表,即列表的嵌套。
>>> a = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
>>> a[1][1] # 访问子列表的元素
5
>>> a[1]
[4, 5, 6]
查找和增删的时候,需要告诉解释器,具体要在哪个列表里查,是大列表,还是子列表,哪一层子列表,哪个子列表,都要说清楚。
>>> a = [[[1, 2, 3],[4, 5, 6]],
[[7, 8, 9], [10, 11, 12]]]
>>> a[1][1]
[10, 11, 12]
>>> a[1][1].index(10)
0
元组与列表相似,但元素属于不可变数据类型,一旦定义,就不可变,因此可以认为元组是“不可变的列表”。
a.直接通过圆括号( )创建
a = (10,20,30) 或者 a = 10,20,30
如果元组只有一个元素,则必须后面加逗号。这是因为解释器会把(1)解释为整数 1
>>> a = () # 创建一个空元组
>>> a
()
>>> a = (1)
>>> type(a)
<class 'int'>
>>> a = (1,) #或者 a = 1,
>>> type(a)
<class 'tuple'>
b.通过 tuple()创建
b = tuple() #创建一个空元组对象
b = tuple("abc")
b = tuple(range(3))
b = tuple([2,3,4])
c.生成器推导式创建
>>> s = (x*2 for x in range(5)) # 生成器推导式使用小括号
>>> s
<generator object <genexpr> at 0x0000000002BDEB48>
>>> tuple(s)
(0, 2, 4, 6, 8)
>>> tuple(s) # 生成器对象只能使用一次,第二次无法使用
()
生成器推导式创建元组,生成的是生成器对象,还需要tuple()函数将其转化成元组,而列表推导式创建列表,则能直接生成列表。
元组的内存形式、访问、切片、查找、求长、最大最小、求和等,与列表完全一致,这里不再赘述。
这里要注意列表的排序,它只支持使用python内置函数sorted进行排序,而且返回的是列表。
>>> a = (1, 2, 3, 5, 7)
>>> sorted(a)
[1, 2, 3, 5, 7]
列表、元组同样有很多方法和函数,都不用刻意的去记,只需要记住前者可变、后者不可变就行了,要用的时候临时查,用得多了,自然就记住了。