得到Python的各种序列后,接下里就要知晓如何访问或取出序列中的数据。

看似很简单,其实门道很多,而且随着所学的序列越来越多后,比如字符串、列表、元组、字典、一维数组、多维数组、Series、DataFrame,渐渐的脑子就会混乱,所以打算梳理一下。方便之后自己查找。

其他序列可以参看鄙人的其他博文。

目录

1. 列表的切片操作

1.1 切片的概念

1.2 切片用法示例

 1.3 切片健壮性的体现

 1.4 利用切片实现其他操作:增加、修改、删除

 1.5 复制与浅复制

2. 一维列表元素的访问

3. 嵌套列表(多维列表)的元素访问


1. 列表的切片操作

列表的单个取值和切片操作和字符串一致。

借此回归一下Python列表的切片操作:关于切片操作这部分的描述,此处参照了董付国老师的《Python程序设计基础》一书。

1.1 切片的概念

切片是Python序列的重要操作之一,适用于列表、元组、字符串、range对象等类型。切片使用2个冒号分隔的3个数字来完成:第一个数字表示切片的开始位置,默认为0,第二个数字表是切片的截止(但不包含)位置(默认为列表长度),第三个数字表示切片的步长(默认为1),当步长省略时,顺便可以省略最后一个冒号。

可以使用切片来截取列表中的任何部分,得到一个新列表,也可以通过切片来修改和删除列表中部分元素,甚至可以通过切片操作为列表对象增加元素。与使用下标访问列表元素不同,切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表,代码具有更强的健壮性。

1.2 切片用法示例

aList=[3,4,5,6,7,9,11,13,15,17]
print(aList[::])  #[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
print(aList[::-1])  #[17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
#加了负号,就是一个逆向输出
print(aList[::2])  # [3, 5, 7, 11, 15]
#以步长为2进行输出,输出下标依次为0 2 4 6
print(aList[1::2])  #[4, 6, 9, 13, 17],从一开始步长为2
print(aList[3::])  #[6, 7, 9, 11, 13, 15, 17]
print(aList[3:6])  #省略的是步长,而且不包括下标为6的元素   #[6, 7, 9]

 1.3 切片健壮性的体现

如果用下标方式访问,一旦索引超出范围,就会会报错,导致程序无法顺利运行。

aList=[3,4,5,6,7,9,11,13,15,17]
print(aList[100])  #IndexError: list index out of range

 使用切片操作就不会产生该问题,会自动截断或者返回空列表。

aList=[3,4,5,6,7,9,11,13,15,17]
print(aList[0:100:1])   #[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
#就是说,不会产生下标越界问题。
print(aList[100:])  #[]

 1.4 利用切片实现其他操作:增加、修改、删除

可以使用切片操作来快速实现很多目的,例如,原地修改列表内容,列表元素的增删改查以及元素替换等操作都可以通过切片来实现。并且不影响列表对象内存地址。

利用切片方法实现列表的增加

aList=[3,5,7]
print(aList[len(aList):])   #[]
#利用切片方法实现列表的增加
aList[len(aList):]=[9]  #把原来三位列表的第四位赋值为9
print(aList)  #[3, 5, 7, 9]

利用切片方法实现列表元素的修改

#aList = [3,5,7,9]
aList[:3]=[1,2,3]
print(aList)  #[1, 2, 3, 9]
aList[:3]=[]
print(aList)  #[9]
aList=list(range(10))
print(aList)  #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
aList[::2]=[0]*(len(aList)//2)  #"//"整除
print(aList)  #[0, 1, 0, 3, 0, 5, 0, 7, 0, 9]

和del命令结合来删除列表中的部分元素

aList=[3,5,7,9,11]
del aList[:3]
print(aList)  #[9, 11]

 1.5 复制与浅复制

切片返回的是列表元素的浅复制,与列表对象的直接赋值并不一样。

复制

复制前后的列表指向同一内存块,拥有相同的内存地址,其中一个列表改变,另一个列表也会随之改变。二者可以视为同一个对象。

aList=[3,5,7]
bList=aList  #bList与aList指向同一内存块
print(bList)  #[3, 5, 7]
bList[1]=8
print(aList,bList)  #[3, 8, 7] [3, 8, 7]  改变列表bList的值,列表aList也也被改变
print(aList==bList)  #True
print(aList is bList)  #True ,aList对象就是bList对象
print(id(aList),id(bList))  #6832776 6832776 二者拥有相同的内存地址

浅复制 

二者相等,但是二者不是同一个对象,指向的内存地址也不一样,对一个列表做修改,也不改变另一个列表。

aList=[3,5,7]
bList=aList[::]
print(aList==bList,aList is bList) 
#输出结果True False ,二者相等,但是二者不是同一个对象!!!
print(id(aList)==id(bList))  #False 二者的内存地址也不一样
bList[1]=8
print(aList,bList)  
#[3, 5, 7] [3, 8, 7]  改变其中一个列表元素的值,也不影响另一个列表

2. 一维列表元素的访问

a_list=["Duan","Yi","Xuan","Chen","Ke","Han","Jia","Le"]
print(a_list)
#['Duan', 'Yi', 'Xuan', 'Chen', 'Ke', 'Han', 'Jia', 'Le']
print(len(a_list)) #8

#从0开始计数
print(a_list[0])  #Duan
#索引是左闭右开,包括起始,不包括结尾
print(a_list[0:3])  #['Duan', 'YI', 'Xuan']
#可以指定“间隔”
print(a_list[::2])  #['Duan', 'Xuan', 'Ke', 'Jia']
#可以逆序输出
print(a_list[::-1])  #['Le', 'Jia', 'Han', 'Ke', 'Chen', 'Xuan', 'YI', 'Duan']

3. 嵌套列表(多维列表)的元素访问

列表里面可以是各种数据类型,甚至是其他列表。

#嵌套列表的索性
date=[2011,2,9,9,54]
day=["sun","mon","tue","wed","thi","fri","sat"]
data=[date,day]
print(data) #[[2011, 2, 9, 9, 54], ['sun', 'mon', 'tue', 'wed', 'thi', 'fri', 'sat']]
print(data[1][3])  #wed  #第二块的第四个

假设有这样一个嵌套列表

a_list=[[1,2,3,4],
      [4,5,6,7],
      [7,8,9,10]]

如果将[1,2,3,4]视为一维列表,那么上述这个列表,可以视为二维列表,在第一维上有三个元素,分别是[1,2,3,4],[4,5,6,7]和[7,8,9,10],在第二维上,每一维又有四个元素。那么如果要访问里面的元素,就先访问第一维,再访问第二维,也可以只访问第一维。

#比如说要访问第二行的第二个元素
print(a_list[1][1]) #5
#访问第一行
print(a_list[0]) #[1, 2, 3, 4]
#如果要访问第二行和第三行
print(a_list[1:3])  #[[4, 5, 6, 7], [7, 8, 9, 10]]

如果要读出每一行的中间两个,也就是按“列”访问,我并没有找到像上述这种直接表示的方法(不知道别人能不能,反正我不会)。因为print( a_list[ : : 1][ 1 : 3] )的结果是[[4, 5, 6, 7], [7, 8, 9, 10]] ,事实上a_list[ : : 1][ 1 : 3]的意思的是,[::1]先在第一维上取出所有元素:[[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]],然后[1:3]又在里面取出第二个和第三个,那就是[[4, 5, 6, 7], [7, 8, 9, 10]],那就只能借助循环的方式了。

这个和后面的numpy有很大区别。

for a in a_list:
      print(a[1:3])
'''
[2, 3]
[5, 6]
[8, 9]
'''

暂时只想到这些,遇到新的再添加。如有错误,还请指出。