Python进阶6——序列操作

1.序列的拼接和复制

Python中使用+对序列进行拼接,使用*对序列进行复制

s=str(1234)
l=list(range(2,13))
print(s,l)
print('----------------')
print(s*2, 3*s)#将字符串s复制并打印
print('----------------')
print(l*2)#将列表复制生成一个新的列表并打印
print('----------------')
print(s+'1234567890')#字符串拼接
print('----------------')
print(l+2*l)#列表拼接
print('----------------')
print(l,s)

上述代码的第三行和最后一行表明,列表的拼接和复制操作并不会改变原来的序列,而是生成一个全新的列表

 

*构建嵌套列表和列表解析式生成嵌套列表两种方法

mat1=[[0]*3 for i in range(3)]
print(mat1)
mat2=[[0]*3]*3
print(mat2)

mat1[1][2]=2
print(mat1)
mat2[1][2]=3
print(mat2)

前四行代码的打印结果看起来并没有不同,但是当对嵌套列表中的元素进行修改时,可以看到这两个嵌套列表只是形式一样

当把mat1和mat2的元素的id打印出来后,可以知道其中的原因

for ele in mat1:
	print(id(ele))

for ele in mat2:
	print(id(ele))

可见,mat1中的三个子列表分别指向了不同的地址空间,然而mat2中的三个子列表却指向了同一个地址空间

所以,当对mat1中的某个元素进行修改时,不会牵一发而动全身,而对mat2进行修改时,会导致其他子列表对应位置的元素也跟着改变

所以,使用列表解析式方式产生的嵌套列表稳定,而使用*生成的嵌套列表不稳定

 

序列的*=和+=

当对象执行*=时,会自动调用魔术方法__imul__,如果没有实现该方法,会调用__mul__,此时,a*=b等价于a=a*b,+=也是一样

当元组与*=和+=组合时,会产生新的元组

l=list(range(1,5))
t=tuple(range(1,5))
print(l,t)
print(id(l), id(t))
l*=3
t*=3
print(l,t)
print(id(l), id(t))

可见,当对列表执行*=操作后,l指向的地址空间没有变,而元组执行*=操作后,却产生了新的元组,原因就是元组的不可变性

 

Python知识点3——列表操作中,最后写到元组可以被整体修改,其实并不是整体修改,只是产生了一个新的元组,然后对象指向了新的元组的地址空间,因为元组是不可变的

t2=(1,23,4)
print(id(t2))
t2=(3)
print(id(t2))

 

元组真的不可改变吗

当元组中的元素含有可变对象时,元组可以改变

t3=(1,2,3,[4,5])
t3[3]+=[6,7]

通过交互模式可以发现,虽然对元组中的列表进行拼接时显示了error,但是元组最终还是被改变了

一是因为+=和*=是原子操作(要不一部不执行,要不全都执行,这里+=操作全部执行结束,且中间不会因为其他软硬件原因导致该操作出现异常),二是因为列表是可变的

 

列表的排序,列表的排序见博客Python知识点2——列表基础

关于排序中的key参数见博客Python进阶1——一摞纸牌

 

bisect模块管理已排序的序列

bisect模块主要是通过二分查找来查找或者插入元素,主要的函数有bisect和insort

bisect的作用是返回插入元素的插入位置的索引

 

举例

import bisect
import sys

listnums=[1,4,5,6,8,20,23,23,26,29,30]#已经拍好顺序的列表
insertnums=[0,1,2,5,8,10,22,23,29,30,31]#要插入的元素

def demo(bisect_fn):#传入函数名
	print("demo")
	for i in insertnums:
		pos=bisect_fn(listnums, i)
		print(pos)#打入插入元素的插入位置的索引

print(__name__)
if __name__ == '__main__':
	if sys.argv[-1]=='left':#最后一个命令行参数,类似于C++中的argc和argv
		bisect_fn=bisect.bisect_left
	else: 
		bisect_fn=bisect.bisect
	print(bisect_fn.__name__)#打印调用的函数名
	demo(bisect_fn)

执行 python3 seoperation.py的结果

bisect模块中的bisect函数是bisect_right函数名别名,将插入元素的位置放置于和它相等的元素的右边

因为0比1小,所以,0将被放置在listnum中索引为0的位置,1和1相等,所以1将被放置与listnum中1的右边,打印出的索引为1,以此类推

执行python3 seoperation.py left的结果

bisect模块中的bisect_left函数的意思是将插入元素的位置放置于和它相等的元素的左边,所以1将被放置与listnum中1的左边,打印出的索引为0

 

上述代码中的if __name__ == '__main__':是一个判断,如果直接运行当前文件,那么变量__name__的值就是'__main__',如果当前文件被作为一个模块导入,那么__name__的值就不是'__main__'

所以if __name__ == '__main__':用来区分当前文件是否作为一个模块被导入,如果不作为模块,那么if __name__ == '__main__':下面的代码执行,否则if __name__ == '__main__':下面的代码不执行

 

给定一个分数,找到对应的成绩

def getgrade(score, section=[60,70,80,90], level='FDCBA'):
	i=bisect.bisect(section, score)
	return level[i]

res=[getgrade(score) for score in range(50,110,10)]
print(res)

总体思路就是通过bisect.bisect(section, score)返回分数对应的level索引,然后返回

 

用bisect.insort向序列中插入新元素

使用insort插入元素时,会保持序列有序

import bisect
listnums=[1,4,5,6,8,20,23,23,26,29,30]
bisect.insort(listnums, 10)
print(listnums)

 

参考:

《流畅的Python》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值