python列表知识点

使用enumrate()生成索引号

enumerate(iter, start),iter表示一个可迭代对象,start表示索引起始值。

for i, j in enumerate([5,6,7], 1):
    print(i,  j)

输出:
1 5
2 6
3 7

列表切片

语法和字符串类似,一个很重要的共同点是:就算索引超出了列表范围,也不会报错,会默认复制尽可能多的元素,如果范围内没有元素,则会生成空列表(字符串会生成空字符串)

列表切片赋值

  • 赋值之后会改变原列表,给切片赋值时,用来赋值的对象必须是一个列表或者集合,这时不用匹配元素个数。如果大小匹配,则是修改原列表的值,如果不匹配,则会替换掉原来的值,也就是说会改变原列表的大小.
l = [1,2,3]
l[:2] = [0,0]
print(l) # [0, 0 3]
l[:2] = [0,0,0]
print(l) [0,0,0,3],改变原列表的大小

在切片赋值时,其实是将可迭代对象的每个元素作为一个列表的元素。因此,将字符串赋给列表切片时,会出现以下情况:

l = [1,2,3]
l[:2] = 'ckdc'
print(l) # ['c', 'k', 'd', 'c', 3]
  • 但如果切片中包含step参数(其大小不能为1,也就是必须“跳跃”取值)时,则用来赋值的对象必须和切片的大小相等。
l = [1, 2, 0, 3, '1', '2', '3', 3]
l[::2] = [9,9,9,9]  # 二者大小必须匹配,不然会报错
print(l) # [9, 2, 9, 3, 9, '2', 9, 3],改变了原列表
l[::2] = [9,9,9] # 这时会报错:ValueError: attempt to assign sequence of size 3 to extended slice of size 4
  • 为列表切片或者索引赋值,会“原地”修改列表的值。但是俩者还是有区别,切片赋值上面已经说的很清楚了。对于索引赋值,只需要记住一点:索引赋值只会修改一个位置的元素,其他位置元素不会产生任何影响,更不会改变列表大小。
l = [1,2,3]
l[0] = 'ckdc'
print(l) # ['ckdc', 2, 3]
l[1] = [1,2]
print(l) # ['ckdc', [1, 2], 3]
# 以上均不会改变列表大小,只会修改指定位置的元素

列表运算符

只介绍两个比较重要的,in/not in, 还有*。其中*与字符串中的用法一致,都是为了快速创建指定大小的列表。
而对于in操作而言,字符串和列表有一些不同。字符串默认含有空字符串,而列表并不默认含有空列表。在对字符串使用in操作符时要求被判断的一定是字符串类型,不然也会报错。

print('' in 'dcsz') # True
print([] in l) # False

使用切片进行列表插入

  • 在指定索引处插入
l = [1,2,3]
print(l[0:0]) #  []
l[0:0] = [1,2,3] # 在索引0处插入列表
print(l) # [1, 2, 3, 1, 2, 3]
l[2:2] = [0] # 在索引2处插入列表
print(l) # [1, 2, 0, 3, 1, 2, 3]

深拷贝与浅拷贝

简单来说,浅拷贝只能拷贝顶层元素,而深拷贝则会拷贝到各个层级。直接上代码:

a = [1, 2, [5, 10]]
b = a[:]  # 进行一次拷贝
b[0] = 0
b[1] = 0
b[2][0] = 0
b[2][1] = 0
print(a) # [1, 2, [0, 0]]

b是a的一个拷贝,但是在修改b的时候,a有的位置跟着变了,有的位置没变。这是为什么呢?因为切片是对列表的一个浅拷贝,浅的意思在于仅拷贝顶层元素,一旦有更深层级的元素,则只会和原列表共用一个对象,如元素a[2],这时b[2]只是它的另一个别名,二者指向同一块存储空间。
在这里插入图片描述

如图,1,2拷贝成功了,但由于第三个元素包含了两个元素,层级更深了,因此第三个只是用一个引用指向了它,因此在改变的时候,a和b的第三个元素都会发生改变。
可以使用copy模块的deepcopy()方法进行深拷贝。
b = copy.deepcopy(a)
这样就完成了深拷贝。

列表函数

函数与字符串的差不多,多了一个sum(),但其仅针对数字类型的列表。除了这些,在使用上和字符串也还是有区别。

  • len()函数作用于字典时,会返回键的个数。
  • sorted()函数在作用于列表时,会生成新的列表
  • reversed()函数会生成逆序可迭代对象。

列表方法:修改列表

前面介绍的函数会生成新列表,而方法则会修改原列表。由于字符串是不可变类型,因此字符串没有这些方法。

  • list.appped()
  • list.clear(): 删除所有内容
  • list.extend(iterable):追加一系列值
  • list.insert(index, value):在指定索引处插入值
  • list.remove(value):移除某值的第一个实例

列表方法:获取列表信息

  • list.count(value) : 统计实例数量。只统计顶层元素
  • list.index(value, beg, end):返回值第一次出现的索引位置,后面的参数用来限定范围,找不到值则会引发异常
  • list.pop(index):返回并删除指定索引的值,默认情况下返回最后一个元素

列表方法:重新排序

  • list.sort(key=None, reverse=False):reverse若为true,则会从大到小排列,key参数是一个可执行函数,要求改函数参数为每个元素,返回值是该元素的主键,使用该主键进行排序。
a = ['dwc', 'AHXJ', 'cujdh','Djuc']
a.sort(key=lambda x:x.casefold(), reverse=True) # 从大到小排
print(a) # ['dwc', 'Djuc', 'cujdh', 'AHXJ']
a.sort(key=lambda x:x.casefold(), reverse=False) # 从小到大排
print(a) # ['AHXJ', 'cujdh', 'Djuc', 'dwc']

其实key的作用在于挑选排序的规则,比如上述是不区分大小写的排序结果。该该函数只能由一个参数,然后sort方法会将它在每一个元素上作用,然后用作用的结果去排序。key函数并不会改变原列表元素的值。

堆栈列表:RPN应用

可以发现,列表的append()方法和pop()方法可以很方便的将列表作为堆栈来使用,因此可以很方便的用列表写出一个RPN解释器:

rpn_str = input("请输入逆波兰表达式:\n")
rpn_str = rpn_str.split()
rpn_stack = []
for i in rpn_str:
    if i in '+-*/': # 遇到运算符则弹出两个操作数,计算之后再压入
        op1 = rpn_stack.pop()
        op2 = rpn_stack.pop()
        rpn_stack.append(str(eval(op2 + i + op1))) # 注意eval()函数的使用
    elif i.isdigit(): # 数字则直接压入
        rpn_stack.append(i)
print(rpn_stack)

functools.reduce()函数

  • functools.reduce(function, list)
    reduce的意思是减少,其作用是:通过function函数,操作列表的相邻元素对,并累计结果(就是操作结果也和下一个元素一起进入function函数产生结果,直到作用完最后一个元素)。因此,function函数必须是两个参数
from functools import reduce
a = reduce(lambda x,y:x+y,[1,2,3,4]) / len([1,2,3,4]) # reduce的作用是实现累加
  • map(function, list), filter(function, list)
    map函数是将function作用到每个元素上,生成新的列表。filter是通过functio函数去筛选列表中的值,也生成一个新的列表。但是这两个函数的功能可以被列表生成式很好的替代。列表生成式已经用的很多了,就不再赘述了。
print(list(map(lambda x:x*x, [1,2,3]))) # [1, 4, 9]
print(list(filter(lambda x:x>1, [1,2,3]))) # [2, 3]

列表推导式的复杂用法

在生成大型矩阵的时候,可以使用numpy包,很方便。但这里为了加深一下对矩阵的理解以及对列表推导式的理解,还是用列表生成式也来生成一下大型矩阵吧。

print([ [ [0] * 10 for i in range(3) ] for j in range(2) ])

该表达式会生成一个2X3X10的矩阵。生成过程是这样的,先生成里面的矩阵,显然维度为3x10,之后再生成最外层,就形成了2x3x10的矩阵。好了,先介绍到这里,下次继续!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值