目录
2.4.4 使用列表推导式(List Comprehensions)
2.17 内置函数max()、min() 和 sum()在列表中的使用
1. 序列的本质和内存结构
在Python中,序列是一种基本的数据结构,是一种数据存储方式,它可以容纳多个元素,并按照一定顺序排列。Python内置了几种常用的序列类型,包括列表(list)、元组(tuple)、字符串(str)、字节序列(bytes)、bytearray和range对象等。
在内存中,序列就是一块用来存放多个值的连续的内存空间。
比如一个整数序列 [10,20,30,40],示意表示:
由于Python3中一切皆对象,在内存中实际是按照如下方式存储的:
从图示中,我们可以看出序列中存储的是整数对象的地址,而不是整数对象的值
2.列表
2.1 列表简介
用于存储任意数目、任意类型的数据集合
列表是内置可变序列,是包含多个元素的有序连续的内存空间。列表的标准语法格式:
a = [10,20,30,40]
其中,10,20,30,40这些称为:列表a的元素。
列表中的元素可以各不相同,可以是任意类型。 比如:
a = ['hello', True, 0.23, 10]
列表中的元素可以是字典,列表,自定义的对象等等
Python的列表大小可变,根据需要随时增加或缩小
2.2 列表的特点
有序性:列表中的元素按照插入顺序排列,每个元素都有一个唯一的索引,可以通过索引访问和修改元素。
可变性:列表是可变的,即可以通过各种方法增加、删除或修改列表中的元素。
任意类型:列表中的元素可以是任意类型的对象,包括其他列表、元组、字典、甚至自定义对象等。
动态性:列表的大小是动态变化的,即可以根据需要动态增加或减少元素的个数。
2.3 列表对象的常用方法大全:
方法
要点
描述
list.append(x)
增加元素
将元素x增加到列表list尾部
list.extend(aList)
增加元素
将列表alist所有元素加到列表list尾部
list.insert(index,x)
增加元素
在列表list指定位置index处插入元素x
list.remove(x)
删除元素
在列表list中删除首次出现的指定元素x
list.pop([index])
删除元素
删除并返回列表list指定为止index处的元素,默认是最后一个元素
list.clear()
删除所有元素
删除列表所有元素,并不是删除列表对象
list.index(x)
访问元素
返回第一个x的索引位置,若不存在x元素抛出异常
list.count(x)
计数
返回指定元素x在列表list中出现的次数
len(list)
列表长度
返回列表中包含元素的个数
list.reverse()
翻转列表
所有元素原地翻转
list.sort()
排序
所有元素原地排序
list.copy()
浅拷贝
返回列表对象的浅拷贝
2.4 列表的创建
2.4.1 使用方括号
[]
最常见的创建列表的方式是使用方括号
[]
,将多个元素用逗号分隔放入方括号中。# 创建一个空列表 empty_list = [] # 创建一个包含元素的列表 numbers = [1, 2, 3, 4, 5] names = ['Alice', 'Bob', 'Charlie'] # 列表可以包含不同类型的元素 mixed_list = [1, 'Alice', True, [1, 2, 3]]
2.4.2 使用
list()
函数可以使用
list()
函数来将其他可迭代对象(如字符串、元组、集合等)转换为列表。# 从字符串创建列表,每个字符成为一个元素 char_list = list('Python') # ['P', 'y', 't', 'h', 'o', 'n'] # 从元组创建列表 tuple_list = list((1, 2, 3, 4)) # [1, 2, 3, 4] # 从集合创建列表 set_list = list({1, 2, 3, 4}) # [1, 2, 3, 4]
2.4.3 使用
range()
函数
range()
函数用于生成一个整数序列,可以通过list()
函数将其转换为列表。# 创建一个包含一定范围内的整数的列表 number_list = list(range(1, 10)) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
2.4.3.1 range的基本用法
range(stop) range(start, stop[, step])
start
: 可选参数,表示序列的起始值,默认为0。stop
: 必选参数,表示序列的终止值(不包含在序列内)。step
: 可选参数,表示步长(即相邻两个数之间的间隔),默认为1。2.4.3.2 返回值
range()
函数返回一个可迭代对象(不是列表),它生成指定范围内的整数。2.4.3.3 range的使用例子
# 生成指定范围的整数序列: # 生成从0到4的整数序列 for i in range(5): print(i) # 输出:0 1 2 3 4 # 生成从2到6的整数序列 for i in range(2, 7): print(i) # 输出:2 3 4 5 6 # 生成从1到10的偶数序列 for i in range(2, 11, 2): print(i) # 输出:2 4 6 8 10 # 转换为列表 # 使用 list() 将 range 对象转换为列表 my_list = list(range(1, 6)) print(my_list) # 输出:[1, 2, 3, 4, 5] # 反向序列: # 生成递减序列 for i in range(10, 0, -2): print(i) # 输出:10 8 6 4 2
2.4.3.4 range的使用注意事项
range()
生成的序列包括起始值,但不包括终止值。- 如果
start
大于或等于stop
,则返回空序列。- 步长
step
可以为负数,这时start
必须大于stop
,用于生成递减的序列。2.4.4 使用列表推导式(List Comprehensions)
列表推导式是一种创建列表的紧凑语法,通常用于从一个可迭代对象中过滤和转换数据来创建新列表。
# 创建一个包含平方数的列表 squares = [x**2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] # 创建一个只包含偶数的列表 even_numbers = [x for x in range(20) if x % 2 == 0] # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
2.5 列表添加元素
当列表增加和删除元素时,列表会自动进行内存管理,大大减少了程序员的负担。但这个特点涉及列表元素的大量移动,效率较低。
除非必要,我们一般只在列表的尾部添加元素或删除元素,这会大大提高列表的操作效率。
2.5.1 使用
append()
方法
append()
方法用于在列表的末尾添加一个元素。原地修改列表对象,是真正的列表尾部添加新的元素,速度最快,推荐使用。
# 初始化一个空列表 my_list = [] # 使用 append() 方法添加元素 my_list.append(1) my_list.append(2) my_list.append(3) print(my_list) # 输出: [1, 2, 3]
2.5.2 使用
+
运算符并不是真正的尾部添加元素,而是创建新的列表对象;将原列表的元素和新列表的元素依次复制到新的列表对象中。这样,会涉及大量的复制操作,对于操作大量元素不建议使用。
# 初始化两个列表 list1 = [1, 2, 3] list2 = [4, 5] # 使用 + 运算符连接两个列表 combined_list = list1 + list2 print(combined_list) # 输出: [1, 2, 3, 4, 5]
2.5.3 使用
extend()
方法
extend()
方法用于将另一个列表的所有元素添加到当前列表的末尾,属于原地操作,不创建新的列表对象。# 初始化两个列表 list1 = [1, 2, 3] list2 = [4, 5] # 使用 extend() 方法将 list2 的元素扩展到 list1 list1.extend(list2) print(list1) # 输出: [1, 2, 3, 4, 5]
2.5.4 使用
insert()
方法
insert()
方法允许在指定位置插入一个元素,- 其语法为
list.insert(index, element)
。
- 使用
insert()
方法可以将指定的元素插入到列表对象的任意制定位置。这样会让插入位置后面所有的元素进行移动,会影响处理速度。涉及大量元素时,尽量避免使用。类似发生这种移动的函数还有:remove()、pop()、del(),它们在删除非尾部元素时也会发生操作位置后面元素的移动。# 初始化一个列表 my_list = [1, 2, 3] # 在索引为 1 的位置插入元素 5 my_list.insert(1, 5) print(my_list) # 输出: [1, 5, 2, 3]
2.5.5 使用乘法操作符
*
乘法操作符
*
可以将列表中的元素重复指定的次数。使用乘法扩展列表,生成一个新列表,新列表元素是原列表元素的多次重复。
# 使用乘法操作符创建重复元素的列表 my_list = [0] * 5 print(my_list) # 输出: [0, 0, 0, 0, 0]
适用于乘法操作的,还有:字符串、元组。例如:
a = '123' a = a*3 print(a) # 123123123
2.6 列表删除元素
2.6.1 使用
del
语句
del
语句用于删除列表中指定索引位置的元素。# 创建一个列表 my_list = [1, 2, 3, 4, 5] # 删除索引为2的元素,即第3个元素(值为3) del my_list[2] print(my_list) # 输出: [1, 2, 4, 5]
2.6.2 使用
pop()
方法
pop()
方法用于删除并返回指定索引位置的元素,默认是列表的最后一个元素。# 创建一个列表 my_list = [1, 2, 3, 4, 5] # 删除并返回最后一个元素(值为5) deleted_element = my_list.pop() print(deleted_element) # 输出: 5 print(my_list) # 输出: [1, 2, 3, 4]
也可以指定要删除的元素的索引:
# 删除索引为1的元素(值为2) deleted_element = my_list.pop(1) print(deleted_element) # 输出: 2 print(my_list) # 输出: [1, 3, 4]
2.6.3 使用
remove()
方法
remove()
方法用于删除列表中第一个匹配给定值(首次出现的指定元素)的元素。若不存在该元素抛出异常
# 创建一个列表 my_list = [1, 2, 3, 4, 2] # 删除值为2的第一个匹配元素 my_list.remove(2) print(my_list) # 输出: [1, 3, 4, 2]
2.6.4 删除元素底层是:元素的拷贝
Python 的列表实际上是一个数组,用于存储元素。这个数组的大小是动态调整的,当添加或删除元素时,Python 会根据需要调整数组的大小。
删除元素的复制问题:
当你删除列表中的一个元素时,Python 并不是简单地将这个元素从数组中删除,而是将列表中的元素重新组织和移动,以保证列表的连续性和内存的整齐性。
删除元素时,为了保持列表的连续性,列表中被删除元素后面的元素需要向前移动一个位置。这就意味着,如果列表中有 n 个元素,删除第一个元素时,其余的 n-1 个元素都需要向前移动一个位置。
如果你使用del
语句或pop()
方法删除元素,Python 会根据需要重新分配内存,并移动其余元素,以保证列表的正确性。为什么会涉及元素的拷贝?:
- 删除元素涉及到移动列表中的元素位置,这意味着列表中剩余的元素可能需要在内存中重新组织和移动,而不是简单地在数组中标记删除。
- 如果没有元素的拷贝和移动,就无法保证列表的内部连续性和正确性,这是由动态数组的特性决定的。
2.7 列表的访问
2.7.1 通过索引来实现
可以通过索引直接访问元素。索引的区间在 [0, 列表长度-1]这个范围。
超过这个范围则会抛出异常。
# 创建一个列表 my_list = [10, 20, 30, 40, 50] # 访问单个元素,索引为2(第3个元素,值为30) print(my_list[2]) # 访问多个元素,使用切片操作 # 获取索引为1到3(不包括3)的元素,即第2到第4个元素 print(my_list[1:3]) # 输出: [20, 30] # 获取最后一个元素,使用负数索引-1 print(my_list[-1]) # 输出: 50 # 获取倒数第二个到倒数第一个元素,即倒数第2到第1个元素 print(my_list[-2:]) # 输出: [40, 50]
2.7.2 使用
index()
函数查找元素索引
index()
函数用于查找列表中第一个匹配给定值的元素,并返回其索引。如果列表中不存在该元素,则会引发ValueError
异常。# 创建一个列表 my_list = [10, 20, 30, 20, 40, 50] # 查找值为20的第一次出现的索引 index_of_twenty = my_list.index(20) print(index_of_twenty) # 输出: 1 # 可以指定起始和结束的索引范围进行查找 # 在索引为2到末尾的范围内查找值为20的第一次出现的索引 index_of_twenty = my_list.index(20, 2) print(index_of_twenty) # 输出: 3
示例中,
index_of_twenty
变量分别存储了值为20的元素在my_list
中第一次出现的索引位置。如果要查找的元素不在列表中,调用index()
方法将引发ValueError
异常。
index()
方法只返回第一个匹配元素的索引。如果需要查找所有匹配元素的索引,可以使用列表解析或循环来实现。- 当要查找的元素不存在于列表中时,
index()
方法会引发ValueError
异常。因此,在使用之前,最好先使用in
关键字检查元素是否存在于列表中。2.8 元素在列表的出现的次数
count()
方法是列表对象提供的一个非常有用的方法之一,用于统计列表中特定元素出现的次数。# 创建一个列表 my_list = [1, 2, 3, 2, 4, 2, 5] # 统计列表中元素2出现的次数 count_of_twos = my_list.count(2) print(count_of_twos) # 输出: 3
my_list.count(2)
返回了值为2的元素在列表my_list
中出现的次数,即3次。
- 如果列表中没有与指定值匹配的元素,
count()
方法将返回0。count()
方法是列表对象的一个实例方法,可以通过列表变量名.count()
的形式调用。count()
方法只计算列表中直接包含的元素,不会递归地搜索嵌套在列表内部的其他可迭代对象(如嵌套列表或元组)中的元素。2.9 列表的长度
len()
函数是 Python 内置函数之一,用于返回一个对象(如列表)的长度或者元素个数。
函数定义:
len(object)
参数:
object
: 可以是序列(如列表、元组、字符串)或者集合(如字典、集合)等对象。
返回值:
len()
函数返回对象中包含的元素个数。# 创建一个列表 my_list = [1, 2, 3, 4, 5] # 获取列表的长度 length_of_list = len(my_list) print(length_of_list) # 输出: 5
len()
函数对于不同类型的对象返回的含义略有不同。对于序列类型(如列表、元组、字符串),它返回序列中元素的个数;对于集合类型(如字典、集合),它返回集合中元素的个数。- 如果传递给
len()
函数的对象是空的(即没有任何元素),则返回的长度为0。- 对于自定义对象,可以通过实现
__len__()
特殊方法来自定义对象的长度计算行为,使得该对象可以作为len()
函数的参数。2.10 成员检测的运算符 in / not in
in
和not in
是用于成员检测的运算符,常用于判断一个元素是否包含在一个序列(如列表、元组、字符串等)中。它们提供了一种简洁且直观的方式来检查特定元素是否存在于给定的序列中。2.10.1
in
运算符
in
运算符用于检查一个元素是否存在于一个序列中,如果存在则返回True
,否则返回False
。# 检查元素是否存在于列表中 my_list = [1, 2, 3, 4, 5] print(3 in my_list) # 输出: True print(6 in my_list) # 输出: False
2.10.2
not in
运算符
not in
运算符是in
的反义词,用于检查一个元素是否不存在于一个序列中,如果不存在则返回True
,否则返回False
。# 检查元素是否不存在于列表中 my_list = [1, 2, 3, 4, 5] print(3 not in my_list) # 输出: False print(6 not in my_list) # 输出: True
注意事项:
in
和not in
运算符可以用于任何支持成员检测的数据结构,例如列表、元组、字符串、集合、字典的键等。- 对于字典,
in
和not in
运算符默认检查的是字典的键是否存在,而不是值。2.11 列表的切片(slice)操作
列表(list)支持强大的切片(slice)操作,这使得对列表进行灵活和高效的子集操作成为可能。切片操作允许我们从一个列表中提取出指定范围内的元素子集,而不必修改原始列表。
类似字符串的切片操作,对于列表的切片操作和字符串类似。
切片是Python序列及其重要的操作,适用于列表、元组、字符串等等。
切片slice操作可以让我们快速提取子列表或修改。标准格式为:
list[start:stop:step]
[起始偏移量start:终止偏移量end[:步长step]]
- 切片开始位置的索引,包含在切片内(默认为0)。
stop
: 切片结束位置的索引,不包含在切片内(默认为列表的长度)。step
: 切片的步长(默认为1),表示从start
索引开始每隔step
个元素取一个元素。典型操作(三个量为正数【start:stop:step为正数】的情况)如下:
操作和说明
示例
结果
[:] 提取整个列表
[10,20,30][:]
[10,20,30]
[start:] 从start索引开始到结尾
[10,20,30][1:]
[20,30]
[:end] 从头开始知道end-1
[10,20,30][:2]
[10,20]
[start:end] 从start到end-1
[10,20,30,40][1:3]
[20,30]
[start:end:step] 从start提取到end-1,步长是step
[10,20,30,40,50,60,70][1:6:2]
[20, 40, 60]
其他操作(三个量为负数【start:stop:step为负数】)的情况:
示例
说明
结果
[10,20,30,40,50,60,70][-3:]
倒数三个
[50,60,70]
[10,20,30,40,50,60,70]
[-5:-3]
倒数第五个到倒数第三个(包头不包尾)
[30,40]
[10,20,30,40,50,60,70][::-1]
步长为负,从右到左反向提取
[70, 60, 50, 40, 30, 20,
10]
切片操作时,起始偏移量和终止偏移量不在[0,字符串长度-1]这个范围,也不会报错。起始偏移量小于0则会当做0,终止偏移量大于“长度-1”会被当成”长度-1”,
例如:
[10,20,30,40][1:30]
结果:
[20, 30, 40]
2.12 列表的遍历
使用
for
循环是最常见和简单的遍历列表的方式。可以按顺序逐个访问列表中的元素。my_list = [1, 2, 3, 4, 5] for item in my_list: print(item)
输出:
1 2 3 4 5
2.13 列表的复制
首先,如下代码并没有真正做到复制,
list1 = [30,40,50] list2 = list1
只是将list2也指向了列表对象,也就是说list2和list2持有地址值
是相同的,列表对象本身的元素并没有复制。
我们可以通过如下简单方式,实现列表元素内容的复制:
list1 = [30,40,50] list2 = [] + list1 #生成了新列表对象
也可以用copy模块进行深浅拷贝,这个后面会单独写一篇
2.14 列表的排序
2.14.1 就地排序
就地排序是指直接修改原始列表,而不返回新的列表副本。
列表的
sort()
方法:numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5] numbers.sort() print(numbers) # 输出:[1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
sort()
方法默认按升序排序。如果需要降序排序,可以使用reverse=True
参数:numbers.sort(reverse=True) print(numbers) # 输出:[9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1]
2.14.2 返回排序后的新列表
返回排序后的新列表,不修改原始列表。
内置函数
sorted():
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5] sorted_numbers = sorted(numbers) print(sorted_numbers) # 输出:[1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
sorted()
函数也可以接受reverse=True
参数进行降序排序:sorted_numbers_desc = sorted(numbers, reverse=True) print(sorted_numbers_desc) # 输出:[9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1]
2.15 打乱列表顺序
打乱列表的顺序(即随机化列表元素的顺序),可以使用
random
模块中的shuffle()
函数。这个函数会直接修改原始列表,将列表中的元素随机打乱顺序,不返回新的列表副本。使用
random.shuffle()
函数:
shuffle()
函数会随机打乱numbers
列表的元素顺序。import random numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] random.shuffle(numbers) print(numbers) # 打印打乱顺序后的列表
random.shuffle()
是就地操作,会直接修改原始列表,而不返回新的列表。因此,如果需要保留原始列表的顺序,可以先复制一份列表再打乱。import random numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] shuffled_numbers = numbers[:] # 复制列表 random.shuffle(shuffled_numbers) print(shuffled_numbers) # 打印打乱顺序后的列表
注意:shuffle()
函数只能用于可变序列(如列表),对于不可变序列(如元组),可以先将其转换为列表再打乱。2.16 列表元素的反转
2.16.1 使用切片[::-1]
可以使用切片反转列表,
numbers = [1, 2, 3, 4, 5] reversed_numbers = numbers[::-1] print(reversed_numbers) # 输出:[5, 4, 3, 2, 1] print(numbers) # 输出:[1, 2, 3, 4, 5]
2.16.2
reversed()
函数
reversed()
函数是用来返回一个反向迭代器(iterator)的内置函数。它接受一个可迭代对象作为参数,并返回一个将该对象元素反向输出的迭代器,而不是直接返回一个新的反向列表。numbers = [1, 2, 3, 4, 5] reversed_numbers = reversed(numbers) print(reversed_numbers) # 输出:<list_reverseiterator object at 0x7f9f16c14310> # 使用 list() 函数将迭代器转换为列表 reversed_list = list(reversed_numbers) print(reversed_list) # 输出:[5, 4, 3, 2, 1]
reversed(numbers)
返回一个迭代器对象<list_reverseiterator object at 0x...>
,而不是直接返回一个列表。要访问其内容,可以将其传递给list()
函数转换为列表。
reversed()
返回的是一个迭代器对象,它只能被遍历一次。一旦遍历完毕或转换为列表后,就无法再次使用相同的迭代器。numbers = [1, 2, 3, 4, 5] reversed_numbers = reversed(numbers) print(list(reversed_numbers)) # 输出:[5, 4, 3, 2, 1] print(list(reversed_numbers)) # 输出:[]
第二次调用
list(reversed_numbers)
返回的是空列表[]
,因为迭代器已经被耗尽。
reversed()
不仅可以用于列表,还可以用于任何可迭代对象,如元组、字符串等。- 由于
reversed()
返回的是一个迭代器而不是列表,它可以在不需要一次性将所有元素存储在内存中的情况下进行操作。这在处理大型数据集或需要节省内存的情况下特别有用。2.17 内置函数
max()
、min()
和sum()在列表中的使用
2.17.1 max()
max()
函数用于返回列表中的最大值(或者可迭代对象中的最大值)。numbers = [1, 3, 5, 2, 4] max_number = max(numbers) print(max_number) # 输出:5
- 如果列表中的元素是可比较的(比如整数或字符串),
max()
将返回列表中的最大值。- 如果列表为空,
max()
将抛出ValueError
异常。
2.17.2 min()
min()
函数用于返回列表中的最小值(或者可迭代对象中的最小值)。numbers = [1, 3, 5, 2, 4] min_number = min(numbers) print(min_number) # 输出:1
- 如果列表中的元素是可比较的,
min()
将返回列表中的最小值。- 如果列表为空,
min()
将抛出ValueError
异常。2.17.3
sum()
sum()
函数用于计算列表中所有元素的和(或者可迭代对象中的所有元素的和)。numbers = [1, 2, 3, 4, 5] total_sum = sum(numbers) print(total_sum) # 输出:15
sum()
将迭代列表中的所有元素,并返回它们的总和。- 如果列表为空,
sum()
将返回0
(注意这与其他语言的处理方式可能有所不同)。- 可以提供第二个参数
start
来指定起始值,例如sum(numbers, 10)
将计算10 + 1 + 2 + ...
的和。2.18 多维列表
一维列表可以帮助我们存储一维、线性的数据。
二维列表可以帮助我们存储二维、表格的数据。例如下表的数据:
姓名
年龄
薪资
城市
张三
18
30000
北京
李四
19
20000
上海
赵五
20
10000
深圳
例如如下二维列表:
data = [ ["张三",18,30000,"北京"], ["李四",19,20000,"上海"], ["赵五",20,10000,"深圳"], ]
内存结构图如下:
例如,取出列表的第一个的值
print(data[1][0],a[1][1],a[1][2]) # 李四 19 20000
可以循环打印这个二维列表:
data = [ ["张三",18,30000,"北京"], ["李四",19,20000,"上海"], ["赵五",20,10000,"深圳"], ] for i in range(3): for j in range(4): print(data[i][j],end="\t") print()
输出结果:
张三 18 30000 北京 李四 19 20000 上海 赵五 20 10000 深圳
第十六讲 python中的序列-列表简介-特点-常用方法-创建-添加-删除-访问-切片-排序-复制-反转
于 2024-07-19 15:08:14 首次发布