列表
简介
在Python中,列表(List)是一种基本的数据结构,它是一个有序的集合,可以包含重复的元素,并且能够存储不同类型的数据项(例如,整数、字符串、甚至其他列表)。列表是可变的(Mutable),这意味着你可以在创建列表后修改它的内容。
列表是Python中非常重要且功能强大的数据结构,支持多种操作,包括迭代、排序和嵌套等。正确使用列表可以使得代码更加简洁、高效。
原理
Python中的列表(List)是一种动态数组,但与其他语言中的传统数组相比,它们更加灵活和强大。要理解列表的工作原理,我们需要了解几个关键点:
动态数组的概念
-
动态大小:Python列表不需要事先声明大小。你可以随时添加或删除元素,列表会自动调整其大小以适应内容。
-
内存分配:在底层,Python列表使用连续的内存块来存储数据。当你创建一个空列表或添加元素到列表中时,Python解释器会分配一块内存给这个列表。如果继续添加元素超过了当前分配的内存大小,列表会自动重新分配一个更大的内存块来容纳更多的元素,然后将原来的元素复制到新的内存块中。这个过程是自动的,对用户来说是透明的。
-
时间复杂度:由于动态数组的特性,列表的操作具有不同的时间复杂度。例如,末尾添加元素(
append
)是常数时间复杂度(O(1)),因为它只需要将新元素放在列表的末尾。但是,如果在列表的开头插入元素,则所有后续的元素都需要向后移动一位,这个操作的时间复杂度是线性的(O(n)),其中n是列表的长度。
列表的优化
Python的列表实现对常见操作进行了优化。例如,当列表增长时,解释器不仅仅为一个新元素分配内存,而是分配一块比当前需求稍大的内存区域。这意味着随后的几次append
操作不需要重新分配内存,从而提高效率。这种策略称为“过剩分配”(overallocation),是一种空间换时间的优化策略。
列表与其他数据结构的比较
- 数组:与固定大小的数组相比,列表更加灵活,可以动态地添加和删除元素。但是,这种灵活性也意味着列表在某些操作上可能比固定大小的数组慢。
- 链表:与链表相比,列表通过使用连续的内存块,可以提供更快的元素访问时间(因为它支持随机访问),但在插入和删除(特别是在列表中间)时可能不如链表高效。
总的来说,Python列表是一种非常通用的数据结构,适用于大多数情况,除非你的应用场景需要特别关注某些操作的性能。在这种情况下,可能需要考虑其他数据结构,如元组(Tuple)、集合(Set)或字典(Dictionary),或者使用专门的数据结构库,如NumPy数组,这些都是根据特定需求优化的。
操作
创建列表
列表可以通过将元素放在方括号[]
中,用逗号分隔来创建。
my_list = [1, "Hello", 3.14, [1, 2, 3]]
访问列表元素
列表元素可以通过索引来访问,索引从0开始。
print(my_list[1]) # 输出: Hello
还可以使用负索引,-1表示最后一个元素,-2表示倒数第二个元素,以此类推。
print(my_list[-1]) # 输出: [1, 2, 3]
修改列表元素
由于列表是可变的,你可以修改其元素。
my_list[1] = "World"
print(my_list) # 输出: [1, "World", 3.14, [1, 2, 3]]
列表切片
切片操作允许你获取列表的一部分。
print(my_list[1:3]) # 输出: ['World', 3.14]
列表追加和扩展
- 使用
append()
方法在列表末尾添加一个元素。 - 使用
extend()
方法可以将另一个集合中的元素逐一添加到列表中。
my_list.append(100)
my_list.extend([200, 300])
删除列表元素
- 使用
remove()
方法删除列表中的特定元素。 - 使用
pop()
方法删除指定位置的元素(默认是最后一个元素)。
my_list.remove("World")
last_item = my_list.pop()
列表排序
列表提供了sort()
方法对列表进行原地排序。
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort()
print(numbers) # 输出: [1, 1, 2, 3, 4, 5, 9]
列表推导式
列表推导式提供了一种简洁的方式来创建列表。
squares = [x**2 for x in range(10)]
列表长度
使用len()
函数可以获取列表的长度。
print(len(my_list))
检查元素是否在列表中
可以使用in
关键字来检查元素是否存在于列表中。
if "Hello" in my_list:
print("Hello is in the list")
操作示例
"""
在Python中,列表是一种数据结构,可以包含任何类型的项,例如数字、字符串、其他列表等。
列表是有序的,这意味着它们的元素有特定的顺序,可以通过索引访问。
"""
# 创建列表
list1 = ['a', 'b', 'c', 'd']
print(f"list1 ==> {list1}")
# 列表的元素可以混合不同数据类型
list2 = [1, 2, 3, 4, '中文字符串', [1.1, 3.3], None]
print(f"list2 ==> {list2}")
# 追加元素
list1.append('test_append_element')
print(f"追加元素:list1 ==> {list1}")
# 获取元素
print("获取list1的索引为0的元素:" + list1[0])
# 修改元素
list1[0] = 'test_modify_element'
print(f"修改元素:list1 ==> {list1}")
# 删除元素
del list1[1]
list1.remove('c') # 删除找到的第一个元素,找不到就报错
print(f"删除元素:list1 ==> {list1}")
# 删除并返回元素
print("删除并返回元素:" + list1.pop(1)) # 删除并返回索引为1的元素,默认删除最后一个元素
print(f"删除元素:list1 ==> {list1}")
# 列表的切片
print(f"列表的切片:{list2[0:2]}") # 生成一个新的列表,不会改变原列表
print(f"列表的切片:list2 ==> {list2}")
# 列表的拼接,生成一个新的列表
list3 = list1 + list2
print(f"列表的拼接1,生成一个新的列表:list3 ==> {list3}")
# 列表的拼接2,修改原列表
list1.extend(list2)
print(f"列表的拼接2,修改原列表:list1 ==> {list1}")
print(f"列表的拼接2,修改原列表:list2 ==> {list2}")
# 列表的反转
list1.reverse()
print(f"列表的反转,修改原列表:list1 ==> {list1}")
# 列表的反转
print(f"列表的反转,不修改原列表:list1 ==> {list1[::-1]}")
# 元素是否在列表中
print(f"元素是否在列表中:{1 in list1}")
# 判断元素在列表中的索引
print(f"判断元素在列表中的索引:{list1.index(1)}")
高级操作
Python列表提供了一系列高级操作,使得处理数据变得更加高效和灵活。以下是一些较为高级的列表操作:
1. 列表推导式(List Comprehensions)
列表推导式是一种简洁创建列表的方法,它可以用来生成列表,过滤列表中的元素,或者对列表中的元素进行操作。
# 生成0到9每个数字的平方的列表
squares = [x**2 for x in range(10)]
# 过滤出列表中的偶数
evens = [x for x in range(10) if x % 2 == 0]
# 对列表中的元素进行操作
fruits = ["apple", "banana", "cherry"]
upper_fruits = [fruit.upper() for fruit in fruits]
2. 嵌套列表推导式
列表推导式可以嵌套,用于生成或操作多维列表。
# 生成一个3x3的矩阵
matrix = [[j for j in range(3)] for i in range(3)]
# 输出 matrix ==> [[0, 1, 2], [0, 1, 2], [0, 1, 2]]
3. 列表的zip
函数
zip
函数用于将多个列表对应位置的元素打包成一个个元组,然后返回由这些元组组成的列表。这对于同时遍历多个列表非常有用。
names = ["Alice", "Bob", "Charlie"]
scores = [85, 90, 88]
for name, score in zip(names, scores):
print(f"{name}: {score}")
"""
输出:
Alice: 85
Bob: 90
Charlie: 88
"""
4. 列表的enumerate
函数
enumerate
函数用于在遍历列表时同时获取元素的索引和值,这在需要索引时非常有用。
for index, name in enumerate(names):
print(f"{index}: {name}")
5. 列表的filter
函数
filter
函数用于过滤列表中的元素,只留下符合条件的元素。
# 过滤出列表中的偶数
evens = list(filter(lambda x: x % 2 == 0, range(10)))
6. 列表的map
函数
map
函数用于对列表中的所有元素应用一个函数。
# 将列表中的每个元素乘以2
doubles = list(map(lambda x: x * 2, range(10)))
7. 列表的reduce
函数
reduce
函数用于对列表中的元素进行累积操作,比如累加、累乘等。它不是列表的内置函数,需要从functools
模块导入。
from functools import reduce
# 计算列表中元素的总和
total = reduce(lambda x, y: x + y, range(10))
8. 列表的切片赋值
列表的切片赋值可以一次性替换列表中的一段元素。
a = [1, 2, 3, 4, 5]
a[2:4] = [0, 0]
# a 现在是 [1, 2, 0, 0, 5]
练习
对数据进行分组,分组规则如下:
1. 80分以上为一组
2. 60-79分为一组
3. 40-59分为一组
4. 20-39分为一组
5. 20分以下为一组
stu_list = [['李渊', 82], ['李世民', 7], ['侯君集', 5], ['李靖', 58], ['魏征', 41], ['房玄龄', 64], ['杜如晦', 65], ['柴绍', 94],
['程知节', 45], ['尉迟恭', 94], ['秦琼', 54], ['长孙无忌', 85], ['李存恭', 98], ['封德彝', 16], ['段志玄', 44], ['刘弘基', 18],
['徐世绩', 86], ['李治', 19], ['武则天', 39], ['太平公主', 57], ['韦后', 76], ['李隆基', 95], ['杨玉环', 33], ['王勃', 49],
['陈子昂', 91], ['卢照邻', 70], ['杨炯', 81], ['王之涣', 82], ['安禄山', 18], ['史思明', 9], ['张巡', 15], ['雷万春', 72],
['李白', 61], ['高力士', 58], ['杜甫', 27], ['白居易', 5], ['王维', 14], ['孟浩然', 32], ['杜牧', 95], ['李商隐', 34],
['郭子仪', 53], ['张易之', 39], ['张昌宗', 61], ['来俊臣', 8], ['杨国忠', 84], ['李林甫', 95], ['高适', 100], ['王昌龄', 40],
['孙思邈', 46], ['玄奘', 84], ['鉴真', 90], ['高骈', 85], ['狄仁杰', 62], ['黄巢', 79], ['王仙芝', 16], ['文成公主', 13],
['松赞干布', 47], ['薛涛', 79], ['鱼玄机', 16], ['贺知章', 20], ['李泌', 17], ['韩愈', 100], ['柳宗元', 88],
['上官婉儿 五代十国:朱温', 55], ['刘仁恭', 6], ['丁会', 26], ['李克用', 39], ['李存勖', 11], ['葛从周', 25], ['王建', 13],
['刘知远', 95], ['石敬瑭', 63], ['郭威', 28], ['柴荣', 50], ['孟昶', 17], ['荆浩', 84], ['刘彟', 18], ['张及之', 45],
['杜宇', 73], ['高季兴', 39], ['喻皓', 50], ['历真', 70], ['李茂贞', 6], ['朱友珪', 7], ['朱友贞', 11], ['刘守光', 2]]
"""
对以上数据进行分组,分组规则如下:
1. 80分以上为一组
2. 60-79分为一组
3. 40-59分为一组
4. 20-39分为一组
5. 20分以下为一组
"""
# 1. 创建5个空列表
new_stu_list = [
[],
[],
[],
[],
[],
]
# 2. 遍历列表
for stu in stu_list:
if stu[1] >= 80:
new_stu_list[0].append(stu)
elif stu[1] >= 60:
new_stu_list[1].append(stu)
elif stu[1] >= 40:
new_stu_list[2].append(stu)
elif stu[1] >= 20:
new_stu_list[3].append(stu)
else:
new_stu_list[4].append(stu)
# 3. 打印分组结果
print("80分以上:", new_stu_list[0])
print("60-79分:", new_stu_list[1])
print("40-59分:", new_stu_list[2])
print("20-39分:", new_stu_list[3])
print("20分以下:", new_stu_list[4])