吉吉:
文章目录
Python序列概述
-
在python中,把大量数据按次序排列而形成的集合体称为序列。Python序列类似于其他语言中的数组,用来存储一系列的多个数据,但功能比数组强大很多。Python中常用的序列结构包含列表、元组、字符串。
-
字典、集合以及range等对象也支持很多序列机构类似的操作,故也列在此处。
-
列表、元组、字符串支持双向索引,第一个元素下标为0,第二个元素下标为1,以此类推;最后一个元素下标为-1,倒数第二个元素下标为-2,以此类推。
-
根据序列结构能否支持索引引用,可分为有序序列和无序序列,根据序列结构是否可变,可分为可变序列和不可变序列
列表
- 列表是Python中内置有序可变序列,列表的所有元素放在一对中括号“[]”中,并使用逗号分隔开;
- 在Python中,一个列表中的数据类型可以各不相同,可以同时分别为整数、实数、字符串等基本类型,甚至是列表、元组、字典、集合以及其他自定义类型的对象。
[10, 20, 30, 40]
['crunchy frog', 'ram bladder', 'lark vomit']
['spam', 2.0, 5, [10, 20]]
[['file1', 200,7], ['file2', 260,9]] #二维列表
[] #空列表
Python采用基于值的自动内存管理模式,变量并不直接存储值,而是存储值的引用或内存地址,这也是python中变量可以随时改变类型的重要原因。同理,Python列表中的元素也是值的引用,所以列表中各元素可以是不同类型的数据。
- 列表元素的访问
示例1:
>>>vehicle = ['train', 'bus', 'car', 'ship']
>>>vehicle [2]
'car'
>>>vehicle [-2]
'car'
- 示例2:二维列表的访问
对二维列表中的元素进行访问,需要使用两对方括号来表示,第一个表示选择列表,第二个在选中列表中再选择元素。
>>> computer=[['IBM','Apple','Lenovo'],['America','America','China']]
>>> computer[0][-1]
'Lenovo'
>>> computer[1][2]
'China'
列表常用方法
列表创建与删除
- 使用“=”直接将一个列表赋值给变量即可创建列表对象
- 创建列表对象
>>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> a_list = [] #创建空列表
- 也可以使用list()函数把元组、range对象、字符串、字典、集合或其他可迭代对象转换为列表。
- 用list()转换为列表
>>> list((3,5,7,9,11))#将元组转换为列表
[3, 5, 7, 9, 11]
>>> list('hello world') #将字符串转换为列表
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
>>> list({3,7,5}) #将集合转换为列表
[3, 5, 7]
>>> list({'a':3, 'b':9, 'c':78}) #将字典的“键”转换为列表
['a', 'c', 'b']
>>> list({'a':3, 'b':9, 'c':78}.items())#将字典的“键:值”对转换为列表
[('b', 9), ('c', 78), ('a', 3)]
>>> x = list() #创建空列表
- 内置函数range()
- 用来创建一个用来生成一系列整数的可迭代对象(整数序列生成器)
- 基本格式:range([start],end[,step])
- 只指定end参数时,生成整数范围为0end-1。指定start时,生成整数范围为startend-1,间隔为step。step默认为1。
range(4) # 生成 0,1,2,3
range(3, 6) # 生成 3, 4, 5
range(1, 10, 2) # 生成 1, 3, 5, 7, 9
range(5, 0, -2) # 生成 5, 3, 1
range(4, 0) # 不能生成任何整数
注意python3中,range() 函数返回的是一个可迭代对象(即可以提供迭代器,对其进行迭代遍历使用的对象 ),而不是列表类型,一般可以用在循环结构中进行迭代遍历,如果是用作列表需要用list()函数进行类型转换。
- range()应用
>>> x=range(3,9,2)
>>> type(x)
<class 'range'>
>>> list(x)
[3, 5, 7]
>>> type(list(x))
<class 'list'>
- 当不再使用时,使用del命令删除整个列表,如果列表对象所指向的值不再有其他对象指向,Python将同时删除该值。
>>> del a_list
>>> a_list
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
a_list
NameError: name 'a_list' is not defined
列表元素的增加
(1)可以使用“+”运算符将元素添加到列表中。
- 用“+”运算符添加元素
>>> aList = [3,4,5]
>>> id(aList)
2038024562568
>>> aList =aList+[7]
>>> aList
[3, 4, 5, 7]
>>> id(aList)
2038024562824
严格意义上来讲,这并不是真的为列表添加元素,而是创建一个新列表,并将原列表中的元素和新元素依次复制到新列表的内存空间。由于涉及大量元素的复制,该操作速度较慢,在涉及大量元素添重点*)
(2)使用列表对象的append()方法,原地修改列表,是真正意义上的在列表尾部添加元素,速度较快。
- 用append()方法添加元素.
>>> aList.append(9)
>>> aList
[3, 4, 5, 7, 9]
所谓“原地”,是指不改变列表在内存中的首地址。也可以使用复合赋值运算符+=实现列表追加元素时属于原地操作,与append()方法一样高效。
- 下面的代码比较了“+”和append()这两种方法的速度差异:
import time
result = []
start = time.time()
for i in range(10000):
result = result + [i]
print(len(result), ',', time.time()-start)
result = []
start = time.time()
for i in range(10000):
result.append(i)
print(len(result), ',', time.time()-start)
在代码中,分别重复执行10000次“+”运算和append()方法为列表插入元素并比较这两种方法的运行时间。在代码中,使用time模块的time()函数返回当前时间,然后运行代码之后计算时间差。
10000 , 0.21801209449768066
10000 , 0.003000020980834961
- Python采用的是基于值的自动内存管理方式,当为对象修改值时,并不是真的直接修改变量的值,而是使变量指向新的值,这对于Python所有类型的变量都是一样的。
>>> a = [1,2,3]
>>> id(a)#返回对象的内存地址
20230752
>>> a = [1,2]
>>> id(a)
20338208
(3)使用列表对象的extend()方法可以将另一个迭代对象的所有元素添加至该列表对象尾部。通过extend()方法来增加列表元素也不改变其内存首地址,属于原地操作。
- 使用extend()方法扩展列表(重点)
>>> aList = [3,4,5,7,9,13]
>>> aList.extend([15,17])
>>> aList
[3,4,5,7,9,13,15,17]
(4)使用列表对象的insert()方法将元素添加至列表的指定位置。
- 使用insert()方法插入元素
>>> aList.insert(3, 6)#在下标为3的位置插入元素6
>>> aList
[3,4,5,6,7,9,11,13,15,17]
- 当列表增加或删除元素时,列表对象自动进行内存的扩展或收缩,并修改索引,从而保证相邻元素之间没有缝隙。Python列表的这个内存自动管理功能可以大幅度减少程序员的负担,但插入和删除非尾部元素时涉及到列表中大量元素的移动,会严重影响效率。
- 在非尾部位置插入和删除元素时会改变该位置后面的元素在列表中的索引,这对于某些操作可能会导致意外的错误结果。
- 所以尽量从列表尾部进行元素的增加与删除操作。
- 列表的insert()可以在列表的任意位置插入元素,但由于列表的自动内存管理功能,insert()方法会涉及到插入位置之后所有元素的移动,这会影响处理速度。类似的还有后面介绍的remove()方法以及使用pop()函数弹出列表非尾部元素和使用del命令删除列表非尾部元素的情况。
- 需要注意的是,列表的功能虽然非常强大,但是负担也比较重,开销较大,在实际开发中,最好根据实际的问题选择一种合适的数据类型,要尽量避免过多使用列表。
(5)使用乘法运算符来扩展列表对象,将列表与整数相乘,生成一个新列表,新列表是原列表中元素的重复。运算符=也可以用于列表元素重复,属于原地操作。
- 使用乘法*复制一个新列表
>>> x = [1, 2, 3, 4]
>>> id(x)
54497224
>>> x = x * 2 #元素重复,返回新列表
>>> x
[1, 2, 3, 4, 1, 2, 3, 4]
>>> id(x) #地址发生改变
54603912
>>> x *= 2 #元素重复,原地进行
>>> x
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
>>> id(x) #地址不变
54603912
- 当使用*运算符将包含列表的列表(多维列表)重复并创建新列表时,并不创建元素的复制,而是创建已有对象的引用。因此,当修改其中一个值时,相应的引用也会被修改。
- 使用乘法*复制一个二维列表
>>> x = [['hello'] * 2] * 3
>>> x
[['hello', 'hello'], ['hello', 'hello'], ['hello', 'hello']]
>>> x[0][0] = 5
>>> x
[[5, 'hello'], [5, 'hello'], [5, 'hello']]
>>> x=[[1,2],[2,3],[3,4]]*3
>>> x
[[1, 2], [2, 3], [3, 4], [1, 2], [2, 3], [3, 4], [1, 2], [2, 3], [3, 4]]
>>> x[0][1]=0
>>> x
[[1, 0], [2, 3], [3, 4], [1, 0], [2, 3], [3, 4], [1, 0], [2, 3], [3, 4]]
列表元素的删除
(1)使用del命令删除列表中的指定位置上的元素。
- 使用del命令删除一个元素
>>> a_list = [3,5,7,9,11]
>>> del a_list[1]
>>> a_list
[3, 7, 9, 11]
(2)使用列表的pop()方法删除并返回指定(默认为最后一个)位置上的元素,如果给定的索引超出了列表的范围则抛出异常。
-
使用pop方法删除一个元素
a_list = list(range(3,13,2))
a_list
[3, 5, 7, 9, 11]a_list.pop()
11a_list
[3, 5, 7, 9]a_list.pop(1)
5a_list
[3, 7, 9]
(3)使用列表对象的remove()方法删除首次出现的指定元素,如果列表中不存在要删除的元素,则抛出异常。 -
使用remove()方法删除一个元素
a_list = [3,5,7,9,7,11]
a_list.remove(7)
a_list
[3, 5, 9, 7, 11] -
代码编写好后必须要经过反复测试,不能满足于几次测试结果正确。例如,下面的代码成功地删除了列表中的重复元素,执行结果是完全正确的。
>>> x = [1,2,1,2,1,2,1,2,1]
>>> for i in x:
if i == 1:
x.remove(i)
>>> x
[2, 2, 2, 2]
- 然而,上面这段代码的逻辑是错误的。同样的代码,仅仅是所处理的数据发生了一点变化,然而当循环结束后却发现并没有把所有的“1”都删除,只是删除了一部分。
>>> x = [1,2,1,2,1,1,1]
>>> for i in x:
if i == 1:
x.remove(i)
>>> x
[2, 2, 1]
- 两组数据的本质区别在于,第一组数据中没有连续的“1”,而第二组数据中存在连续的“1”。出现这个问题的原因是列表的自动内存管理功能。
- 在删除列表元素时,Python会自动对列表内存进行收缩并移动列表元素以保证所有元素之间没有空隙,增加列表元素时也会自动扩展内存并对元素进行移动以保证元素之间没有空隙。每当插入或删除一个元素之后,该元素位置后面所有元素的索引就都改变了。
- 正确的代码:
>>> x = [1,2,1,2,1,1,1]
>>> for i in x[::]: #切片
if i == 1:
x.remove(i)
或者:
>>> x = [1,2,1,2,1,1,1]
>>> for i in range(len(x)-1,-1,-1):
if x[i]==1:
del x[i]
列表元素访问与计数
-
使用下标直接访问列表元素,如果指定下标不存在,则抛出异常。
-
使用下标访问一个元素
>>> a_list = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> aList[3]
6
>>> aList[3] = 5.5
>>> aList
[3, 4, 5, 5.5, 7, 9, 11, 13, 15, 17]
>>> aList[15]
Traceback (most recent call last):
File "<pyshell#34>", line 1, in <module>
aList[15]
IndexError: list index out of range
-
使用列表对象的index()方法获取指定元素首次出现的下标,若列表对象中不存在指定元素,则抛出异常。
-
使用index()访问一个元素
>>> aList
[3, 4, 5, 5.5, 7, 9, 11, 13, 15, 17]
>>> aList.index(7)
4
>>> aList.index(100)
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
aList.index(100)
ValueError: 100 is not in list
-
使用列表对象的count()方法统计指定元素在列表对象中出现的次数
-
使用count()统计元素
>>> aList
[3, 4, 5, 5.5, 7, 9, 11, 13, 15, 17]
>>> aList.count(7)
1
>>> aList.count(0)
0
>>> aList.count(8)
0
成员测试运算符in
- 如果需要判断列表中是否存在指定的值,可以使用count()方法,如果存在则返回大于0的数,如果返回0则表示不存在。
- 也使用更加简洁的成员测试运算符in来判断一个值是否存在于列表中,返回结果为“True”或“False”。
使用in运算来判断
>>> aList
[3, 4, 5, 5.5, 7, 9, 11, 13, 15, 17]
>>> 3 in aList
True
>>> 18 in aList
False
>>> bList = [[1], [2], [3]]
>>> 3 in bList
False
>>> [3] in bList
True
>>> aList = [3, 5, 7, 9, 11]
>>> bList = ['a', 'b', 'c', 'd']
>>> (3, ‘a’) in zip(aList, bList)#判段元组是否存在
True
>>> for a, b in zip(aList, bList):
print(a, b)
内置函数zip()
- 用于将多个列表中元素重新组合为元组并返回包含这些元组的zip对象。
- 从参数中的多个迭代器取元素组合成一个新的迭代器
- 返回:一个zip对象,其内部元素为元组;可以转化成列表或元组
- 传入参数:元组、列表、字典等迭代器
- 使用zip()构造元组的列表
>>> aList = [1, 2, 3]
>>> bList = [4, 5, 6]
>>> cList = zip(aList, bList) #返回zip对象
>>> cList
<zip object at 0x0000000003728908>
>>> list(cList) #把zip对象转换成列表
[(1, 4), (2, 5), (3, 6)]
列表排序
(1)使用列表对象的sort()方法进行原地排序,支持多种不同的排序方法。
- key参数来指定一个函数,此函数将在每个元素比较前被调用,其结果作为排序依据
- reverse参数接受False 或者True 表示是否逆序
- 使用sort()列表排序
>>> x = list(range(11)) #包含11个整数的列表
>>> import random
>>> random.shuffle(x) #把列表x中的元素随机乱序
>>> x
[6, 0, 1, 7, 4, 3, 2, 8, 5, 10, 9]
>>> x.sort()#按默认升序排序
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x.sort(key=str) #按转换为字符串后的大小,升序排序
>>> x
[0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x.sort(key = lambda y:len(str(y))) #按转换成字符串的长度排序
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> x.sort(reverse = True) #按降序排序
>>> x
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
(2)使用内置函数sorted对列表进行排序并返回新列表
- 使用sorted内置函数生成排好序的新列表
>>> aList=[9, 7, 6, 5, 4, 3, 17, 15, 13, 11]
>>> sorted(aList)#升序排序
[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> sorted(aList,reverse = True) #降序排序
[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
sorted函数可用于任意可迭代对象,sort()一般作用于列表(区别)
(3)使用列表对象的reverse()方法将元素原地逆序
- 使用reverse()方法逆序列表
>>> aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> aList.reverse()
>>> aList
[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
(4)使用内置函数reversed对列表元素返回一个逆序后的新的迭代对象,原列表不变。
- 使用reversed()方法逆序列表
>>> aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> newList = reversed(aList) #返回reversed对象
>>> list(newList) #把reversed对象转换成列表
[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
>>> for i in newList:
print(i, end=' ') #这里没有输出内容
#迭代对象已遍历结束
>>> newList = reversed(aList) #重新创建reversed对象
>>> for i in newList:
print(i, end=' ')
17 15 13 11 9 7 6 5 4 3
切片操作
-
切片是Python序列的重要操作之一,适用于列表、元组、字符串、range对象等有序类型。
-
在形式上,切片使用2个冒号分隔的3个数字来完成。
[start:end:step] -
第一个数字start表示切片开始位置(默认为0);
-
第二个数字end表示切片截止(但不包含)位置(默认为列表长度);
-
第三个数字step表示切片的步长(默认为1)。
-
当start为0时可以省略,当end为列表长度时可以省略,当step为1时可以省略,省略步长时还可以同时省略最后一个冒号。
-
当step为负整数时,表示反向切片,此时start默认为-1,end默认为-len(list)-1。
-
切片时一定要保证start到end的方向与步长step的方向同向,否则会切出空的序列 。
(1)使用切片获取列表部分元素
使用切片可以返回列表中部分元素组成的新列表。与使用索引作为下标访问列表元素的方法不同,切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表,代码具有更强的健壮性。
- 列表切片操作
>>> aList = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> aList[::] #返回包含原列表中所有元素的新列表
[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
>>> aList[::-1] #返回包含原列表中所有元素的逆序列表
[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
>>> aList[::2] #隔一个取一个,获取偶数位置的元素
[3, 5, 7, 11, 15]
>>> aList[1::2] #隔一个取一个,获取奇数位置的元素
[4, 6, 9, 13, 17]
>>> aList[3::] #从下标3开始的所有元素
[6, 7, 9, 11, 13, 15, 17]
>>> aList[3:6] #指定切片的开始和结束位置,即下标在[3, 6)之间的所有元素
[6, 7, 9]
>>> aList[0:100] #切片结束位置大于列表长度时,从列表尾部截断
#0 1 2 3 4 5 6 7 8 9正向索引
[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
#-10-9 -8 -7 -6 -5 -4 -3 -2 -1反向索引
>>> a[100:] #切片开始位置大于列表长度时,返回空列表
[]
>>> x[100]#直接使用下标访问会发生越界
IndexError: list index out of range
>>> aList[3:-10:-1] #位置3在位置-10的右侧,-1表示反向切片
[6, 5, 4]
>>> aList[3:-5] #位置3在位置-5的左侧,正向切片
[6, 7]
>>> aList
(2)使用切片为列表增加元素
可以使用切片操作在列表任意位置插入新元素,不影响列表对象的内存地址,属于原地操作。
- 利用切片操作修改原列表。
>>> aList = [3, 5, 7]
>>> aList[len(aList):]
[]
>>> aList[len(aList):] = [9] #在列表尾部增加元素
>>> aList[:0] = [1, 2] #在列表头部插入多个元素
>>> aList[3:3] = [4] #在列表中间位置插入元素
>>> aList
[1, 2, 3, 4, 5, 7, 9]
- 使用切片替换和修改列表中的元素
- 利用切片操作修改原列表。
>>> aList = [3, 5, 7, 9]
>>> aList[:3] = [1, 2, 3] #替换列表元素,等号两边的列表长度相等
>>> aList
[1, 2, 3, 9]
>>> aList[3:] = [4, 5, 6] #切片连续,等号两边的列表长度可以不相等
>>> aList
[1, 2, 3, 4, 5, 6]
>>> aList[::2] = [0]*3 #隔一个修改一个
>>> aList
[0, 2, 0, 4, 0, 6]
>>> aList[::2] = ['a', 'b', 'c']#隔一个修改一个
>>> aList
['a', 2, 'b', 4, 'c', 6]
>>> aList[1::2] = range(3) #序列解包的用法
>>> aList
['a', 0, 'b', 1, 'c', 2]
>>> aList[1::2] = zip('abc', range(3))
#map、filter、zip对象都支持这样的用法
>>> aList
['a', ('a', 0), 'b', ('b', 1), 'c', ('c', 2)]
>>> aList[::2] = [1]
#切片不连续时等号两边列表长度必须相等
ValueError: attempt to assign sequence of size 1 to extended slice of size 3
- (4)使用切片删除列表中的元素
>>> aList = [3, 5, 7, 9]
>>> aList[:3] = [] #删除列表中前3个元素
>>> aList
[9]
也可以结合使用del命令与切片来删除列表中的部分元素,并且切片元素可以不连续。
>>> aList = [3, 5, 7, 9, 11]
>>> del aList[:3] #切片元素连续
>>> aList
[9, 11]
>>> aList = [3, 5, 7, 9, 11]
>>> del aList[::2] #切片元素不连续,删偶数位元素
>>> aList
[5, 9]
列表推导式
- 列表推导式提供了一种创建list的简便方法。列表推导式使用非常简洁的方式来快速生成满足特定需求的列表,代码具有非常强的可读性。列表推导式在逻辑上等价于一个循环语句,只是形式上更加简洁。
>>> aList = [x*x for x in range(10)]
相当于
>>> aList = []
>>> for x in range(10):
aList.append(x*x)
>>> aList
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
-
freshfruit = [’ banana’, ’ loganberry ', 'passion fruit ']
aList = [w.strip() for w in freshfruit] -
等价于下面的代码
>>> aList = []
>>> for item in freshfruit:
aList.append(item.strip())
阿凡提与国王比赛下棋,国王说要是自己输了的话阿凡提想要什么他都可以拿得出来。阿凡提说那就要点米吧,棋盘一共64个小格子,在第一个格子里放1粒米,第二个格子里放2粒米,第三个格子里放4粒米,第四个格子里放8粒米,以此类推,后面每个格子里的米都是前一个格子里的2倍,一直把64个格子都放满。需要多少粒米呢?
>>> sum([2**i for i in range(64)])
18446744073709551615
>>> int('1'*64, 2)
18446744073709551615
1)实现嵌套列表的平铺
>>> vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
- 在这个列表推导式中有2个循环,其中第一个循环可以看作是外循环,执行的慢;而第二个循环可以看作是内循环,执行的快。上面代码的执行过程等价于下面的写法:
>>> vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> result = []
>>> for elem in vec:
for num in elem:
result.append(num)
>>> result
[1, 2, 3, 4, 5, 6, 7, 8, 9]
(2)过滤不符合条件的元素
在列表推导式中可以使用if子句对列表中的元素进行筛选,只在结果列表中保留符合条件的元素。下面的代码可以列出当前文件夹下所有Python源文件:
>>> import os
>>> [filename for filename in os.listdir('.') if filename.endswith(('.py', '.pyw'))]
下面的代码用于从列表中选择符合条件的元素组成新的列表:
>>> aList = [-1, -4, 6, 7.5, -2.3, 9, -11]
>>> [i for i in aList if i>0] #所有大于0的数字
[6, 7.5, 9]
- 问题解决:已知有一个包含一些同学成绩的字典,现在需要计算所有成绩的最高分、最低分、平均分,并查找所有最高分同学,代码可以这样编写:
>>> scores = {"Zhang San": 45, "Li Si": 78, "Wang Wu": 40, "Zhou Liu": 96, "Zhao Qi": 65, "Sun Ba": 90, "Zheng Jiu": 78, "Wu Shi": 99,"Dong Shiyi": 60}
>>> highest = max(scores.values()) #最高分
>>> lowest = min(scores.values())#最低分
>>> average = sum(scores.values()) / len(scores) #平均分
>>> highest, lowest, average
(99, 40, 72.33333333333333)
>>> highestPerson = [name for name, score in scores.items() if score == highest] #items()方法返回字典的“键-值对”列表
>>> highestPerson
['Wu Shi']
(3)同时遍历多个列表或可迭代对象
>>> [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
>>> [(x, y) for x in [1, 2, 3] if x==1 for y in [3, 1, 4] if y!=x]
[(1, 3), (1, 4)]
- 对于包含多个循环的列表推导式,一定要清楚多个循环的执行顺序或“嵌套关系”。例如,上面第一个列表推导式等价于
>>> result = []
>>> for x in [1, 2, 3]:
for y in [3, 1, 4]:
if x != y:
result.append((x,y))
>>> result
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
(4)使用列表推导式实现矩阵转置*
>>> matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
上面列表推导式的执行过程等价于下面的代码
>>> matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
>>> result = []
>>> for i in range(len(matrix[0])):
result.append([row[i] for row in matrix])
>>> result
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
(5)列表推导式中可以使用函数或复杂表达式
>>> def f(v):
if v%2 == 0:
v = v**2
else:
v = v+1
return v
>>> [f(v) for v in [2, 3, 4, -1] if v>0]
[4, 4, 16]
>>> [v**2 if v%2 == 0 else v+1 for v in [2, 3, 4, -1] if v>0]
[4, 4, 16]
>>> x = list(range(10))
>>> [item>5 for item in x]
[False, False, False, False, False, False, True, True, True, True]
序列操作的常用内置函数
- len(列表):返回列表中的元素个数。
- max(列表)、 min(列表):返回列表中的最大或最小元素。
- sum(列表):对列表的元素进行求和运算,对非数值型列表运算需要指定start参数
- 以上内置函数同样适用于元组、字典、集合、字符串、range对象等。
>>> x=range(1, 11)
>>> len(x)
10
>>> sum(range(1, 11)) #sum()函数的start参数默认为0
55
>>> sum(range(1, 11), 5)#指定start参数为5,等价于5+sum(range(1,11))
60
>>> sum([[1, 2], [3], [4]], []) #指定start参数为[],等价于[]+[1, 2]+[3]+ [4]
[1, 2, 3, 4] # 这个操作占用空间较大,慎用
>>> x = list(range(11)) #生成列表
>>> import random
>>> random.shuffle(x)#打乱列表中元素顺序
>>> x
[0, 6, 10, 9, 8, 7, 4, 5, 2, 1, 3]
>>> all(x) #测试是否所有元素都等
价于True
False
>>> any(x) #测试是否存在等价于
True的元素
True
>>> max(x) #返回最大值
10
>>> max(x, key=str) #按指定规则返回最大值
9
>>> min(x)
0
- enumerate(列表):枚举列表元素,返回一个可迭代的枚举对象,其中每个元素为包含下标和值的元组。
- 该函数对元组、字符串等所有可迭代对象同样有效。
>>> for i in enumerate('abcdef'):
print(i,end=' ')
(0, 'a') (1, 'b') (2, 'c') (3, 'd') (4, 'e') (5, 'f')
>>> for x,y in enumerate('abcdef'):
print((x,y),end=' ')
(0, 'a') (1, 'b') (2, 'c') (3, 'd') (4, 'e') (5, 'f')