一、列表(List)
1. 定义与表示
- 列表是 Python 中最常用的有序、可变数据类型,用于存储一系列元素(元素可以是任意数据类型,包括嵌套列表、字典、集合、元组等)。
- 表示方式:用 [] 包裹元素,元素之间用逗号分隔,例如:
list1 = [1, 2, 3] # 整数列表
list2 = ["a", 1, True, [4, 5]] # 混合类型列表(字符串、布尔、嵌套列表)
empty_list = [] # 空列表
2. 核心特性
- 有序性:元素有固定顺序,可通过索引访问(索引从 0 开始)。
- 可变性:可修改、添加、删除元素(内存地址不变,内容可变)。
- 可重复性:允许包含重复元素。
- 异构性:元素可以是不同数据类型(整数、字符串、列表等)。
3. 基本操作
(1)访问元素(索引与切片)
- 索引:通过 list[index] 访问单个元素(支持正向索引和反向索引)。
lst = ["a", "b", "c", "d"]
print(lst[0]) # 正向索引:第1个元素,输出 "a"
print(lst[-1]) # 反向索引:最后1个元素,输出 "d" - 切片:通过 list[start:end:step] 访问子列表(左闭右开,step 为步长)。
lst = [0, 1, 2, 3, 4, 5]
print(lst[1:4]) # 从索引1到3,输出 [1, 2, 3]
print(lst[::2]) # 步长2,取所有偶数索引元素,输出 [0, 2, 4]
print(lst[::-1]) # 步长-1,反转列表,输出 [5, 4, 3, 2, 1, 0]
(2)修改元素
- 直接通过索引赋值修改元素:
lst = [1, 2, 3]
lst[1] = 20 # 修改索引1的元素,结果:[1, 20, 3]
(3)拼接与重复
- 拼接:用 + 合并两个列表(生成新列表,原列表不变)。
lst1 = [1, 2]
lst2 = [3, 4]
print(lst1 + lst2) # 输出 [1, 2, 3, 4] - 重复:用 * 重复列表元素(生成新列表)。
lst = [1, 2]
print(lst * 3) # 输出 [1, 2, 1, 2, 1, 2]
(4)成员判断
- 用 in 判断元素是否在列表中,not in 判断是否不在。
lst = [1, 2, 3]
print(2 in lst) # 输出 True
print(4 not in lst) # 输出 True
(5)长度、最大 / 最小值
- len(lst):返回列表元素个数。
- max(lst)/min(lst):返回列表中最大 / 最小元素(元素需可比较,如全为数字或全为字符串)。
lst = [3, 1, 4]
print(len(lst)) # 输出 3
print(max(lst)) # 输出 4
4. 常用方法(重点)
append(x) | 在列表末尾添加元素 x(修改原列表,无返回值) | lst = [1,2]; lst.append(3) | [1, 2, 3] |
extend(iter) | 用可迭代对象 iterable(如列表、元组)中的元素扩展到列表(批量添加,原列表不变) | lst = [1,2]; lst.extend([3,4]) | [1, 2, 3, 4] |
insert(index, x) | 在索引 index 处插入元素 x(原元素后移) | lst = [1,3]; lst.insert(1, 2) | [1, 2, 3] |
remove(x) | 删除列表中第一个出现的元素 x(若不存在则报错) | lst = [1,2,2]; lst.remove(2) | [1, 2] |
pop(index) | 删除并返回索引 index 处的元素(默认删除最后一个,索引不存在则报错) | lst = [1,2,3]; lst.pop(1) | 返回 2,列表变为 [1, 3] |
clear() | 清空列表(保留空列表) | lst = [1,2]; lst.clear() | [] |
index(x) | 返回元素 x 在列表中第一个出现的索引(若不存在则报错) | lst = [1,2,3,2]; lst.index(2) | 返回 1 |
count(x) | 统计元素 x 在列表中出现的次数 | lst = [1,2,2,3]; lst.count(2) | 返回 2 |
sort(key=None, reverse=False) | 对列表元素排序(默认升序,reverse=True 降序,修改原列表) | lst = [3,1,2]; lst.sort() | [1, 2, 3] |
reverse() | 反转列表元素顺序(修改原列表) | lst = [1,2,3]; lst.reverse() | [3, 2, 1] |
copy() | 复制列表(浅拷贝,返回新列表) | lst = [1,2]; new_lst = lst.copy() | new_lst 为 [1,2](与原列表独立) |
5. 列表推导式(高效生成列表)
- 语法:[表达式 for 变量 in 可迭代对象 if 条件]
- 作用:用一行代码生成列表,比循环更简洁高效。
# 生成1-10的平方列表
squares = [x**2 for x in range(1, 11)]
print(squares) # 输出 [1, 4, 9, …, 100]# 筛选偶数
even_numbers = [x for x in range(1, 11) if x % 2 == 0]
print(even_numbers) # 输出 [2, 4, 6, 8, 10]# 嵌套列表推导式(二维列表转一维)
matrix = [[1,2], [3,4], [5,6]]
flat = [num for row in matrix for num in row]
print(flat) # 输出 [1, 2, 3, 4, 5, 6]#嵌套循环(类似双重 for 循环):
[表达式 for 变量1 in 可迭代对象1 for 变量2 in 可迭代对象2]
比如 [i*j for i in [1,2] for j in [3,4]] → 结果 [3,4,6,8]
6. 注意事项
注:拷贝的差异,本质上体现在对嵌套的可变对象的处理上。因为对不可变对象来说,不管是深拷贝还是浅拷贝,其实都没啥区别,因为它们本身不能被修改,就相当于复制了一份一样的 “副本”,而且这个 “副本” 和原对象的值、地址啥的都一样。
1. 浅拷贝(shallow copy)
只拷贝 “外层对象”,但对于外层对象中嵌套的可变子对象,不重新创建,而是直接引用原对象的子对象(即共享同一份子对象,同一个地址)。
示例(关键看嵌套的可变对象):
import copy
# 原列表:外层是列表(可变),里面嵌套了一个子列表(可变)
old_list = [1, 2, [3, 4]] # 1、2是不可变对象,[3,4]是可变子对象
# 浅拷贝
new_list = old_list.copy() # 等价于 old_list[:] 或 copy.copy(old_list)
# 测试1:修改外层的不可变元素(不影响原列表)
new_list[0] = 100
print(old_list) # [1, 2, [3, 4]](原列表不变)
print(new_list) # [100, 2, [3, 4]]
# 测试2:修改嵌套的可变子对象(原列表和新列表会同时变化!)
new_list[2][0] = 300 # 修改子列表的第一个元素
print(old_list) # [1, 2, [300, 4]](原列表的子列表被改了!)
print(new_list) # [100, 2, [300, 4]]
2. 深拷贝(deep copy)
不仅拷贝 “外层对象”,还会递归地拷贝所有嵌套的可变子对象,生成完全独立的新对象,与原对象没有任何共享引用。(全部纯纯新的地址)
示例(嵌套对象完全独立):
import copy
old_list = [1, 2, [3, 4]] # 同上
# 深拷贝
new_list = copy.deepcopy(old_list)
# 测试1:修改外层元素(不影响原列表,和浅拷贝一样)
new_list[0] = 100
print(old_list) # [1, 2, [3, 4]]
print(new_list) # [100, 2, [3, 4]]
# 测试2:修改嵌套的可变子对象(原列表完全不受影响!)
new_list[2][0] = 300
print(old_list) # [1, 2, [3, 4]](原列表的子列表没变!)
print(new_list) # [100, 2, [300, 4]]
3.区别
外层对象 | 复制新对象,独立 | 复制新对象,独立 |
嵌套的可变子对象 | 不复制,共享引用(改一个影响另一个) | 递归复制,生成新子对象(完全独立,互不影响) |
性能 | 更快(复制少) | 较慢(递归复制多) |
-
Python 中的对象分为不可变对象(如整数、字符串、元组)和可变对象(如列表、字典、集合)。
- 不可变对象:值一旦创建就不能修改,修改时会生成新对象(本质就是生成新地址)。
- 可变对象:值可以直接修改,修改时不会生成新对象(如 list1[0]=10 是在原地址上改)。
- 列表切片:new_list = old_list[:]
- list.copy() 方法:new_list = old_list.copy()
- copy 模块的 copy() 函数:new_list = copy.copy(old_list)(推荐)
- copy模块里的copy函数挺万能的,不管是列表、字典还是集合,都能用它来做浅拷贝。这样就不用记每个类型各自的拷贝方法,一个函数搞定好多类型。
- copy 模块的 deepcopy() 函数:new_list = copy.deepcopy(old_list)
4.应用
浅拷贝:它速度快,占用内存少。如果你的对象里没有嵌套可变对象,或者你不需要对嵌套可变对象进行独立修改,就可以用浅拷贝。比如你只是想复制一个简单的列表,里面都是不可变类型(像整数、字符串),浅拷贝就够,又快又省资源。
深拷贝:当你需要完全独立的副本,尤其是对象有嵌套可变对象,并且你要修改副本里的嵌套对象,又不想影响原对象的时候,深拷贝就派上用场了。
一句话记住:
- 浅拷贝:“表面复制”,嵌套的可变对象还是 “一家人”。
- 深拷贝:“连根复制”,嵌套的可变对象也变成 “两家人”,彻底独立。
-
import copy
lst = [1, [2, 3]]
shallow = lst.copy()
deep = copy.deepcopy(lst)
lst[1].append(4) # 修改子列表
print(shallow) # 输出 [1, [2, 3, 4]](浅拷贝受影响)
print(deep) # 输出 [1, [2, 3]](深拷贝不受影响) - 列表是可变对象:作为函数参数时,修改列表会影响外部原列表(传引用),因为传入时共用一个地址,这和浅拷贝与深拷贝不同,请读者区分开。
二、字典(Dictionary)
1. 定义与表示
- 字典是 Python 中键值对映射的可变数据类型,用于存储关联型数据。
- 表示方式:用 {} 包裹,元素为 键: 值 对,键与值之间用冒号分隔,键值对之间用逗号分隔。
dict1 = {"name": "张三", "age": 18, "hobby": ["篮球", "游戏"]} # 普通字典
empty_dict = {} # 空字典
dict_from_list = dict([("a", 1), ("b", 2)]) # 用dict()函数从列表生成
2. 核心特性
- 键值对映射:通过唯一的 “键” 访问对应的 “值”,键是访问的唯一标识。
- 键的约束:键必须是不可变类型(字符串、数字、元组等),且同一字典中键不可重复(重复会被覆盖)。
- 值的灵活性:值可以是任意数据类型(包括列表、字典、函数等),无限制。
- 可变性:支持动态添加、修改、删除键值对(内存地址不变,内容可变)。
- 有序性:Python 3.7+ 后字典是有序的(按插入顺序保存),之前版本无序。
3. 基本操作
(1)访问值
- 通过键直接访问:dict[key](键不存在则报错)。
info = {"city": "北京", "area": 16410}
print(info["city"]) # 输出 "北京" - 通过 get() 方法访问:dict.get(key, default)(键不存在则返回默认值,避免报错)。
print(info.get("population", "未知")) # 输出 "未知"(键"population"不存在)
(2)修改 / 新增键值对
- 直接赋值:键存在则修改值,键不存在则新增键值对。
info["area"] = 16411 # 修改已有键的值
info["population"] = 2184 # 新增键值对
print(info) # 输出 {"city": "北京", "area": 16411, "population": 2184}
(3)删除键值对
- del dict[key]:删除指定键值对(键不存在则报错)。
- dict.pop(key, default):删除并返回指定键的值(键不存在则返回默认值)。
- dict.clear():清空字典所有键值对(保留空字典)。
del info["area"] # 删除"area"键值对
print(info.pop("city", "无")) # 输出 "北京"(删除并返回值)
info.clear() # 清空字典,结果:{}
(4)其他基础操作
- 拼接 / 合并:用 dict.update(other_dict) 合并另一个字典(覆盖重复键,后来者居上)。
a = {"x": 1, "y": 2}
b = {"y": 3, "z": 4}
a.update(b) # a变为 {"x": 1, "y": 3, "z": 4}("y"被覆盖) - 成员判断:用 in / not in 判断键是否存在(仅判断键,不判断值)。
print("x" in a) # 输出 True(判断键"x"是否存在)
- 长度:len(dict) 返回键值对的数量。
print(len(a)) # 输出 3
4. 常用方法(重点)
dict.keys() | 返回所有键组成的可迭代对象(可转成列表) | info = {"name": "张三", "age": 18} info.keys() list(info.keys()) |
dict_keys(['name', 'age']) ['name', 'age'] |
dict.values() | 返回所有值组成的可迭代对象(可转成列表) | info = {"name": "张三", "age": 18} info.values() list(info.values()) |
dict_values(['张三', 18]) ['张三', 18] |
dict.items() | 返回所有键值对组成的可迭代对象(每个元素为 (键, 值) 元组) | info = {"name": "张三", "age": 18} info.items() list(info.items()) |
dict_items([('name', '张三'), ('age', 18)]) [('name', '张三'), ('age', 18)] |
dict.copy() | 复制字典(浅拷贝,生成新字典) | info = {"name": "张三", "age": 18} info_copy = info.copy() info_copy |
{'name': '张三', 'age': 18} |
dict.setdefault(key, default) | 若键不存在则新增(值为 default),存在则返回对应值(不修改原字典) | info = {"name": "张三"} info.setdefault("age", 18) info info.setdefault("name", "李四") info |
18 {'name': '张三', 'age': 18} 张三 {'name': '张三', 'age': 18} |
5. 字典推导式(高效生成字典)
- 语法:{键表达式: 值表达式 for 变量 in 可迭代对象 if 条件}
- 作用:用一行代码生成字典,比循环更简洁。
# 生成1-5的平方字典
squares = {x: x**2 for x in range(1, 6)}
print(squares) # 输出 {1:1, 2:4, 3:9, 4:16, 5:25}# 筛选值为偶数的键值对
even_squares = {k: v for k, v in squares.items() if v % 2 == 0}
print(even_squares) # 输出 {2:4, 4:16}
6. 注意事项
- 浅拷贝特性:dict.copy() 或 dict 函数复制的是浅拷贝,若字典中嵌套可变对象(如列表),修改嵌套对象会影响原字典和拷贝字典。
- 作为函数参数:字典是可变对象,作为参数传入函数时,修改字典会影响外部原字典(同列表的传引用特性)。
三、元组(Tuple)
1. 定义与表示
- 元组是 Python 中不可变的有序序列,用于存储不可修改的一组数据。
- 表示方式:用 () 包裹元素,元素之间用逗号分隔。例如:
tuple1 = (10, "苹果", 3.14) # 普通元组
single_tuple = (5,) # 单元素元组(必须加逗号,否则视为普通括号)
empty_tuple = () # 空元组
tuple_from_list = tuple([1, 2, 3]) # 用tuple()函数从列表生成
2. 核心特性
- 不可变性:元组创建后,元素的数量、顺序、值不可修改(不能新增、删除、替换元素)。
- 例外:若元素是可变对象(如列表),可修改可变对象的内部内容(但元组本身的结构不变)。
- 有序性:元素有固定顺序,可通过索引访问(同列表)。
- 可重复性:允许包含重复元素。
- 元素灵活性:可存储任意数据类型(包括列表、字典、元组等)。
3. 基本操作
(1)访问元素(索引与切片)
- 索引:tuple[index](正向索引从 0 开始,反向索引从 – 1 开始)。
t = ("a", "b", "c", "d")
print(t[1]) # 输出 "b"(正向索引)
print(t[-2]) # 输出 "c"(反向索引) - 切片:tuple[start:end:step](左闭右开,返回新元组)。
print(t[1:3]) # 输出 ("b", "c")
print(t[::-1]) # 输出 ("d", "c", "b", "a")(反转)
(2)拼接与重复
- 拼接:tuple1 + tuple2(生成新元组,原元组不变)。
t1 = (1, 2)
t2 = (3, 4)
print(t1 + t2) # 输出 (1, 2, 3, 4) - 重复:tuple * n(生成新元组,元素重复 n 次)。
print(t1 * 3) # 输出 (1, 2, 1, 2, 1, 2)
(3)成员判断
- 用 in / not in 判断元素是否在元组中。
print("b" in t) # 输出 True
(4)长度、最大 / 最小值
- len(tuple):返回元素个数。
- max(tuple) / min(tuple):返回最大 / 最小元素(元素需可比较)。
nums = (3, 1, 4)
print(len(nums)) # 输出 3
print(max(nums)) # 输出 4
4. 常用方法
tuple.count(value) | 统计元素 value 在元组中出现的次数 | (1, 2, 2, 3).count(2) | 2 |
tuple.index(value) | 返回元素 value 在元组中第一次出现的索引(元素不存在则报错) | ("a", "b", "a").index("a") | 0 |
5. 注意事项
- 不可变性的细节:元组本身不可修改,但如果元素是可变对象(如列表),可修改该元素的内部内容。
t = (1, [2, 3])
t[1].append(4) # 修改元组中的列表元素(允许)
print(t) # 输出 (1, [2, 3, 4]) - 与列表的区别:元组不可变,适合存储固定数据(如配置项、坐标);列表可变,适合存储动态数据。
- 作为字典的键:元组是不可变类型,可作为字典的键;列表不可作为字典的键。
四、集合(Set)
1. 定义与表示
- 集合是 Python 中无序、唯一的可变数据集合,用于存储不重复的元素。
- 表示方式:用 {} 包裹元素(元素之间用逗号分隔),或用 set() 函数生成。例如:
set1 = {1, 2, 3, 4} # 普通集合(自动去重)
empty_set = set() # 空集合(不能用{},{}表示空字典)
set_from_list = set([1, 2, 2, 3]) # 从列表生成集合(自动去重)→ {1, 2, 3}
2. 核心特性
- 唯一性:集合中元素不可重复,自动去重(添加重复元素会被忽略)。
- 无序性:元素没有固定顺序,不能通过索引访问(与列表、元组的核心区别)。
- 元素约束:元素必须是不可变类型(字符串、数字、元组等),不能包含列表、字典等可变类型。
- 可变性:支持动态添加、删除元素(内存地址不变,内容可变)。
3. 基本操作
(1)添加元素
- set.add(value):添加单个元素(元素已存在则忽略)。
- set.update(iterable):添加可迭代对象(如列表、元组)中的所有元素(自动去重)。
s = {1, 2, 3}
s.add(4) # 结果:{1, 2, 3, 4}
s.update([3, 4, 5]) # 添加列表元素,去重后:{1, 2, 3, 4, 5}
(2)删除元素
- set.remove(value):删除指定元素(元素不存在则报错)。
- set.discard(value):删除指定元素(元素不存在则忽略,不报错)。
- set.pop():随机删除并返回一个元素(空集合调用会报错)。
- set.clear():清空集合所有元素(保留空集合)。
s.remove(5) # 结果:{1, 2, 3, 4}
s.discard(6) # 无变化(6不存在)
print(s.pop()) # 随机返回一个元素(如1),集合变为 {2, 3, 4}
(3)集合运算(核心功能)
- 交集:set1 & set2 或 set1.intersection(set2) → 两个集合的共同元素。
- 并集:set1 | set2 或 set1.union(set2) → 两个集合的所有元素(去重)。
- 差集:set1 – set2 或 set1.difference(set2) → set1 有而 set2 没有的元素。
- 对称差集:set1 ^ set2 或 set1.symmetric_difference(set2) → 两个集合中互不相同的元素。
a = {1, 2, 3}
b = {2, 3, 4}
print(a & b) # 交集 → {2, 3}
print(a | b) # 并集 → {1, 2, 3, 4}
print(a – b) # 差集 → {1}
print(a ^ b) # 对称差集 → {1, 4}
(4)其他基础操作
- 成员判断:in / not in 判断元素是否在集合中(效率远高于列表)。
print(2 in a) # 输出 True
- 长度:len(set) 返回元素个数。
print(len(a)) # 输出 3
4. 常用方法
add() | 用于向集合中添加元素。如果元素已存在,则不会重复添加。 | thisset = {'a', 'b', 'c'} thisset.add('d') print(thisset) |
{'a', 'b', 'c', 'd'} |
remove() | 用于移除集合中的指定元素。如果元素不存在,会引发 KeyError 异常。 | thisset = {'a', 'b', 'c'} thisset.remove('b') print(thisset) |
{'a', 'c'} |
discard() | 也用于移除集合中的指定元素,但如果元素不存在,不会引发异常。 | thisset = {'a', 'b', 'c'} thisset.discard('d') print(thisset) |
{'a', 'b', 'c'} |
clear() | 用于清空集合中的所有元素,将集合变为空集。 | thisset = {'a', 'b', 'c'} thisset.clear() print(thisset) |
set() |
pop() | 用于随机移除并返回集合中的一个元素。如果集合为空,会引发 KeyError 异常。 | thisset = {'a', 'b', 'c'} removed_element = thisset.pop() print(removed_element) |
'a'(每次结果可能不同)… |
注:列表和集合里都有 pop 方法,但行为不一样。列表的 pop 方法默认删除并返回最后一个元素。集合的 pop 是随机删除并返回一个元素。字典里没有 pop 方法,不过有个 popitem 方法,它是随机删除并返回一个键值对。
5. 集合推导式(高效生成集合)
- 语法:{表达式 for 变量 in 可迭代对象 if 条件}
- 作用:快速生成集合(自动去重)。
# 生成1-10的偶数集合
evens = {x for x in range(1, 11) if x % 2 == 0}
print(evens) # 输出 {2, 4, 6, 8, 10}# 从字符串提取不重复字符
chars = {c for c in "hello world" if c != " "}
print(chars) # 输出 {'h', 'e', 'l', 'o', 'w', 'r', 'd'}(去重)
6. 注意事项
- 无序性导致的不可索引:集合没有固定顺序,不能通过索引(如 s[0])访问元素,只能通过 in 判断是否存在,或遍历元素。
- 元素必须可哈希:集合的元素必须是不可变类型(可哈希),如整数、字符串、元组等。列表、字典、集合等可变类型不能作为集合元素(会报错)。
s = {1, "a", (2, 3)} # 合法(元素都是不可变类型)
s = {[1, 2]} # 报错(列表是可变类型,不可哈希) - 集合的 pop() 方法随机删除:set.pop() 没有参数,删除的元素是随机的(因集合无序),不能指定删除某个元素(需用 remove 或 discard)。
- 与字典的表示冲突:空集合必须用 set() 表示,{} 表示的是空字典,而非空集合。
- 高效的成员判断:集合的 in 操作时间复杂度为 O(1)(远快于列表的 O(n)),适合需要频繁判断 “元素是否存在” 的场景(如去重、数据筛选)。
- 浅拷贝特性:用 set.copy() 或 copy.copy() 复制集合时,若集合中包含嵌套的可变对象(如元组内的列表,因元组为不可变对象),浅拷贝会共享这些嵌套对象(但集合本身的元素必须是不可变的,所以这种情况较少见)。
总结
列表 | 有序 | 可重复 | 可变 | [ ] | [1, 2, 3] |
元组 | 有序 | 可重复 | 不可变 | ( ) | (1, 2, 3) |
集合 | 无序 | 不可重复 | 可变 | { } | {1, 2, 3} |
字典 | 无序 | 键不可重复,值可重复 | 键不可变,值可变 | { } | {"name": "Tom", "age": 18} |
评论前必须登录!
注册