一、列表使用【重点掌握】
1.概念
变量:使用变量存储数据,但是,缺点:一个变量每次只能存储一个数据
思考:如果一次性存储多个数据,怎么做?
实际问题:存储5个人的年龄,求他们的平均年龄,按照以前的方式解决:
age1 = 10
age2 = 18
age3 = 9
age4 = 15
age5 = 20
average = (age1 + age2 + age3 + age4 + age5) / 5继续思考:如果要存储100,甚至1000个人的年龄呢?
解决方案:此时采用定义变量的方式会显得很麻烦,而Python提供了一种解决方案,使用列表进行多个数据的存储
作用:列表相当于是一个容器,可以同时存储多个数据
本质:列表是一个有序的集合
说明:有序指的就是有顺序【数据的存放的顺序和底层存储的顺序是相同的】
2.基本使用
2.1定义列表
1.定义列表
列表是一种数据类型,定义列表相当于定义一个列表的变量
语法:列表名 = [数据1....]
说明:列表使用list表示,但是,列表名不要直接使用list【list()】,建议listxxx或者xxxlist
a.定义空列表
list1 = []
print(list1)
b.定义非空列表
*注意:列表是有序的集合,数据的存放顺序和内存中的存储顺序相同
list2 = [34,6,56,57,7]
print(list2)
c.列表中可以存储重复数据
list3 = [22,33,44,22,22,22,22]
print(list3)
d.列表中可以同时存储不同类型的数据
list4 = ["hello",10,45.9,True]
print(list4)
2.2列表元素获取
2.列表元素的访问
"""
注意:
a.列表中存储的数据被称为元素
b.列表是有序的,所以列表中的元素被依次进行了编号,编号从0开始,
这个编号被称为索引,下标或者角标
c.索引的取值范围:
0 ~ 列表元素个数 - 1
-1 ~ -(元素个数)
d.如果超出索引的范围,则会报错IndexError
"""
nameList = ["tom","jack","bob","rose","zhangsan"]
print(nameList)
a.获取元素
语法:列表名[索引]
n1 = nameList[2]
print(n1)
print(nameList[2])
print(nameList[4])
*注意1:如果使用了超出范围的下标,则会报错
print(nameList[10]) #IndexError: list index out of range 索引越界
*注意2:下标的表示可以使用正数【从左向右】,也可以使用负数【从右向左】
print(nameList[-1])
print(nameList[-5])
#print(nameList[-6]) #IndexError: list index out of range
nameList = ["tom","jack","bob","rose","zhangsan"]
print(nameList)
b.修改元素
语法:列表名[索引] = 值
print(nameList[1])
nameList[1] = "蔡徐坤" #注意:修改列表元素相当于给变量重新赋值
print(nameList[1])
print(nameList)
#结论:列表是一种可变的数据类型,其中的元素可以随时修改
2.3列表基本操作
列表基本操作
#1.列表组合:+
list1 = [2,3,4]
list2 = [7,8]
print(list1 + list2)
print(list1)
#2.列表元素的重复:*
print(list1 * 3)
print(list1)
#结论:列表组合和列表元素的重复都是生成了一个新的列表,对原列表没有任何影响
print("=" * 30)
#3.判断元素是否在列表中:
# a.成员运算符【in , not in】,一般结合if语句和for循环使用
list3 = [2, 3, 4, 7, 8]
print(3 in list3) #True
print(6 in list3) #False
print(3 not in list3) #False
print(6 not in list3) #True
if 3 in list3:
print("3在列表中")
# b.身份运算符【is , is not】,判断两个变量的地址是否是同一个
a = 10
b = 10
print(a is b) #True
list1 = [1,2,3]
list2 = [1,2,3]
print(list1 is list2) #False
print(list1 == list2) #True
"""
注意:
a.变量中实际存储的是地址
比如:10的地址假设为:2343455
a和b中存储的是2343455
list1和list2是两个容器,只是其中的内容相同
2.4列表切片
4.列表切片
概念:通过开始下标,结束下标以及步长获取一个子列表
语法:列表名[start:end:step]
a.start可以省略,默认从0开始
b.end可以省略,默认为最后一个下标
c.step可以省略,默认为1
d.可以根据具体的情况选择性省略
e.注意:前闭后开区间【包头不包尾】
list1 = [11,22,33,44,55,66,77,88,99]
a.获取指定区间,而且下标都是正数,省略step
sublist1 = list1[1:4] #指定区间
sublist1 = list1[1:] #从指定下标开始到结尾
sublist1 = list1[:4] #从开头到指定下标
b.获取指定区间,而且下标都是正数,定义step
sublist1 = list1[1:4:2]
sublist1 = list1[1::2]
sublist1 = list1[:4:2]
list1 = [11,22,33,44,55,66,77,88,99]
c.获取指定区间,而且下标都是负数
sublist1 = list1[-1:-4] #[]
sublist1 = list1[-1:] #只获取最后一个元素
sublist1 = list1[:-4] #[11, 22, 33, 44, 55]
sublist1 = list1[-1:-4:-1]
print(sublist1)
sublist1 = list1[-1::-1]
print(sublist1)
sublist1 = list1[:-4:-1]
print(sublist1)
sublist1 = list1[-4:-1:-1]
print(sublist1)
sublist1 = list1[-4::-1]
print(sublist1)
sublist1 = list1[:-1:-1]
print(sublist1)
list1 = [11,22,33,44,55,66,77,88,99]
print(list1[::])
print(list1[::1])
print(list1[::-1]) #倒序
切片
list1 = [11,22,33,44,55,66,77,88,99]
print(list1[-1]) #获取元素
一、一般情况
*注意:start和end写出来,遵循前闭后开
... -4 -3 -2 -1 0 1 2 3 4 ...
1.省略step
print(list1[0:3]) #[11, 22, 33]
print(list1[:3]) #[11, 22, 33]
print(list1[0:]) #[11, 22, 33, 44, 55, 66, 77, 88, 99]
list1 = [11,22,33,44,55,66,77,88,99]
2.start和end为负数
print(list1[-1:-4:1])
print(list1[-1:-4:])
print(list1[-1:-4:-1])
print(list1[-4:-1:1]) #[66 77 88]
print(list1[-4:-1:]) #[66 77 88]
print(list1[-4:-1:-1]) #[]
list1 = [11,22,33,44,55,66,77,88,99]
3.start和end为正数
print(list1[1:4:1]) #[22, 33, 44]
print(list1[1:4:]) #[22, 33, 44]
print(list1[1:4:-1]) #[]
4.start和end可以为正数,也可以为负数【特殊情况】
11 22 33 44 55 66 77 88 99 元素
0 1 2 3 4 5 6 7 8 正索引
-9 -8 -7 -6 -5 -4 -3 -2 -1 负索引
print(list1[1:-4]) #[22, 33, 44, 55]
print(list1[1:-4:-1]) #[]
print(list1[-1:4]) #[]
print(list1[-1:4:-1]) #[99, 88, 77, 66]
print(list1[-1:-5:-1]) #[99, 88, 77, 66]
总结:如果start和end没有省略,start + step的结果判断是否在指定区间内
二、特殊情况
list1 = [11,22,33,44,55,66,77,88,99]
1.
print(list1[100:]) # []
2.
print(list1[0:-1]) #[11, 22, 33, 44, 55, 66, 77, 88]
print(list1[0:8]) #[11, 22, 33, 44, 55, 66, 77, 88]
3.
print(list1[4:100]) #[55, 66, 77, 88, 99]
print(list1[4:]) #[55, 66, 77, 88, 99]
4.
print(list1[::1]) #[11, 22, 33, 44, 55, 66, 77, 88, 99]
print(list1[::-1]) #[99, 88, 77, 66, 55, 44, 33, 22, 11] 【面试题】,倒序
5
print(list1[-1:0]) #[]
print(list1[-1:0:-1]) #[99, 88, 77, 66, 55, 44, 33, 22]
6.
print(list1[-4::-1])
3.系统功能
函数 说明 len(list) 获取列表元素个数 max(list) 返回列表元素最大值 min(list) 返回列表元素最小值 list(seq) 将元组转换为列表 list.append(obj) 在列表末尾添加新的对象 list.count(obj) 统计某个元素在列表中出现的次数 list.extend(seq) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) list.index(seq) 从列表中找出某个值第一个匹配项的索引位置 list.insert(index,obj) 将对象插入列表 list.pop(index) 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值 list.remove(obj) 移除列表中某个值的第一个匹配项 list.reverse() 反向列表中元素 list.sort(key=None,reverse=False) 对原列表进行排序 list.copy() 复制列表 list.clear() 清空列表
Python中系统提供了一些操作列表的系统功能【函数】,可以帮助完成一些操作
列表是一种可变的数据类型,可以进行增删改的操作
1.增
a.list.append(x),在列表末尾追加一个元素,x可以是任意类型
list11 = [1,2,3]
list11.append(4)
list11.append(False)
list11.append("abc")
list11.append([33,55])
print(list11)
b.list.extend(x),在列表末尾追加一个元素,x必须是一个容器【集合,序列】
list12 = [1,2,3]
print(list12)
*注意:可迭代对象包括字符串,列表,元组,字典,集合
list12.extend(5) #TypeError: 'int' object is not iterable可迭代对象
print(list12)
list12.extend([5])
print(list12)
list12.extend("abc")
print(list12)
总结;append和extend如果添加的是容器,append将容器直接添加进去,而extend只添加元素
c.list.insert(index,x),在列表的指定为值上插入指定的元素
list13 = [1,2,3]
print(list13)
list13.insert(1,10)
print(list13)
*注意:如果插入的时候index超出下标范围,则默认在列表末尾插入元素
list13.insert(6,8)
print(list13)
list13.insert(2,[33,55])
print(list13)
list13.insert(3,"hello")
print(list13)
总结:extend只能添加容器,而且将容器中的数据打碎加入,
append和insert可以添加任意类型的数据,直接加入
2.删
a.list.remove(x),移除列表中的指定元素,如果出现重复元素,只会删除一个
list21 = [1, 10, 2, 3, 8,2,2,2]
print(list21)
list21.remove(2)
print(list21)
*注意:如果元素不存在,则报错
list21.remove(666) #ValueError: list.remove(x): x not in list
print(list21)
b.list.pop(index=-1) ,删除指定位置上的元素,如果不给值,则默认删除最后一个元素
list22 = [1, 10, 2, 3, 8]
print(list22)
list22.pop()
print(list22)
list22.pop(1)
print(list22)
*注意1:使用了超出范围的下标,则报错
list22.pop(9) #IndexError: pop index out of range
print(list22)
*注意2:pop()返回被删除的元素
list22 = [1, 10, 2, 66, 8]
print(list22)
num = list22.pop(3)
print(num)
print(list22)
result = list22.remove(2) #None
print(result)
总结:pop返回被删除的元素,remove返回为None
c.list.clear() ,清空
list22 = [1, 10, 2, 66, 8]
print(list22)
list22.clear()
print(list22)
3.改
a.list.reverse() ,反转【倒序】
list31 = [34,56,56,67,100,200]
list31.reverse()
print(list31)
list31 = [34,56,56,67,100,200]
print(list31[::-1])
b.list.sort(),排序,默认为升序排序
list32 = [100,34,200,56,56,67]
print(list32)
升序
list32.sort()
print(list32)
降序
list32.sort(reverse=True)
print(list32)
字符串列表排序
list33 = ["456","abc","Kuf","helloabcbbv","xvya","888"]
print(list33)
list33.sort()
print(list33)
不同类型的元素是否可以排序----》不可以,因为sort底层采用的是关系运算符,不同类型无法比较
# list34 = [45,"faf","lll","5757",False,"你好"]
# list34.sort() #TypeError: '<' not supported between instances of 'str' and 'int'
4.查
a.len(list):获取列表中的元素个数/获取列表的长度
list41 = [4,6,56,56,76,6]
print(len(list41))
b.max(list):获取列表中的元素的最大值print(max(list41))c.min(list):获取列表中的元素的最小值
print(min(list41))
d.list.count(x),获取元素x在列表中出现的次数
print(list41.count(56))
c = list41.count(56)
print(c)
e.list.index(x),获取元素x在列表中第一次出现的下标【从左往右】
list41 = [4,6,56,56,76,6]
i1 = list41.index(56)
print(i1)
*注意:如果元素不存在,则报错
# i1 = list41.index(100) #ValueError: 100 is not in list
4.列表嵌套
列表的嵌套,其实就是一个列表中的元素又是一个列表
注意:操作嵌套列表,只要把要操作元素的下标当作变量名来使用即可
二、列表相关
1.列表拷贝
1.1内存中的变量
Python中的数据都是保存在内存中
Python中的数据分为两大类:
不可变数据类型:数字,布尔,元组,字符串
可变数据类型:列表,字典,集合
1.不可变数据类型
a = 10
b = a
print(a,b)
print(id(a),id(b))
a = 20
print(a,b) #20 10
print(id(a),id(b))
2.可变数据类型
list1 = [22,33,44]
list2 = list1
print(list1,list2)
print(id(list1),id(list2))
*注意:更改的是容器的内容,并不是容器本身
list1[1] = 100
list1 = [45,6,7]
print(list1,list2)
print(id(list1),id(list2))
3.id(x):获取变量x在内存中的地址
如果两个变量的id()值相等,则说明表示同一个数据
①变量其中实际存储了一个数据的地址
②变量被称为引用
a------》4362284320 10的地址
b------》4362284320 10的地址
a------》4362284640 20的地址
b------》4362284320 10的地址
list1,list2----->4363800456
list1,list2----->4363800456
对于不可变数据类型,如果修改值,内存地址会发生改变
对于可变数据类型,如果修改值【容器中的元素】。内存地址不会发生改变
1.2copy和=
1.=
a.单列表
list1 = [1,2,3]
list2 = list1
print(list1,list2)
list1[1] = 100
print(list1,list2)
b.嵌套列表
list1 = [[1,2,3],[4,5]]
list2 = list1
print(list1,list2)
list1[1][1] = 100
print(list1,list2)
print(id(list1),id(list2))
2.copy()
a.单列表copy
list1 = [1,2,3]
list2 = list1.copy()
print(list1,list2)
list1[1] = 100
print(list1,list2)
print(id(list1),id(list2))
b.嵌套copy
list1 = [[1,2,3],[4,5]]
list2 = list1.copy()
print(list1,list2)
list1[1][1] = 100
print(list1,list2)
print(id(list1),id(list2))
总结:前提:不管是基层列表 ,都更改最里层的数据
=:不管是单层列表还是嵌套列表,只要其中一个更改,另一个随着更改
copy:对于单层列表,其中一个更改,另一个不受影响
对于嵌套列表,其中一个更改,另一个随着更改
copy只拷贝最外层
1.3浅拷贝和深拷贝【面试题】
Python提供了copy模块来复制一个对象。copy模块提供了浅复制和深复制两种方式,它们的使用方式相同,但是执行的效果有一定的差异
浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容
深拷贝:是对于一个对象所有层次的递归拷贝
import copy
copy.copy()表示浅拷贝,copy.deepcopy()表示深拷贝
1.浅拷贝
a.单层浅拷贝
list1 = [1,2,3]
list2 = copy.copy(list1)
print(list1,list2)
list1[1] = 100
print(list1,list2)
print(id(list1),id(list2))
b.嵌套浅拷贝
list1 = [[1,2,3],[4,5]]
list2 = copy.copy(list1)
print(list1,list2)
list1[1][1] = 100
print(list1,list2)
print(id(list1),id(list2))
2.深拷贝
a.单层深拷贝
list1 = [1,2,3]
list2 = copy.deepcopy(list1)
print(list1,list2)
list1[1] = 100
print(list1,list2)
print(id(list1),id(list2))
b.嵌套深拷贝
list1 = [[1,2,3],[4,5]]
list2 = copy.deepcopy(list1)
print(list1,list2)
list1[1][1] = 100
print(list1,list2)
print(id(list1),id(list2))
总结:
copy.copy(列表)/列表.copy():对于单层列表,其中一个更改,另一个不受影响
对于嵌套列表,其中一个更改,另一个随着更改
copy.deepcopy(列表):对于所有列表,其中一个更改,另一个不受影响
2.列表推导式
列表推导式,就是指的轻量级循环创建列表
语法:[元素的规律 for循环 if条件]
作用:简化代码
特点:本质生成一个列表
1.生成列表[1,2,3,4....9]
list(x)将容器x转化为列表
list1 = list(range(1,10))
print(list1)
2.生成列表[1,4,9,16....81]
#方式一
list21 = []
for i in range(1,10):
list21.append(i ** 2)
print(list21)
#方式二
list22 = [i ** 2 for i in range(1,10)]
print(list22)
print(type(list22))
3.生成列表[1,9,25,49,81]
#方式一
list31 = []
for i in range(1,10):
if i % 2 == 1:
list31.append(i ** 2)
print(list31)
#方式二
list32 = [i ** 2 for i in range(1,10) if i % 2 == 1]
print(list32)
例:生成一个列表,列表中的元素为1~30之间3的倍数
list33 = [n for n in range(1,31) if n % 3 == 0]
print(list33)
4.可以使用两个for循环
#方式一
list41 = []
for i in "ABC":
for j in "XYZ":
list41.append(i + j) #举例:"a" + "b" ---->"ab" 拼接
print(list41)
#方式二:在列表推导式中,平行书写的for循环实际相当于嵌套for循环
list42 = [i + j for i in "ABC" for j in "XYZ"]
print(list42)
list43 = [[i,j,k] for i in range(3) for j in range(2) for k in range(2)]
print(list43)
例:已知一个数字列表,生成一个新的列表,列表中的元素为原列表的2倍
numlist = [34,6,6,56,5]
newlist = [num * 2 for num in numlist]
print(newlist)
3.简单算法
1.1冒泡排序
排序思路:比较两个相邻的下标对应的元素,如果符合条件就交换位置(最值出现在最后位)
[12,9,13,7,5]----->[5,7,9,12,13]
0 1 2 3 4
12 9 13 7 5
比较的轮数 参与比较的下标 每一轮比较的次数 结果
第0轮 0-1 1-2 2-3 3-4 4 得到了最大值
第1轮 0-1 1-2 2-3 3 得到了第二大值
第2轮 0-1 1-2 2
第3轮 0-1 1
0 3
1 2
2 1
3 0
规律:
a.使用嵌套循环:for循环
b.外层循环:控制比较的轮数
内层循环:控制每一轮比较的次数兼顾参与比较的下标
c.外层循环的取值范围:0~3---》0 ~ len - 2---->range(0,len - 1)--->range(len - 1) i
内层循环的取值范围:0 ~ (3 - i)---->0~(len - 2 - i)---->range(len - 1 - i) j
list1 = [45,2,100,56,6,55,70]
for i in range(len(list1) - 1):
for j in range(len(list1) - 1 - i):
#比较:如果下标小的元素 > 下标大的元素,则交换位置.升序
if list1[j] > list1[j + 1]:
list1[j],list1[j + 1] = list1[j + 1],list1[j]
print(list1)
1.2选择排序
排序思路:固定一个下标,然后拿这个下标对应的值依次和后面的元素进行比较,最值出现在头角标位置上
[12,9,13,7,5]----->[5,7,9,12,13]
0 1 2 3 4
12 9 13 7 5
比较的轮数 参与比较的下标 每一轮比较的次数 结果
第0轮 0-1 0-2 0-3 0-4 4 得到了最小值【最左边】
第1轮 1-2 1-3 1-4 3 。。。。
第2轮 2-3 2-4 2
第3轮 3-4 1
规律:
a.使用嵌套循环:for循环
b.外层循环:控制比较的轮数
内层循环:控制每一轮比较的次数兼顾参与比较的下标
c.外层循环的取值范围:0~3---》0 ~ len - 2---->range(0,len - 1)--->range(len - 1) i
内层循环的取值范围:i + 1 ~ 4---->i + 1 ~ len - 1---->range(i + 1,len) j
d.参与比较的下标:i 和 j
list1 = [45,2,100,56,6,55,70]
#选择排序:升序
for i in range(len(list1) - 1):
for j in range(i + 1,len(list1)):
if list1[i] > list1[j]:
list1[i],list1[j] = list1[j],list1[i]
print(list1)
1.3二分法查找
查找思路:将待查找的元素与中间下标对应的元素比较,如果大于中间下标对应的元素,则去右半部分查找
注意:前提是列表是有序(升序或者降序)的,通过折半来缩小查找范围,提高查找效率
#二分法查找:列表必须是有序的
list1 = [45,65,6,7,100,45,65,47]
list1.sort() #升序
print(list1)
#待查找的元素
key = 45
#初始值
left = 0
right = len(list1) - 1
#说明:当left == right,还未找到元素,则说明不存在
while left <= right:
middle = (left + right) // 2
#左半部分
if list1[middle] > key:
#给right重新赋值
right = middle - 1
#右半部分
elif list1[middle] < key:
#给left重新赋值
left = middle + 1
#找到了
else:
print("待查找元素的下标为:%d" % (middle))
#如果查找到,则可以提前结束循环
break
else:
print("待查找元素不存在")