【python】list(5)

参考

Note:


最近一次修订时间为 2020-11-04



打了激素的数组
这里写图片描述
在这里插入图片描述
图片来自:https://www.bilibili.com/video/av20982396/?p=7

1 列表的创建

列表的创建用[ ],列表可以嵌套使用,即列表中包含其它数据类型,比如包含list(列表)、tuple(元组)、dict(字典)、set(集合)

list1 = [1,2,3,4,5] #创建列表
print ('list1:',list1)

list2 = ['a','b','c','d'] #列表中的数据类型可以是相同的,都是字符串
print ('list2:',list2)

list3 = [1,2.33,'Python','a'] #列表中的数据类型也可以是不同的,整型、浮点型、字符串
print ('list3:',list3)

list4 = [1, 2.33, 'Python', 'a',list3]#列表里还可以嵌套列表,列表中有列表
print ('list4:',list4)

list5 = []#创建空列表
print ('list5:',list5)
print ("list5's type is:",type(list5))

output

list1: [1, 2, 3, 4, 5]
list2: ['a', 'b', 'c', 'd']
list3: [1, 2.33, 'Python', 'a']
list4: [1, 2.33, 'Python', 'a', [1, 2.33, 'Python', 'a']]
list5: []
list5's type is: <class 'list'>

下面详细来看看list的嵌套结构

set1 = {1,2,3,4,5}
print (type(set1))

dict1 = {'a':1}
print (type(dict1))

tuple1 = ('a','b','c')
print (type(tuple1))

list7 = [1,2,3,4,5]
print (type(list7))

list8 = [set1,dict1,tuple1,list7]
print (type(list8))

output

<class 'set'>
<class 'dict'>
<class 'tuple'>
<class 'list'>
<class 'list'>

多维列表的创建

a = [[1,2],[3,4]]
type(a)

output

list

多重赋值

data_1, data_2, data_3, data_4 = [], [], [], []
# 或者使用列表推导式,见本文第四小节
data_1, data_2, data_3, data_4 = [[] for i in range(4)]
print(data_1, data_2, data_3, data_4)

output

[] [] [] []

配合循环来创建

list1 = [i for i in range(10)]
print(list1)

list2 = list(range(10))
print(list2)

output

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

2 一些列表的基本操作

2.1 通过索引取出列表中的元素

索引从0开始
这里写图片描述

2.2 连接(+)、复制(*)、求长度(len())

  • 连接用 +
  • 复制用 *
  • 求长度用 len()
list1 = [1, 2, 3, 4, 5]
list2=['a', 'b', 'c', 'd']

print ('list1+list2:',list1+list2)#使用加号连接列表
print('list1*3:',list1*3) #列表复制阵列,把列表复制三遍
print ("list1+list2's length is:",len(list1+list2)) #求列表长度

结果为

list1+list2: [1, 2, 3, 4, 5, 'a', 'b', 'c', 'd']
list1*3: [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
list1+list2's length is: 9

2.3 检查列表中是否存在某个元素(in)

用 in
这里写图片描述

2.4 删除列表(del)

1)用 del 删除整个列表
这里写图片描述

2)删除列表中指定的元素

list2=['a', 'b', 'c', 'd']

del list2[2] #删除列表中索引为 i 的元素
print(list2)

结果为

['a', 'b', 'd']

3)删除子列表

list1 = [0,1,2,3,4,5,6]
del list1[1:3]#删除列表的子列表
print(list1)

结果为

[0, 3, 4, 5, 6]

看看更为灵活的删除

a = [1,2,3,4,5]
del a[2::2] # 从 inde 2 开始隔 2 删一个
print(a)

output

[1, 2, 4]

2.5 求最大值最小值(max、min)

maxmin

list2=['a', 'b', 'c', 'd']

print (max(list2)) #返回列表中最大的值,max(列表名)
print (min(list2))#返回列表中最小的值

结果为

d
a

列表中元素如果不能比较的话,使用max就会报错
这里写图片描述

2.6 切片

列表切片指的是将列表的一部分切出来,有点像字符串切片。并且不改变原列表的内容!!!

列表切片的形式是:

list[起始索引:终止索引(不包含):步长间隔]

Note:步长可以是负值,切片切出来的还是列表

list1 = [0,1,2,3,4,5,6,7,8]
print ('list1[5:8]:',list1[5:8])#步长省略则默认为1
print ('list1[1:6:2]:',list1[1:6:2]) #步长为2
print ('list1[3:]:',list1[3:]) #取索引3到最后
print ('list1[:5]:',list1[:5]) #从头取到索引5(索引5取不到)
print ('list1[::2]:',list1[::2]) #取所有,步长为2
print ('list1[3:-1]:',list1[3:-1]) #从索引3取到倒数第一个(倒数第一个取不到)
print ('list1[:]:',list1[:]) #取所有的
print ('list1[::-1]:',list1[::-1]) #逆序列表
print ('list1[8:2:-2]:',list1[8:2:-2]) #逆序取,步长为2

结果为

list1[5:8]: [5, 6, 7]
list1[1:6:2]: [1, 3, 5]
list1[3:]: [3, 4, 5, 6, 7, 8]
list1[:5]: [0, 1, 2, 3, 4]
list1[::2]: [0, 2, 4, 6, 8]
list1[3:-1]: [3, 4, 5, 6, 7]
list1[:]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
list1[::-1]: [8, 7, 6, 5, 4, 3, 2, 1, 0]
list1[8:2:-2]: [8, 6, 4]

Note:一定要注意,索引区间为[A,B)半闭半开,-1逆序第一个元素

Question:llist1[0]和list1[0:1]一样吗?
结果是不一样的

llist1[0]输出列表的第零个元素
list1[0:1]输出的是包含列表第零个元素的列表

继续上才艺

[m:n] 取a[m]~a[n-1] 之间的内容,m \ n 可以为负,m>n 时返回空
[m::n] 取a[m] 开始,每跳 n 个取一个,n 为负数逆取,n 为负时,m 为空则置为 0,n为正时 m 为空则置为 -1

a = list(range(10))
print(a)

print(a[::2]) # [0, 2, 4, 6, 8]
print(a[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0],到第一个元素停止
print(a[::-2]) # [9, 7, 5, 3, 1]

print(a[3::1]) # [3, 4, 5, 6, 7, 8, 9]
print(a[3::2]) # [3, 5, 7, 9]
print(a[3::3]) # [3, 6, 9]
print(a[3::-1]) # [3, 2, 1, 0]

print(a[8::-2]) # [8, 6, 4, 2, 0]
print(a[8::-3]) # [8, 5, 2]

output

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[9, 7, 5, 3, 1]
[3, 4, 5, 6, 7, 8, 9]
[3, 5, 7, 9]
[3, 6, 9]
[3, 2, 1, 0]
[8, 6, 4, 2, 0]
[8, 5, 2]

list1 = [1, 2, 3, 4, 5, 6, 8, 1, 2, 3, 6, 9, 8, 6]
print(list1[::])
print(list1[::2])

output

[1, 2, 3, 4, 5, 6, 8, 1, 2, 3, 6, 9, 8, 6]
[1, 3, 5, 8, 2, 6, 8]

起始索引:终止索引 就是 slice(起始索引,终止索引) 的缩写

s = [1,2,3,4]
print(s[1:3])
print(s[slice(1,3)])  # 1:3 就是 slice(1,3) 的缩写

output

[2, 3]
[2, 3]

2.7 修改元素

list1 = [0,1,2,3,4,5,6,7,8]

list1[2] = 'Python' # 修改列表元素
print (list1)

list1[4:6] = ['a','b','c','d']
print (list1)

结果为

[0, 1, 'Python', 3, 4, 5, 6, 7, 8]
[0, 1, 'Python', 3, 'a', 'b', 'c', 'd', 6, 7, 8]

2.8 对列表元素循环

list1 = [1,2,3,4,5]
for i in list1:
    print(i)

结果为

1
2
3
4
5

2.9 copy

id() 方法用于获取对象的内存地址

list1 = [0,1,2,3,4,5,6,7,8]
print (id(list1))
print (id(list1[:]))

list2 = list1[:]
print (id(list2))

list3 = list1[:]
print (id(list3))

大家多会觉得,这四个 id 应该都一样,可事实如下:

1863546661320
1863546661512
1863546661384
1863545252296

四个 id 都不一样,以上是为什么呢?
涉及到 python 的浅复制和深复制,因为python的赋值更像是贴标签

list2 = list1
list3 = list1[:]

上面两种复制方法差别很大
list2 是浅层复制(贴标签),会跟随 list1 的改变而改变,list3 是深复制,这才是我们真正意义上的复制

list1 = [0,1,2,3,4,5,6,7,8]
print(id(list1))
list2 = list1
print(id(list2))
list3 = list1[:]
print(id(list3))

output

1863546690184
1863546690184
1863545219976

1)直接复制
a = b 直接复制

a = [1,2,3,4]
b = a # 复制
print(id(a)==id(b))
for i in range(len(a)):
    print(id(a[i])==id(b[i]))
a[0] = 5
print(a)
print(b)
b[0]=1
print(a)
print(b)

output

True
True
True
True
True
[5, 2, 3, 4]
[5, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]

会发现,a 和 b 的 id 地址是一样的,a 和 b 中每一个元素的 id 都是一样的,改变 a 和 b 任何一个变量,对方都会改变,这就尴尬了,就像花钱买回来的玩具汽车,别人也有个遥控器!

2)copy.copy() 浅复制

当使用浅拷贝时,python只是拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。看代码:

import copy
a = [1,2,3,4]
b = copy.copy(a)# 复制
print(id(a)==id(b))
for i in range(len(a)):
    print(id(a[i])==id(b[i]))
a[0] = 5
print(a)
print(b)
b[0]=2
print(a)
print(b)

output

False
True
True
True
True
[5, 2, 3, 4]
[1, 2, 3, 4]
[5, 2, 3, 4]
[2, 2, 3, 4]

a 和 b 的 id 不一样了,虽然,a 和 b 每个元素的 id 一样,但是 a 和 b 的改变不会影响到对方,这样似乎解决了 1)中的缺点,但是再看看下面的例子

import copy
a = [1,2,[3,4]]
b = copy.copy(a)# 复制
print(id(a)==id(b))

print('\nfirst layer')
for i in range(len(a)):
    print(id(a[i])==id(b[i]))
    
print('\nsecond layer')
for i in range(len(a[2])):
    print(id(a[2][i])==id(b[2][i]))

output

False

first layer
True
True
True

second layer
True
True

a 和 b 的 id 不一样,但是每一个元素的 id 都一样,改变 第一层的元素试试

a[0] = 5
print(a)
print(b)
b[0] = 2
print(a)
print(b)

output

[5, 2, [3, 4]]
[1, 2, [3, 4]]
[5, 2, [3, 4]]
[2, 2, [3, 4]]

a 和 b 不会相互影响


改改第二层的元素试试

import copy
a = [1,2,[3,4]]
b = copy.copy(a)# 复制
print(a)
print(b)
a[2][0] = 8
print(a)
print(b)
b[2][0]=2
print(a)
print(b)

output

[1, 2, [3, 4]]
[1, 2, [3, 4]]
[1, 2, [8, 4]]
[1, 2, [8, 4]]
[1, 2, [2, 4]]
[1, 2, [2, 4]]

oh,no 无良商家,卖门留一把门钥匙(哈哈哈,开玩笑的,想表达两者关系绑定了),这就是浅层复制,第一层独立了,第二层藕断丝连!我们用深层复制来斩断这个情丝吧!!!

3)copy.deepcopy() 深复制
deepcopy 对外围和内部元素都进行了拷贝对象本身,而不是对象的引用。

import copy
a = [1,2,[3,4]]
b = copy.deepcopy(a)# 复制
print(id(a)==id(b))

print('\nfirst layer')
for i in range(len(a)):
    print(id(a[i])==id(b[i]))
    
print('\nsecond layer')
for i in range(len(a[2])):
    print(id(a[2][i])==id(b[2][i]))

output

False

first layer
True
True
False

second layer
True
True

可以看出,第二层的 id 不同了,但是第二层列表里面的每个元素的 id 还是相同的!


再测试一下

import copy
a = [1,2,[3,4]]
b = copy.deepcopy(a)# 复制
print(a)
print(b)
a[2][0] = 8
print(a)
print(b)
b[2][0]=2
print(a)
print(b)

output

[1, 2, [3, 4]]
[1, 2, [3, 4]]
[1, 2, [8, 4]]
[1, 2, [3, 4]]
[1, 2, [8, 4]]
[1, 2, [2, 4]]

ok,有自主权了,可以叫做出师了吗?或者叫农夫与蛇,忘恩负义,恩断义绝,哈哈哈,完全和前任划清界限的感觉!

3 列表的一些常用方法

  • 添加:append、extend、insert
  • 删除:remove、del、pop

这里写图片描述

全部的BIF可以用dir查看

dir(list)

3.1 append

list.append(obj),在列表末尾添加新的对象

list1 = [0,1,2,3,4,5,6,7,8]
print (list1)

list1.append('Kobe') #list.append( obj ) 在列表末尾添加新的对象
print (list1)

list1.append(1)
print (list1)

结果为

[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 'Kobe']
[0, 1, 2, 3, 4, 5, 6, 7, 8, 'Kobe', 1]

3.2 count

list.count(obj),统计某个元素在列表中出现的次数

list1 = [1,2,1,2,1]
print (list1.count(1)) #list.count( obj ) 统计某个元素在列表中出现的次数
print (list1.count('1'))

结果为

3
0

3.3 extend

list.extend(seq),在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

list2 = [0,1,2,3,4]
print (list2)
list2.extend('a') #list.extend(seq) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
print (list2)
list2.extend(['b',[1,2,3]])#extend添加单个元素和append很像,但他可以一次添加更多元素,元素可以是列表
print (list2)

结果为

[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4, 'a']
[0, 1, 2, 3, 4, 'a', 'b', [1, 2, 3]]

那么问题来了,append和extend有什么区别呢?看如下的例子就知道了

list1 = [1,2,3]
list1.append([4,5,6])
print (list1)

list1 = [1,2,3]
list1.extend([4,5,6])
print (list1)

结果为

[1, 2, 3, [4, 5, 6]]
[1, 2, 3, 4, 5, 6]

这两个方法功能类似,但是在处理多个列表的时候,这两个方法的处理结果是完全不相同的。想一次性给某一个列表添加多个元素,用 extend,以列表的形式添加!

灵活运用,例如将列表的所有元素,包括子列表,都展开成一个列表

list1 = [1,[2],3,[4,5]]
result = []
for item in list1:
    if isinstance(item,list):
        result.extend(item)
    else:
        result.append(item)
print(result)

output

[1, 2, 3, 4, 5]

3.4 index

list.index(obj),从列表中找出某个值第一个匹配项的索引位置

list1 = [1,2,1,4,1]
print (list1.index(1)) #list.index(obj)从列表中找出某个值第一个匹配项的索引位置
print (list1.index(4))

output

0
3

也可以返回某一个区间内,第一次出现的元素索引

list1 = [1,2,1,4,1]
print (list1.index(1,1,3)) #list.index(obj)从列表中找出某个值第一个匹配项的索引位置,范围,1-3(0是第一个)

结果为
2

3.5 insert

list.insert(index, obj),将对象插入列表,查到指定index(索引)的前面

list1 = [0,1,2,3,4]
list1.insert(2,'b')#list.insert(index, obj)将对象插入列表
print (list1)
list1.insert(0,'a')
print (list1)

结果为

[0, 1, 'b', 2, 3, 4]
['a', 0, 1, 'b', 2, 3, 4]

也可以插入其它的数据结构,例如列表

list1 = [0,1,2,3,4]
list1.insert(4,['b','c'])#也可以插入一个列表
print (list1)

结果为

[0, 1, 2, 3, ['b', 'c'], 4]

补充,也可以通过索引来实现插入

a = [1,2,3,4,5]
a[:0] = [-1,0]
print(a)

output

[-1, 0, 1, 2, 3, 4, 5]

3.6 pop

list.pop(obj=list[-1]),移除列表中的一个元素(默认最后一个元素),并且返回该元素的值

list1 = [0,1,2,3,4,5]

a = list1.pop()#list.pop(obj=list[-1])移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
print (a)

print (list1)

list1.pop(2)#也可以指定删除的索引
print (list1)

结果为

5
[0, 1, 2, 3, 4]
[0, 1, 3, 4]

3.7 remove

list.remove(obj),移除列表中某个值的第一个匹配项

list1 = [0,1,2,3,4,2,2]
list1.remove(2)#list.remove(obj)移除列表中某个值的第一个匹配项
print (list1)

结果为

[0, 1, 3, 4, 2, 2]

补充

for i in a:
	if i==x:
		a.remove(i)

删不干净,索引变了

用 for 发起任何形式的遍历时,它的遍历顺序是一开始就确定的,而在遍历中删除了元素导致了当前索引的变化。整个列表的元素向前移动,但i却在最初就确定了,所以导致漏删元素。

Python遍历列表时删除元素的几种方法

for i in a[:]:
	if i==x:
		a.remove(i)

这样就可以删干净

3.8 reverse(和 list1[::-1] 效果一样)

list.reverse(),反向列表中元素

list1 = [0,1,2,3,4,5]
list1.reverse()#list.reverse()反向列表中元素
print (list1)

结果为

[5, 4, 3, 2, 1, 0]

list1[::-1] 效果一样

3.9 sort

list.sort([func]),对原列表进行排序,修改了原列表

list5 = [2,1,4,5,3,6,8,7,0]
list5.sort()#list.sort([func])对原列表进行排序
print (list5)

结果为

[0, 1, 2, 3, 4, 5, 6, 7, 8]

默认为升序,降序的操作如下

list1 = [2,1,4,5,3,6,8,7,0]
list1.sort(reverse = True)
print (list1)

结果为

[8, 7, 6, 5, 4, 3, 2, 1, 0]

也可以对字符串进行排序,按照ASCII的顺序来,数字 < 大写字母 < 小写字母

list1 = ['a','A','1','Python','python']
list1.sort()
print(list1)

结果为

['1', 'A', 'Python', 'a', 'python']

sort 与 sorted 的区别

list1 = [6, 3, 8, 9, 10, 7]
list2 = list1.sort()
print(list1)
print(list2)

list2 = sorted(list1)
print(list1)
print(list2)

output

[3, 6, 7, 8, 9, 10]
None
[3, 6, 7, 8, 9, 10]
[3, 6, 7, 8, 9, 10]

看下 sort 和 sorted 的介绍,就可以发现,一个是 list 对象中的一个方法,没有返回值,一个是 BIF,返回 list

list 
def sort(self,
         *,
         key: Optional[(_T) -> Any] = ...,
         reverse: bool = ...) -> None
builtins 
def sorted(__iterable: Iterable[_T],
           *,
           key: Optional[(_T) -> Any] = ...,
           reverse: bool = ...) -> List[_T]

和 sort 一样,print 也是没有返回值的

a = print('bryant')
type(a)

output

bryant
NoneType

sort 的有个 key 参数,用法非常灵活

list1 = list("Python is my favorite programming language".split(" "))

print(list1) # 原始列表
list1.sort()
print(list1) # 默认排序
list1.sort(key=len)
print(list1) # 根据长度排序
list1.sort(key=str.lower) 
print(list1) # 区分大小写排序

output

['Python', 'is', 'my', 'favorite', 'programming', 'language']
['Python', 'favorite', 'is', 'language', 'my', 'programming']
['is', 'my', 'Python', 'favorite', 'language', 'programming']
['favorite', 'is', 'language', 'my', 'programming', 'Python']

3.10 配合 enumerate

animals = ['dog','cat','fish']

for i,j in enumerate(animals):
    print(i,j)

output

0 dog
1 cat
2 fish

3.11 zip

zip 函数接受任意多个(包括0个和1个)序列作为参数,合并后返回一个 tuple列表,请看示例:

a = [1,2,3]
b = [4,5,6]
print(zip(a,b))
print(type(zip(a,b)))
c = list(zip(a,b))
print(c)

output

<zip object at 0x0000019D86D724C8>
<class 'zip'>
[(1, 4), (2, 5), (3, 6)]

zip 0 个序列

d = list(zip())
d

output

[]

zip 一个序列

for i in zip(a):
    print(i)

output

(1,)
(2,)
(3,)

zip 两个序列

for i,j in zip(a,b):
    print(i,j)

output

1 4
2 5
3 6

zip 三个序列

for i,j,z in zip(a,a,b):
    print(i,j,z)

output

1 1 4
2 2 5
3 3 6

4 列表推导式或解析式

List comprehensions,灵感取自函数式编程语言Haskell。Ta 是一个非常有用和灵活的工具,可以用来动态的创建列表,语法如下:

[有关 A 的表达式 for A in B]

例如,生成一个列表,元素是1~10的平方。

[i**2 for i in range(1,11)]#一行代码搞定!是不是很优雅

和 for……in……配合生成列表, 再看一些例子,熟悉下这种操作

[m+n for m in 'ABC' for n in'abc'] 

结果为

['Aa', 'Ab', 'Ac', 'Ba', 'Bb', 'Bc', 'Ca', 'Cb', 'Cc']

[x**2 for x in range(1,11) if x%3==0] 

结果为

[9, 36, 81]

list1 = [(x, y) for x in range(10) for y in range(10) if x%2==0 if y%2!=0]
print (list1)

结果为

[(0, 1), (0, 3), (0, 5), (0, 7), (0, 9), (2, 1), (2, 3), (2, 5), (2, 7), (2, 9), (4, 1), (4, 3), (4, 5), (4, 7), (4, 9), (6, 1), (6, 3), (6, 5), (6, 7), (6, 9), (8, 1), (8, 3), (8, 5), (8, 7), (8, 9)]

再看看更为灵活的用法

list1 = ["FizzBuzz" if i%3 == i%5 == 0
        else "Fizz" if i%3 == 0
        else "Buzz" if i%5 == 0
        else i for i in range(1,20)]
print(list1)

output

[1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz', 16, 17, 'Fizz', 19]

补充,同样的 set 和 dict 也有解析式

list1 = [1, 2, 3, 4, 5, 2, 5, 1, 4, 8]
set1 = { x for x in list1 if x % 2 == 0 }
print(type(set1))
print(set1)
dict1 = { x: x % 2 == 0 for x in range(1, 11) }
print(type(dict1))
print(dict1)

output

<class 'set'>
{8, 2, 4}
<class 'dict'>
{1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False, 10: True}

Note: 更多连载请查看【python】

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值