之前,我们已经探讨过字符串的相关操作了(Python–字符串)。列表和字符串相同,他也是一种序列,所谓序列,就是按照一定顺序存储对象的容器,容器中的每个序列都被默认存在一个下标(索引)与之对应。从这个角度讲,列表当然和字符串在序列的性质方面是有相同之处的。不过他们的不同之处更多,比如在存储的方式上,存储对象的类型上等等。
列表也是一种序列
我们发现,列表在创建和访问上,满足和字符串类似的性质。
1. 列表的创建
和建立字符串一样,分为两种:直接赋值以及通过 list() 函数
alist = [1,2,"we",[12.5,"how"]] # >>> 由四个元素构成的列表
alist = [] # >>> 空列表
alist = list("123") # >>> ["1","2","3"]
列表由中括号 “[ ]” 里面写入对象的形式表示,不同的对象之间由 “,” 隔开,当然,如果中括号内什么都没有,就表示创建了一个空列表。我们可以发现,Python中列表的一个显著特征是它里面可以存储任何类型的对象(整型,浮点型,字符串,甚至是列表自己等等),而不像字符串,只能存储字符。
另外,需要注意的是,使用 list() 函数时,传入的参数一定得是可迭代的,比如传入整数,浮点数,就一定会报错。
2. 列表的访问
两种方法:通过下标;通过切片
alist = [1,3,4,5]
alist[-1] # >>> 5
alist[0:2] # >>> [1,2]
alist[0::2] # >>> [1,5]
alist[::-1] # >>> [5,1]
和字符串一样,索引的设置也是从0开始的,而且同样存在正索引和负索引。切片也一样是由三个3个参数构成[begin : end : step],具体的设置和字符串中是一模一样的,在此不赘述(参见:Python–字符串)
相关操作
我们已经知道字符串是不可变的,也就是说,我们所做的关于对字符串的更新操作,其实都是通过新建一个新的字符串对象实现的。但是列表则方便的多,他是可变的,你可以随时添加、删除、修改列表中的元素。再加上我们上面谈到的列表可以存储任意类型的对象,那么,其实可以想象,列表为我们提供的这种非常便捷的数据存储结构,一定会大大简化程序的编写。
1. 添加
append() 函数可以实现直接向列表的末尾添加元素,而且语法非常简单。
alist = []
alist.append(1) # >>> alist = [1]
alist.append("we") # >>> alist = [1,"we"]
注意,此时就是列表alist本身改变了,而不是新建了另一个列表,这一点和字符串有着本质区别。
2. 插入
append() 函数只能在列表的末尾添加元素,而有时,我们需要在一些特定的位置插入元素,这就需要用到 insert() 函数。
alist = ["I","Python"]
alist.insert(1,"wrote") # 在位置1处插入字符串对象 "wrote"
print(alist) # >>> ["I","wrote","Python"]
insert() 函数的结构时这样的:insert(index,obj). 第一个参数表示要插入的位置,第二个参数表示要插入的元素
3. 删除
两种删除方法:remove(obj) 和 pop(index)
从两个函数的参数就可以看出使用场景的不同。如果我们已知要删除对象本身的值,则使用 remove(obj) 直接删除,而如果知道要删除对象的位置,则使用 pop(index) 根据索引删除元素,如果没有给出要删除的索引,则默认索引为-1,也就是删除列表的最后一个元素。
我们具体来看看怎么用
alist = [1,1,5,6]
alist.remove(1) # >>> 删除第一个为1的元素
print(alist) # >>> [2,6]
alist.pop(0) # >>> 删除index = 0的元素,也就是现在alist里面的2
print(alist) # >>> [1,6]
需要注意的是,remove(obj) 函数是没有返回值的(或者说他的返回值是 None),比如:
alist = [1,6]
print(alist.remove(1)) # >>> None
# >>> 因为只是删除了alist中第一个值为1的元素,但是函数本身并没有返回值
而 pop(index) 函数会返回被删除的那个值:
alist = [1,6]
print(alist.pop()) # >>> 6
# >>> 返回被删除的那个元素
4. 修改
通过下标,可以修改列表相应的元素
alist = [1,4]
alist[1] = 3 # >>> [1,4]
alist[-1] = 3 # >>> [1,9]
当然,也可以通过切片实施批量修改,但是,这种方式要尽量避免使用。
alist = [1,4]
alist[0:2] = [3,4]
print(alist) # >>> [3,4]
因为稍不注意,就会出错,比如还是刚才的例子:
alist = [1,4]
b = alist[0:2] # >>> b = [1,2]; 相当于把alist的一部分复制了,然后用b引用
b[1] = 3
print(b) # >>> [1,3]
print(alist) # >>> [1,4] alist并未改变
所以应尽量避免这种批量修改。
5. 拓展
我们也可以将一个列表与另一个列表(也可以是别的序列)合并,合并方式有两种:
(1) extend() 函数
alist = [1,4]
alist.extend([5,6,7,8])
print(alist) # >>> [1,8]
alist.extend("we")
print(alist) # >>> [1,8,"w","e"]
extend() 函数实际上是给原列表添加了内容,而并没有建立新的列表。
(2) + 操作符
+ 操作符在列表中的作用和字符串中一样,表示连接。且只能在相同类型的对象间操作,列表的 + 就只能加列表
alist = [1,4]
alist += [5,8]
print(alist) # >>> [1,8]
需要注意的是,对一个列表使用 + 操作符必须要对这个加之后的结果(实际上是一个新对象)赋值。这一点和整数,浮点数的加法以及字符串的链接是一样的。比如,像下面的操作就是非法的:
alist = [1,3]
alist + [4,5] # >>> invalid!
6. 操作符
上面的拓展当中,已经介绍了 + 操作符,和字符串的设定一样,列表还有重复操作符 * 和成员操作符 in,not in,使用方式也和字符串中一样,这里,只是给出例子
alist = [1,2]
alist *= 3
print(alist) # >>> [1,2]
print(1 in alist) # >>> True
print(2 not in alist) # >>> True
常用函数
上面已经介绍了一些列表的相关内建函数:append(),remove(),pop(),extend(),insert(),下面,我再介绍一些别的。
1. 长度和大小值
alist = [3,9,8]
# len()函数求取列表长度
print(len(alist)) # >>> 5
# max(),min()求取列表最大最小值
print(max(alist)) # >>> 9
print(min(alist)) # >>> 1
求大小值的时候,需要列表所存储的元素是同一种类型,或者是可比较大小的不同类型(比如整型和浮点)。
2. 翻转和排序
字符串是不可变类型,所以,对字符串的翻转其实是新建了一个对象,而列表可变,所以,我们可以实现对列表本身的翻转和排序。
(1) 翻转
alist = [1,5]
alist.reverse() # 翻转列表,但是这个函数本身没有返回值,只是翻转了列表
print(alist) # >>> [5,1]
当然,我们还可以通过函数 reversed() 生成一个新的经过翻转的列表,而不改变原列表。
alist = [1,5]
temp = reversed(alist) # >>> 新生成了一个对象,而且这个对象不是list型的,但是可以通过for循环访问
for i in temp:
print(i) # >>> 依次输出: 5,1
print(alist) # >>> [1,5],原列表不变
用切片的方式,也能实现列表的翻转
alist = [1,5]
temp = alist[::-1] # temp是一个新生成的列表
print(temp) # >>> [5,1]
print(alist) # >>> [1,原列表不变
(2) 排序
和求取列表的最大最小值类似,对列表排序时,也得要求列所存储的元素是同一类型或者可比较的不同类型。
两个函数可实现排序:sort(),sorted()
alist = [3,8]
alist.sort() # >>> 对alist原地排序(按升序),但是函数本身没有输出,只是完成了一个功能,跟reverse()类似
print(alist) # >>> [1,9]
alist = [3,8]
b = sorted(alist) # >>> 新建了一个列表b,b是alist排好序的样子
print(b) # >>> [1,9]
print(alist) # >>> [3,8] 原列表alist未变
注意:sorted() 函数跟之前的 reversed() 函数不同,sorted() 就是直接生成了一个新的list,不用通过for循环,也能直接打印出来。
当然,sort() 函数虽是默认升序排列,但我们也能通过更改相应的参数实现降序排列。
alist = [3,8]
alist.sort(reversed=True) # >>> 设置参数reversed=True实现降序排列
print(alist) # >>> [9,1]
其实,sort() 函数的使用通过设置参数还有很多变型,这个等我们以后讲到具体问题时再说吧。
3. 求和和统计
(1) 列表通过 sum() 函数完成求和,当然,要满足列表所存储的元素都是整型或浮点
alist = [1,45,56,2.33]
print(sum(alist)) # >>> 104.33
(2) 列表通过 count() 函数完成对列表中元素的统计
alist = [1,[1,2],2]]
print(alist.count(1)) # >>> 2
print(alist.count([1,2])) # >>> 2
print(alist.count([2,1])) # >>> 0
4. 清空和复制
(1) 清空
直接赋值一个空列表是可以的,但是这样做的原理相当于是让变量名去引用了一个新的空的列表,并不是真正意义上的清空
alist= [1,3]
alist = [] # >>> 引用了一个新的空的列表
print(alist) # >>> []
真正意义上清空列表可以使用 clear() 函数
alist= [1,3]
print(id(alist)) # >>> 4328406280
alist.clear()
print(alist) # >>> []
print(id(alist)) # >>> 4328406280,同一个位置,说明是原地清空
(2) 复制
两种方法可以实现:切片及 copy() 函数
切片 [:]
alist= [1,3]
b = alist[:]
b[0] = 8
print(b) # >>> [8,3] 修改b,alist不受影响
函数 copy()
alist= [1,3]
b = alist.copy()
print(id(alist)) # >>> 4362226952
print(id(b)) # >>> 4362264520<
和切片的方法一样,在另一个位置复制了列表
5. enumerate() 和 zip()
关于这两个函数的使用和字符串一样,具体参见之前的博文吧(Python–字符串),这里,只是给出例子:
a = ["I","he","she"]
b = ["my","his","her"]
for i,j in enumerate(a):
print(i,j) # >>> 依次输出 0 "I",1 "he",2 "she"
for i,j in zip(a,b):
print(i,j) # >>> 依次输出 "I" "my","she","her"
需要注意的一点是,如果想把多个多个元素通过一个序列的方式传递给 zip() 函数,是需要在这个序列名前面加 * 的,否则不会出现我们想要的结果:
a = [[1,3],[4,6],[7,9]]
for i in zip(*a):
print(i) # >>> 依次输出 (1,7),(2,8),(3,9)
而如果不加 *,函数会认为只有一个输入
a = [[1,9]]
for i in zip(a):
print(i) # >>> 依次输出 ([1,),([4,([7,9],)