python中列表(list)和元组(tuple)的深⼊讲解
前⾔
在我们实际开发中,经常需要将⼀组数据存储起来,以便使⽤。如果学习了其他的语⾔可能知道数组(Array)这个数据结构,它就可以将多个数据进⾏存储,访问数据可以通过数组下标的⽅式,的进⾏获取。如果你是python开发者,那么可以使⽤更加灵活的列表(list)和元组(tuple),来进⾏数据储存。下⾯我们先简单了解下列表和元组的基本使⽤。
列表
列表是动态的,长度可以改变,可以随意增加,修改或删除元素。
初始化列表
a = list()
b = []
# 可以通过range快速创建list
c = list(range(1,6))
print("a:", a)
print("b:", b)
print("c:", c)
# a: []
# b: []
# c: [1, 2, 3, 4, 5]
添加元素
append:在列表的末尾添加⼀个元素
>>l = []
>>l.append("python")
深基坑专项施工方案>>l刷新bios
['python']
extend:使⽤可迭代对象中的所有元素来扩展列表
>>l = ["python"]
>>t = ["java"]
>&d(t)
>>l
['python', 'java']
inrt:在给定的位置插⼊⼀个元素。第⼀个参数是要插⼊的元素的索引,所以 list_name.inrt(0, x) 插⼊列表头部
>>l = ["python", "java"]
>>l.inrt(1,"go")
>>l
['python', 'go', 'java']
删除元素
remove(x):从列表中删除值为x的第⼀项。如果没有需要删除的值,那就抛出异常
>>l = ["python", "java"]
>&ve("java")
>>l
['python']
>&ve("test")
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: ve(x): x not in list
pop: 删除列表中给定位置的元素并返回它。如果没有给定位置,pop() 将会删除并返回列表中的最后⼀个元素
>>l = ["python", "java", "go"]
>>l.pop()
'go'
>>l
['python', 'java']
>>l.pop(1)
'java'
>>l.pop(1)
Traceback (most recent call last):
File "<input>", line 1, in <module>
IndexError: pop index out of range
del: Python 中的关键字,专门⽤来执⾏删除操作,它不仅可以删除整个列表,还可以删除列表中的某些元素
>>l = ["python", "java", "go", "js"]
>>del l[0:1]
>>l
['java', 'go', 'js']
>>del l[0]
>>l
['go', 'js']
clear(): 移除列表中的所有元素。等价于 del a[:]
>>l = ["python", "java", "go", "js"]
>>l.clear()
>>l
[]
ps:这⾥注意和del 的区别, clear是清空, del list_name 是删除,内存也释放
修改元素
修改单个可以通过下标的⽅法
>>l = ["python", "go", "java"]
>>l[0] = "PYTHON"
>>l
['PYTHON', 'go', 'java']
修改⼀组数据可以通过切⽚的⽅式
>>l = ["python", "go", "java"]
>>l[0:2] = "PYTHON", "GO"
>>l
['PYTHON', 'GO', 'java']
>>l[0:2] = ["python", "go"]
>>l
['python', 'go', 'java']
查询元素
index(x) :⽅法⽤来查找某个元素在列表中出现的位置(也就是索引),如果该元素不存在,则会导致 ValueError 错误>>l
['python', 'go', 'java']
>>l.index("python")
>>l.index("python1")
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: 'python1' is not in list
count() :⽤来统计某个元素在列表中出现的次数
>>l
['python', 'go', 'java']
>&unt("PYTHON")
>&unt("python")
1
其他操作憧憬的近义词是什么
sort:对列表中的元素进⾏排序
>>l
['go', 'java', 'python']
>>l.sort(rever=True)
>>l
['python', 'java', 'go']
>>l.sort()
>>l
['go', 'java', 'python']
rever: 反转元素
>>l = [1,2,3,4,5]
>&ver()
>>l
[5, 4, 3, 2, 1]
copy: 返回列表的⼀个浅拷贝,等价于 a[:]
>>l
[5, 4, 3, 2, 1]
>>a = l.copy()
>>a
[5, 4, 3, 2, 1]
python列表使⽤场景
1-使⽤列表实现栈
栈(stack)特点就是后进先出,使⽤列表实现是⾮常容易的,要添加⼀个元素到堆栈的顶端,使⽤ append() 。要从堆栈顶部取出⼀个元素,使⽤ pop() ,不⽤指定索引。
stack = []
stack.append(1)
千源网stack.append(2)
stack.append(3)
stack.append(4)
stack.pop()
# 4
stack.pop()
# 3
stack.pop()
# 2
stack.pop()
# 1
# 注意捕捉错误
2-实现队列
from collections import deque
queue = deque(["python", "go", "java"])
queue.append("python")
queue.append("go")
print(queue)
queue.popleft()
queue.popleft()
print(queue)
返回结果
deque(['python', 'go', 'java', 'python', 'go'])
deque(['java', 'python', 'go'])
列表推导式
a = [x ** 2 for x in range(10)]
b = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
# 嵌套列表推导式
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
c = [[row[i] for row in matrix] for i in range(4)]
print("a:", a)
print("b:", b)
print("c:", c)
返回
a: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
b: [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
c: [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
元组
元组是静态,⼤⼩固定,不可以对元素进⾏增加,修改或删除的操作创建元组
a = 1, 2, 3
print("a", a)
b = (1, 2, 3)
print("b", b)
# 将字符串转换成元组
tup1 = tuple("hello")
赢得比赛英语print("将字符串转换成元组", tup1)
# 将列表转换成元组
list1 = ['Python', 'Java', 'C++', 'JavaScript']
tup2 = tuple(list1)
print("将列表转换成元组", tup2)
# 将字典转换成元组
dict1 = {'a': 100, 'b': 42, 'c': 9}
tup3 = tuple(dict1)
print("将字典转换成元组", tup3)
# 将区间转换成元组
range1 = range(1, 6)
tup4 = tuple(range1)
print("将区间转换成元组", tup4)
返回结果
a (1, 2, 3)
b (1, 2, 3)
将字符串转换成元组 ('h', 'e', 'l', 'l', 'o')
将列表转换成元组 ('Python', 'Java', 'C++', 'JavaScript')
将字典转换成元组 ('a', 'b', 'c')
将区间转换成元组 (1, 2, 3, 4, 5)
访问元素
a = (1, 2, 3, 4, 5)周水子小学
# 通过下标
print(a[0])
# 通过切⽚:a[start : end : step]
print(a[0:4:2])
返回结果
1
(1, 3)
删除
a = (1, 2, 3, 4, 5)
招待是什么意思del a
元组和列表区别
元组是静态,列表是动态
元组修改
购置税优惠
l = (1,2,3,4)
id(l)
# 4497372488
l = l + (5,6)
id(l)
# 4494985832
列表修改
l = [1,2,3,4]
id(l)
# 4499169160
l = l + [5,6]
id(l)
# 4495787016
通过上⾯可以发现元组是不可以改变的,这⾥强调⼀点很多新⼿对这个 l = l + (5,6) 很不难理解,不是说元组不可以修改的吗,那为什么这⾥可以修改?记住这⾥虽然可以执⾏,但是他是创建了⼀个新的元组,这时候的 l 不是原来的 l, 可以通过 id
查询(或则执⾏ l[0] = -1 就会报错)
在这⾥我多说⼏句,这⾥的静态和动态,⼤⽩话来讲是列表是可以进⾏列表的操作(新增,删除,修改),⼀般操作⾏为下他的内存地址不变(通过id查看),这和他的实现有关,但是元组就会改变,所以新的元组和原来的不⼀样,⼀般时候有⼈(⾯试官或则开发不⼩⼼)会问你 a = ([1,2], 3,4), 为什么可以进⾏a[0].append(3),但是id(a)前后不变,这就是0下标的元素是列表,列表可以修改的。
列表需要更多内存,元组需要更少内存
list_t = []
print("列表初始化时候⼤⼩:", list_t.__sizeof__())
tuple_t = ()
print("元组初始化时候⼤⼩:", tuple_t.__sizeof__())
返回结果
列表初始化时候⼤⼩: 40
元组初始化时候⼤⼩: 24
看到结果有没有发现列表⽐元组⼤18字节,那么问题来了:这18字节是怎么来的?这是由于列表是动态的,它需要存储指针来指向对应的元素(占⽤ 8 个字节)。另外,由于列表中元素可变,所以需要额外存储已经分配的长度⼤⼩(占⽤ 8 个字节),这样才能实时追踪列表空间的使⽤情况。但是对于元组,情况就不同了,元组长度⼤⼩固定,且存储元素不可变,所以存储空间也是固定的。
列表不可被hash,元组可以被hash
tuple_t = (1, 2)
print("元组hash值:", hash(tuple_t))
list_t = [1, 2]
print("列表hash值:", hash(list_t))
执⾏结果
Traceback (most recent call last):
File "/Urs/linjian/MonitorCenter/MonitorCenter/apps/t6.py", line 4, in <module>
print("列表hash值:", hash(list_t))
TypeError: unhashable type: 'list'
元组hash值: 3713081631934410656
从上⾯的结果可以发现元组是可以被hash,但列表却是不可以。如果基础扎实的应该会反应过来,python中hash需要满⾜是不可变类型的数据结构(字符串str、元组tuple、对象集objects)
执⾏效率
# 初始化⼀个相同元素的列表和元组使⽤情况
(djangoDemo) MonitorCenter % python -m timeit 'x=(1,2,3,4,5,6)'
100000000 loops, best of 3: 0.0103 uc per loop
(djangoDemo) MonitorCenter % python -m timeit 'x=[1,2,3,4,5,6]'
10000000 loops, best of 3: 0.0514 uc per loop
# 元组和列表索引操作对⽐
(djangoDemo) MonitorCenter % python -m timeit 'x=(1,2,3,4,5,6)' 'y=x[3]'
10000000 loops, best of 3: 0.0267 uc per loop
(djangoDemo) MonitorCenter % python -m timeit 'x=(1,2,3,4,5,6)' 'y=x[3]'
10000000 loops, best of 3: 0.0265 uc per loop
上⾯的运⾏结果显⽰:元组初始化远快于列表,⼤概有五倍的差距,但是索引操作的时候速度没有多⼤差距