1.概述
在Python中,有四种常见的数据结构
| 数据结构 | 是否可变 | 是否允许重复 | 是否有序 | 定义符号 |
|---|---|---|---|---|
| 列表(List) | 可变 | 允许 | 有序 | [] |
| 元组(Tuple) | 不可变 | 允许 | 有序 | () |
| 字典(Dict) | 可变 | 键不允许,值允许 | 有序 | {} |
| 集合(Set) | 可变 | 不允许 | 无序 | {} |
2.列表(List)
列表是一种有序的数据结构,元素写在[]中间,用,隔开通过下标访问。
列表创建有三种,直接创建,通过list()方法,以及推导式。
列表的特点:
- 可以被索引(从左到右和从右到左)和切片(substring)
- 可以使用
+操作符进行拼接 - 列表中的元素是可变的
- 元素可以是任意类型
- 元素允许重复
2.1 创建
#直接创建
list1 = [1,2,3,4,5]
list2 = ['abc', 2, 1.55]
python还有几种常见创建list方式:
list()方法创建一个空的集合
empty_list = list()
print(empty_list)
用list()方法从字符串创建数组
s = 'hello'
l = list(s)
print(l) #['h', 'e', 'l', 'l', 'o']
从set集合创建
s = {1,2,3,4}
l = list(s)
print(l) #[1, 2, 3, 4]
从tuple元组创建
t = (1,2,3,4)
l = list(t)
print(l) #[1, 2, 3, 4]
从dic字典创建,只取每个key作为元素
d = {'a':1, 'b':2, 'c':3}
l = list(d)
print(l) #['a', 'b', 'c']
从dic字典创建,取每个键值对作为元素
d = {'a':1, 'b':2, 'c':3}
l = list(d.items())
print(l) #[('a', 1), ('b', 2), ('c', 3)]
从dic字典创建,取每个value作为元素
d = {'a':1, 'b':2, 'c':3}
l = list(d.values())
print(l) #[1, 2, 3]
通过range()创建list
sample_list = list(range(10))
print(sample_list) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
带类型标识符
from typing import List, Union
# 只包含整数的列表
lst1: List[int] = [1, 2, 3, 4, 5]
# 包含其他类型
lst2: List[ Union[int, str, List[int] ] ] = [1, 2, 3, 4, '5']
2.2 列表常见方法
索引和切片
# 索引 => 1
print(list1[0])
# 第2到第4的元素,不含第4个 => [2, 3]
print(list1[1:3])
# 从第3个元素开始到末尾 => [3, 4, 5]
print(list1[2:])
# list1复制成两份拼接一起 => [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
print(list1 * 2)
# 拼接 => [1, 2, 3, 4, 5, 'abc', 2, 1.55]
print(list1 + list2)
Python列表可以倒序索引,从-1开始,且元素可变
list1[-1] = 100
print(list1[-1]) #100
列表可变,因此可以进行添加和删除元素等操作
删除第一个值为2的元素
l = [1,2,3,4,5,2]
l.remove(2)
print(l) #[1, 3, 4, 5, 2]
追加元素
l = [1,2,3,4,5]
l.append(4)
print(l) #[1, 2, 3, 4, 5, 4]
在某个元素前添加
l = [1,2,3,4,5]
l.insert(3, 'a')
print(l) #[1, 2, 3, 'a', 4, 5]
加号运算,两个列表拼接成为一个全新的列表对象
list1 = [1,2,3]
list2 = [3,4,5]
list3 = list1 + list2
print(list1)
print(list2)
print(list3)
print(id(list1))
print(id(list2))
print(id(list3))
[1, 2, 3]
[3, 4, 5]
[1, 2, 3, 3, 4, 5]
2575803669824
2575803939264
2575796778880
删除指定位置的元素并返回
l = [1,2,3,4,5,2]
sl = l.pop(2) # 删除指定位置的元素并返回
print(sl)
print(l)
3
[1, 2, 4, 5, 2]
长度,最大值,最小值,求和
list1 = [6, 2, 4, 7, 8]
print(f"获取列表长度: {len(list1)}")
print(f"列表的最大值: {max(list1)}")
print(f"列表的最小值: {min(list1)}")
print(f"列表的所有元素的和: {sum(list1)}")
获取列表长度: 5
列表的最大值: 8
列表的最小值: 2
列表的所有元素的和: 27
排序,反转
sort_list=[10,8,7,1,20]
sort_list.sort() # 列表排序
print(f"列表排序: {sort_list}")
sort_list.reverse() # 列表反转
print(f"列表反转: {sort_list}")
列表排序: [1, 7, 8, 10, 20]
列表反转: [20, 10, 8, 7, 1]
2.3 遍历列表
1.使用for循环遍历列表
lst=[6, 2, 3, 4, 7, 8]
for item in lst:
print(f"遍历列表元素: {item}")
遍历列表元素: 6
遍历列表元素: 2
遍历列表元素: 3
遍历列表元素: 4
遍历列表元素: 7
遍历列表元素: 8
2.下标遍历
lst=[6, 2, 3, 4, 7, 8]
for i in range(len(lst)):
print(f"使用下标遍历列表元素: {lst[i]}")
使用下标遍历列表元素: 6
使用下标遍历列表元素: 2
使用下标遍历列表元素: 3
使用下标遍历列表元素: 4
使用下标遍历列表元素: 7
使用下标遍历列表元素: 8
3.使用enumerate函数遍历列表,可以同时遍历下标和元素,还可以start=指定从哪个下标开始
lst=[6, 2, 3, 4, 7, 8]
for index, item in enumerate(lst):
print(f"使用enumerate函数遍历列表元素: {index} -> {item}")
for index, item in enumerate(lst, start=2):
print(f"使用enumerate函数遍历列表元素 start=2 : {index} -> {item}")
使用enumerate函数遍历列表元素: 0 -> 6
使用enumerate函数遍历列表元素: 1 -> 2
使用enumerate函数遍历列表元素: 2 -> 3
使用enumerate函数遍历列表元素: 3 -> 4
使用enumerate函数遍历列表元素: 4 -> 7
使用enumerate函数遍历列表元素: 5 -> 8
使用enumerate函数遍历列表元素 start=2 : 2 -> 6
使用enumerate函数遍历列表元素 start=2 : 3 -> 2
使用enumerate函数遍历列表元素 start=2 : 4 -> 3
使用enumerate函数遍历列表元素 start=2 : 5 -> 4
使用enumerate函数遍历列表元素 start=2 : 6 -> 7
使用enumerate函数遍历列表元素 start=2 : 7 -> 8
4.zip函数同时遍历多个列表
内置的zip函数和压缩没有一点关系,只用于维度合并,不能数据压缩
list_a = [1, 2, 3]
list_b = [4, 5, 6]
for item_a, item_b in zip(list_a, list_b):
print(f"使用zip函数遍历多个列表元素: {item_a}, {item_b}") #
使用zip函数遍历多个列表元素: 1, 4
使用zip函数遍历多个列表元素: 2, 5
使用zip函数遍历多个列表元素: 3, 6
3.元组(Tuple)
元组是一种和列表相似的数据结构,元素是任意类型,有序,允许重复,区别是:元组元素不可变
3.1 创建
几种简单创建方式
tup = tuple() #通过tuple()方法创建
tup = () #空元组
tup = (1, 2, 3) #创建元组
tup = (1,) # 元组内只有一个元素,结尾要加逗号
tup = 1, 2, 3 #一种不被推荐的创建方式
tup = (1, "hello", 3.14, True) #支持不同类型
tup = (1, 2, 2, 3, 3, 3) # 重复元素
从其他数据结构创建
# 使用tuple()函数接收列表创建元组
tup = tuple([1, 2, 3])
print("使用tuple()函数接收列表参数,创建元组:", tup)
# 使用tuple()函数接收字符串创建元组
tup = tuple("hello")
print("使用tuple()函数接收字符串作为参数,创建元组:", tup)
# 使用tuple()函数接收集合创建元组
tup = tuple({1, 2, 3})
print("使用tuple()函数接收集合作为参数,创建元组:", tup)
# 使用tuple()函数接收元组创建元组
from_tuple = (1, 2, 3)
tup = tuple(from_tuple)
print("使用tuple()函数接收元组作为参数,创建元组:", tup)
# 使用tuple()函数接收字典创建元组,字典的key值会作为元组的元素
tup = tuple({"a": 1, "b": 2})
print("使用tuple()函数接收字典作为参数,创建元组:", tup)
# 使用tuple()函数接收字典的values创建元组
from_dict = {"a": 1, "b": 2}
tup = tuple(from_dict.values())
print("使用tuple()函数接收字典的values作为参数,创建元组:", tup)
# 使用tuple()函数接收字典的items创建元组
tup = tuple(from_dict.items())
print("使用tuple()函数接收字典的items作为参数,创建元组:", tup)
使用tuple()函数接收列表参数,创建元组: (1, 2, 3)
使用tuple()函数接收字符串作为参数,创建元组: ('h', 'e', 'l', 'l', 'o')
使用tuple()函数接收集合作为参数,创建元组: (1, 2, 3)
使用tuple()函数接收元组作为参数,创建元组: (1, 2, 3)
使用tuple()函数接收字典作为参数,创建元组: ('a', 'b')
使用tuple()函数接收字典的values作为参数,创建元组: (1, 2)
使用tuple()函数接收字典的items作为参数,创建元组: (('a', 1), ('b', 2))
带类型标识符创建
from typing import Tuple
# 包含整数、字符串、布尔值的元组
tup: Tuple[int, str, bool, List[int] ] = (25, "z3", True)
3.2 常见方法
1.访问
tup = (1, 2, 3)
tup[0]
2.元组元素不可变,下面程序会出错
tup = (1, 2)
tup[1] = 5 ❌
元组中元素的idhash不可变,但是内容可变,例如元组
([1, 2], 3)中的list[1, 2]可以追加和编辑元素
3.索引和切片
tup = ('a', 'b', 'c')
print(f"元组访问有序性: {tup}")
print(f"元组支持索引: {tup[0]}")
print(f"元组支持索引: {tup[-2]}")
print(f"元组支持切片:{tup[1:3]}")
元组访问有序性: ('a', 'b', 'c')
元组支持索引: a
元组支持索引: b
元组支持切片:('b', 'c')
4.计算,长度,最大值,最小值,求和,排序
tup=(1,2,3,4,5)
# 元组相加
print(f"元组相加: {tup + (6, 7, 8)}")
# 元组相乘
print(f"元组相乘: {tup * 2}")
# 元组的成员运算
print(f"成员运算: {2 in tup}")
# 元组的长度
print(f"元组的长度: {len(tup)}")
# 最大值和最小值和求和
print(f"元组的最大值: {max(tup)}")
print(f"元组的最小值: {min(tup)}")
print(f"元组的求和: {sum(tup)}")
# 排序
tup = tuple(sorted((5,3, 1, 4, 2)))
print(f"元组的排序: {tup}")
元组相加: (1, 2, 3, 4, 5, 6, 7, 8)
元组相乘: (1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
成员运算: True
元组的长度: 5
元组的最大值: 5
元组的最小值: 1
元组的求和: 15
元组的排序: (1, 2, 3, 4, 5)
3.3 遍历元组
1.使用for循环遍历元组
tup = (1, 2, 3, 4, 5)
for item in tup:
print(f"遍历元组元素: {item}")
遍历元组元素: 1
遍历元组元素: 2
遍历元组元素: 3
遍历元组元素: 4
遍历元组元素: 5
2.使用下标遍历元组
tup = (1, 2, 3, 4, 5)
for i in range(len(tup)):
print(f"使用下标遍历元组元素: {tup[i]}")
使用下标遍历元组元素: 1
使用下标遍历元组元素: 2
使用下标遍历元组元素: 3
使用下标遍历元组元素: 4
使用下标遍历元组元素: 5
3.使用enumerate函数遍历元组
tup = (1, 2, 3, 4, 5)
for index, item in enumerate(tup):
print(f"使用enumerate函数遍历元组元素: 索引 {index}, 元素 {item}")
使用enumerate函数遍历元组元素: 索引 0, 元素 1
使用enumerate函数遍历元组元素: 索引 1, 元素 2
使用enumerate函数遍历元组元素: 索引 2, 元素 3
使用enumerate函数遍历元组元素: 索引 3, 元素 4
使用enumerate函数遍历元组元素: 索引 4, 元素 5
4.将元组转换为列表遍历
tup = (1, 2, 3, 4, 5)
traverse_list = list(tup)
for item in traverse_list:
print(f"将元组转换为列表遍历: {item}")
将元组转换为列表遍历: 1
将元组转换为列表遍历: 2
将元组转换为列表遍历: 3
将元组转换为列表遍历: 4
将元组转换为列表遍历: 5
5.使用生成器遍历元组
tup = (1, 2, 3, 4, 5)
for item in (x for x in tup):
print(f"使用生成器遍历元组元素: {item}")
使用生成器遍历元组元素: 1
使用生成器遍历元组元素: 2
使用生成器遍历元组元素: 3
使用生成器遍历元组元素: 4
使用生成器遍历元组元素: 5
4.集合(Set)
set是一种无序,可变的数据类型,可包含任意类型,元素唯一不可重复,重复的元素将被自动去重,类似Java中的HashSet
set支持交集,并集,差集等集合操作
set不支持索引和切片
4.1 创建
常见创建
# 使用花括号创建集合
s = {1, 2, 3}
# 使用set()函数创建空集合
s = set()
# 可以包含任意类型
s = {1, "hello", 3.14, True}
s = {1, 2, 2, 3, 3, 3} #集合不允许重复元素,3会被自动去重
从字符串创建
s = set("hello")
print("使用set()函数接收字符串作为参数,创建集合:", s)
使用set()函数接收字符串作为参数,创建集合: {'h', 'o', 'e', 'l'}
从其他数据结构创建
# 使用set()函数接收列表创建集合
from_list=[1, 2, 3]
s = set(from_list)
print("使用set()函数接收列表参数,创建集合:", s)
# 使用set()函数接收元组创建集合
from_tuple = (1, 2, 3)
s = set(from_tuple)
print("使用set()函数接收元组作为参数,创建集合:", s)
# 使用set()函数接收字典创建集合
from_dict = {"a": 1, "b": 2}
s = set(from_dict)
print("使用set()函数接收字典作为参数,创建集合:", s)
# 使用set()函数接收字典的values创建集合
s = set(from_dict.values())
print("使用set()函数接收字典的values作为参数,创建集合:", s)
# 使用set()函数接收字典的items创建集合
s = set(from_dict.items())
print("使用set()函数接收字典的items作为参数,创建集合:", s)
# 5) 使用set()函数接收集合创建集合
from_set = {1, 2, 3}
s = set(from_set)
print("使用set()函数接收集合作为参数,创建集合:", s)
使用set()函数接收列表参数,创建集合: {1, 2, 3}
使用set()函数接收元组作为参数,创建集合: {1, 2, 3}
使用set()函数接收字典作为参数,创建集合: {'b', 'a'}
使用set()函数接收字典的values作为参数,创建集合: {1, 2}
使用set()函数接收字典的items作为参数,创建集合: {('a', 1), ('b', 2)}
使用set()函数接收集合作为参数,创建集合: {1, 2, 3}
从range函数创建
from_range = range(5)
s = set(from_range)
print("使用set()函数接收range对象作为参数,创建集合:", s)
使用set()函数接收range对象作为参数,创建集合: {0, 1, 2, 3, 4}
从推导式和生成器创建
# 使用set()函数接收生成器创建集合
from_generator = (x for x in range(5))
s = set(from_generator)
print("使用set()函数接收生成器作为参数,创建集合:", s)
# 使用集合推导式创建集合
s = {x for x in range(5)}
print("使用集合推导式创建集合:", s)
使用set()函数接收生成器作为参数,创建集合: {0, 1, 2, 3, 4}
使用集合推导式创建集合: {0, 1, 2, 3, 4}
带类型标识符创建
from typing import Set, Union
# 只包含字符串的集合
s1: Set[ Union[str, int, List[int] ] ] = {"z3", "li4", "w5", 8}
# 只包含字符串的集合
s2: Set[ str ] = {"z3", "li4", "w5"}
4.2 常见方法
1.增删改,长度,最值,求和,排序
s = {1, 2, 3, 4, 5}
# 集合添加元素
s.add(6)
print(f"集合添加元素: {s}")
# 删除集合存在元素
s.remove(3)
print(f"集合删除元素: {s}")
# 集合的成员检测
print(f"集合的成员检测: {4 in s}")
print(f"集合的成员检测: {8 in s}")
# 集合的长度
print(f"集合的长度: {len(s)}")
# 集合的最大值和最小值和求和
print(f"集合的最大值: {max(s)}")
print(f"集合的最小值: {min(s)}")
print(f"集合的求和: {sum(s)}")
# 集合的排序
sorted_set = sorted(s)
print(f"集合的排序: {sorted_set}")
# 删除集合不存在元素
# s.remove(8) # ❌ 会抛出 KeyError 异常
集合添加元素: {1, 2, 3, 4, 5, 6}
集合删除元素: {1, 2, 4, 5, 6}
集合的成员检测: True
集合的成员检测: False
集合的长度: 5
集合的最大值: 6
集合的最小值: 1
集合的求和: 18
集合的排序: [1, 2, 4, 5, 6]
2.交集并集差集
# 集合的交集
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}
intersection_set = set_a.intersection(set_b)
print(f"集合的交集: {intersection_set}")
# 集合的并集
union_set = set_a.union(set_b)
print(f"集合的并集: {union_set}")
# 集合的差集
difference_set = set_a.difference(set_b)
print(f"集合的差集: {difference_set}")
集合的交集: {4, 5}
集合的并集: {1, 2, 3, 4, 5, 6, 7, 8}
集合的差集: {1, 2, 3}
3.比较
==左右集合元素相同<左是右的真子集<=左是右的子集
- 子集 对于两个集合 ( A ) 和 ( B ),如果 ( A ) 中的每一个元素都是 ( B ) 中的元素,那么称 ( A ) 是 ( B ) 的子集
- 真子集 如果 ( A ) 是 ( B ) 的子集,并且 ( A ≠ B )(即 ( A ) 至少比 ( B ) 少一个元素),那么称 ( A ) 是 ( B ) 的真子集
print( {1, 2, 3, 4, 5} == {1, 2, 3, 4, 5} ) # True 集合元素相同
print( {1, 2, 3, 4, 5} < {1, 2, 3, 4, 5} ) # False 不是真子集
print( {1, 2, 3, 4, 5} <= {1, 2, 3, 4, 5} ) # True 是子集
print( {1, 2, 3, 5} < {1, 2, 3, 4, 5} ) # True 是真子集
python集合的子集真子集比较,可用于权限标识比较
4.3 遍历
1.使用for循环遍历集合
set_a = {1, 2, 3, 4, 5}
for e in set_a:
print(f"遍历集合元素: {e}")
遍历集合元素: 1
遍历集合元素: 2
遍历集合元素: 3
遍历集合元素: 4
遍历集合元素: 5
2.enumerate遍历集合
for index, item in enumerate(set_a):
print(f"使用enumerate遍历集合元素: {index} -> {item}")
使用enumerate遍历集合元素: 0 -> 1
使用enumerate遍历集合元素: 1 -> 2
使用enumerate遍历集合元素: 2 -> 3
使用enumerate遍历集合元素: 3 -> 4
使用enumerate遍历集合元素: 4 -> 5
3.转换为list遍历
set不可直接像list那样
for i in range(len(lst))下标遍历,因为没有顺序
set_list = list(set_a)
for item in set_list:
print(f"使用列表遍历集合元素: {item}")
使用列表遍历集合元素: 1
使用列表遍历集合元素: 2
使用列表遍历集合元素: 3
使用列表遍历集合元素: 4
使用列表遍历集合元素: 5
4.zip函数遍历
set_a = {1, 2, 3}
set_b = {4, 5, 6}
for item_a, item_b in zip(set_a, set_b):
print(f"使用zip遍历多个集合元素: {item_a}, {item_b}")
使用zip遍历多个集合元素: 1, 4
使用zip遍历多个集合元素: 2, 5
使用zip遍历多个集合元素: 3, 6
5.字典(Dict)
字典(Dict)是一种由键值对组成的,有序的可变的数据类型
- Python3.7以后,字典是有序的,保持插入顺序。
- 字典由键值对组成,键必须是不可变类型(如字符串、数字、元组)不能是(列表、集合、字典等)可变类型,值可以是任意类型。值可以重复,键必须唯一,如果键重复,新的值会覆盖前面旧的值。
- 字典是可变的,可以添加、修改或删除键值对。
- 字典没有索引,不能用下标或切片访问。
5.1 创建
花括号{}创建字典
dic = {"a": 1, "b": 2, "c": 3}
print(dic) #有序的
print(dic.items()) # 键值对
print(dic.keys()) # 键
print(dic.values()) # 值
{'a': 1, 'b': 2, 'c': 3}
dict_items([('a', 1), ('b', 2), ('c', 3)])
dict_keys(['a', 'b', 'c'])
dict_values([1, 2, 3])
通过键访问
dic = {'a': 1, 'b': 2, 'c': 3}
print( dic['a'] ) #1
print( dic.get('a') ) #1
可变
dic = {'a': 1, 'b': 2, 'c': 3}
dic.update({'c': 5, 'd': 4})
print(dic) #{'a': 1, 'b': 2, 'c': 5, 'd': 4}
使用dict()函数接收键值对创建字典
dic = dict()
print("使用dict()函数创建空字典:", dic) # {}
dic = dict(name="name", age=20)
print( dic) #{'name': 'name', 'age': 20}
dic = dict([("name", "qq"), ("age", 25)])
print( dic) #{'name': 'qq', 'age': 25}
使用dict()函数从其他数据结构创建字典
# 使用dict()函数接收列表创建字典
from_list = [("a", 1), ("b", 2), ("c", 3)]
dic = dict(from_list)
print(dic) # {'a': 1, 'b': 2, 'c': 3}
# 使用dict()函数接收元组创建字典
from_tuple = (("a", 1), ("b", 2), ("c", 3))
dic = dict(from_tuple)
print(dic) # {'a': 1, 'b': 2, 'c': 3}
# 使用dict()函数接收集合创建字典
from_set = {("a", 1), ("b", 2), ("c", 3)}
dic = dict(from_set)
print(dic) # {'c': 3, 'a': 1, 'b': 2}
# 使用dict()函数接收字典创建字典
from_dict = {"a": 1, "b": 2, "c": 3}
dic = dict(from_dict)
print(dic) # {'a': 1, 'b': 2, 'c': 3}
使用zip()函数创建字典
keys = "abc"
values = [1, 2, 3]
print( dict(zip(keys, values)) ) # {'a': 1, 'b': 2, 'c': 3}
keys = ['a', 'b', 'c']
values = [1, 2, 3]
print( dict(zip(keys, values)) ) # {'a': 1, 'b': 2, 'c': 3}
keys = "abc"
from_range = range(3)
dic = dict(zip(keys, from_range))
print(dic) # {'a': 0, 'b': 1, 'c': 2}
5.2 常见方法
添加新的键值对
dic = {'a': 1, 'b': 2, 'c': 3}
dic['d'] = 4
print(dic) #{'a': 1, 'b': 2, 'c': 3, 'd': 4}
修改键对应的值
dic = {'a': 1, 'b': 2, 'c': 3}
dic['c'] = 40
print(dic) #{'a': 1, 'b': 2, 'c': 40}
删除某个键值对
dic = {'a': 1, 'b': 2, 'c': 3}
e = dic.pop('c')
print(e) #3
print(dic) #{'a': 1, 'b': 2}
删除的键找不到,返回指定的默认值
dic = {'a': 1, 'b': 2, 'c': 3}
e = dic.pop('d', 0)
print(e) #0
print(dic) # {'a': 1, 'b': 2, 'c': 3}
通过del删除
dic = {'a': 1, 'b': 2, 'c': 3}
del dic['c']
print(dic) #{'a': 1, 'b': 2}
pop()能返回删除的键值对的值,但是del不能
成员key存在检测
dic = {'a': 1, 'b': 2, 'c': 3}
print('a' in dic) #True
print('f' in dic) #False
字典长度
dic = {'a': 1, 'b': 2, 'c': 3}
print("获取字典长度:", len(dic)) # 3
最大最小,根据key首字符unicode码值,如相同再去比较下一位字符
dic = {"name": "z3", "age": 18, "gender": "男"}
print("字典中最大值查找:", max(dic)) # name
print("字典中最小值查找:", min(dic)) # age
排序
dic = {"pink": 14, "red": 2, "zoo": 73, 'blue': 4}
print('原字典', dic)
sorted_dict_key = sorted(dic)
print("字典的键排序:", sorted_dict_key)
sorted_dict_value = sorted(dic.items(), key=lambda item: item[1]) #从每个entry中取出第二个([1])即为value
print("字典的值排序:", sorted_dict_value)
原字典 {'pink': 14, 'red': 2, 'zoo': 73, 'blue': 4}
字典的键排序: ['blue', 'pink', 'red', 'zoo']
字典的值排序: [('red', 2), ('blue', 4), ('pink', 14), ('zoo', 73)]
默认值,get()和setdefault()都可实现取值时设置默认值
dic = {"a": 1, "b": 2, "c": 3}
print( dic.get("a", "没有找到") ) # 1
print( dic.get("f", "没有找到") ) # 没有找到
print( dic.setdefault("a", "没有找到") ) # 1
print( dic.setdefault("f", "没有找到") ) # 没有找到
合并,如果没有key相同,则update()能用于将字典合并
dict1 = {"name": "🐔哥", "age": 25, "gender": "男"}
dict2 = {"hobby": "打篮球", "clouth": '背带裤'}
dict2.update(dict1)
print( dict2 ) #{'hobby': '打篮球', 'clouth': '背带裤', 'name': '🐔哥', 'age': 25, 'gender': '男'}
5.3 遍历
遍历字典的键,值,键值对
dic = {"a": 1, "b": 2, "c": 3, 'd': 4}
for key in dic:
print(f"遍历字典的键: {key}")
for value in dic.values():
print(f"遍历字典的值: {value}")
for key, value in dic.items():
print(f"遍历字典的键值对: 键 {key}, 值 {value}")
for item in dic.items():
print(f"遍历字典的键值对:{item}")
遍历字典的键: a
遍历字典的键: b
遍历字典的键: c
遍历字典的键: d
遍历字典的值: 1
遍历字典的值: 2
遍历字典的值: 3
遍历字典的值: 4
遍历字典的键值对: 键 a, 值 1
遍历字典的键值对: 键 b, 值 2
遍历字典的键值对: 键 c, 值 3
遍历字典的键值对: 键 d, 值 4
遍历字典的键值对:('a', 1)
遍历字典的键值对:('b', 2)
遍历字典的键值对:('c', 3)
遍历字典的键值对:('d', 4)
enumerate()带顺序遍历
dic = {"a": 1, "b": 2, "c": 3, 'd': 4}
for index, item in enumerate(dic.items()):
print(f"使用enumerate函数遍历字典: 索引 {index}, 键值对:{item}")
for index, (key, value) in enumerate(dic.items()):
print(f"使用enumerate函数遍历字典: 索引 {index}, 键 {key}, 值 {value}")
使用enumerate函数遍历字典: 索引 0, 键值对:('a', 1)
使用enumerate函数遍历字典: 索引 1, 键值对:('b', 2)
使用enumerate函数遍历字典: 索引 2, 键值对:('c', 3)
使用enumerate函数遍历字典: 索引 3, 键值对:('d', 4)
使用enumerate函数遍历字典: 索引 0, 键 a, 值 1
使用enumerate函数遍历字典: 索引 1, 键 b, 值 2
使用enumerate函数遍历字典: 索引 2, 键 c, 值 3
使用enumerate函数遍历字典: 索引 3, 键 d, 值 4
转换为列表后,进行遍历
dic = {"a": 1, "b": 2, "c": 3, 'd': 4}
dict_list = list(dic.items()) # 转换为有序列表
for item in dict_list:
print(f"转换为列表后遍历字典: 键值对 {item}")
for key, value in dict_list:
print(f"转换为列表后遍历字典: , 键 {key}, 值 {value}")
转换为列表后遍历字典: 键值对 ('a', 1)
转换为列表后遍历字典: 键值对 ('b', 2)
转换为列表后遍历字典: 键值对 ('c', 3)
转换为列表后遍历字典: 键值对 ('d', 4)
转换为列表后遍历字典: , 键 a, 值 1
转换为列表后遍历字典: , 键 b, 值 2
转换为列表后遍历字典: , 键 c, 值 3
转换为列表后遍历字典: , 键 d, 值 4
使用生成器遍历字典,不允许在for前面直接解包key, value
dic = {"a": 1, "b": 2, "c": 3, 'd': 4}
dict_generator = (item for item in dic.items())
for item in dict_generator:
print(f"使用生成器遍历字典: 键值对:{item}")
使用生成器遍历字典: 键值对:('a', 1)
使用生成器遍历字典: 键值对:('b', 2)
使用生成器遍历字典: 键值对:('c', 3)
使用生成器遍历字典: 键值对:('d', 4)
dic = {"a": 1, "b": 2, "c": 3, 'd': 4}
dict_generator = (item for item in dic.items())
for k, v in dict_generator:
print(f"使用生成器遍历字典: 键值对:{k} = {v}")
使用生成器遍历字典: 键值对:a = 1
使用生成器遍历字典: 键值对:b = 2
使用生成器遍历字典: 键值对:c = 3
使用生成器遍历字典: 键值对:d = 4
使用zip()函数遍历多个字典
dict_a = {"name": "z3", "age": 18}
dict_b = {"city": "北京", "hobby": "打篮球"}
for item_a, item_b in zip(dict_a.items(), dict_b.items()):
print(f"使用zip函数遍历多个字典: 键值={item_a} | 键值={item_b}")
for (key_a, value_a), (key_b, value_b) in zip(dict_a.items(), dict_b.items()):
print(f"使用zip函数遍历多个字典: 键 {key_a}, 值 {value_a} | 键 {key_b}, 值 {value_b}")
for a, b in zip(dict_a, dict_b):
print(f"a={a},b={b}")
使用zip函数遍历多个字典: 键值=('name', 'z3') | 键值=('city', '北京')
使用zip函数遍历多个字典: 键值=('age', 18) | 键值=('hobby', '打篮球')
使用zip函数遍历多个字典: 键 name, 值 z3 | 键 city, 值 北京
使用zip函数遍历多个字典: 键 age, 值 18 | 键 hobby, 值 打篮球
a=name,b=city
a=age,b=hobby
6.推导式 (Comprehension)
推导式是一种独特的数据处理方式,将一个可迭代对象(列表,元组,集合,字符串)的元素,通过某种条件运算或筛选后,构建成一个新的数据序列的结构体。类似Java中的Stream API。
Python支持各种数据结构的推导式。
6.1 列表推导式
大致形式:
[列表生成元素表达式 for 变量 in 列表]
[列表生成元素表达式 for 变量 in 列表 if 条件]
例💡:从list:lst中提取所有元素,通通扩大十倍
lst = [1,2,3,4,5,6,7,8,9,0]
sub_list = [s*10 for s in lst ]
print(sub_list) #[10, 20, 30, 40, 50, 60, 70, 80, 90, 0]
例💡:带条件的推导式,从list:lst中提取所有偶数,生成新的list:sub_list
lst = [1,2,3,4,5,6,7,8,9,0]
sub_list = [s for s in lst if s % 2 == 0 ]
print(sub_list) #[2, 4, 6, 8, 0]
例💡:提取所有偶数,并将它们乘以10
lst = [1,2,3,4,5,6,7,8,9,0]
sub_list = [s*10 for s in lst if s % 2 == 0 ]
print(sub_list) #[20, 40, 60, 80, 0]
例💡:0-4的5个数中,筛选出比2大的,对每个进行加3
lst = [x+3 for x in range(5) if x > 2]
print(lst) #[6, 7]
例💡:包含多个循环的列表推导式
continue1 = [1, 2, 3]
continue2 = ["a", "b", "c"]
lst = [(i, j) for i in continue1 for j in continue2]
print(lst) #[(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]
6.2 元组推导式
⚠️ 严格来讲没有元组推导式,元组推导式得到的是生成器对象
大致形式:
(列表生成元素表达式 for 变量 in 列表)
(列表生成元素表达式 for 变量 in 列表 if 条件)
例💡:根据列表,通过推导式生成一个元组
⚠️ 元组比较特殊,生成的对象是一个generator object生成器而不是元组本身,还需要
tuple()函数转换为元组对象,且tuple()函数转换为元组对象前,不可对生成器对象进行迭代
lst = [1,2,3,4,5,6,7,8,9,0]
tup = (s*10 for s in lst if s % 2 == 0)
print( tup ) # <generator object <genexpr> at 0x000001CDE7A6BC60>
print( tuple(tup) ) # (20, 40, 60, 80, 0)
6.3 集合推导式
大致形式:
{列表生成元素表达式 for 变量 in 列表}
{列表生成元素表达式 for 变量 in 列表 if 条件}
例💡:提取偶数
lst = [1,2,3,4,5,6]
sub_list = {x for x in lst if x % 2 == 0}
print( sub_list) #{2, 4, 6}
6.4 字典推导式
大致形式:
{列表生成key元素表达式:列表生成value元素表达式 for 变量 in 列表}
{列表生成key元素表达式:列表生成value元素表达式 for 变量 in 列表 if 条件}
例💡:将列表中各字符串值为键,各字符串的长度为值,组成键值对
myList = ['Google','Oracle', 'Taobao','Baidu']
dic = {k:len(k) for k in myList}
print(dic) # {'Google': 6, 'Oracle': 6, 'Taobao': 6, 'Baidu': 5}
字典推导式遍历字典
dic = {"a": 1, "b": 2, "c": 3, 'd': 4}
dict_comprehension = {key: value for key, value in dic.items()}
for item in dict_comprehension.items():
print(f"使用字典推导式遍历字典: 键值对:{item}")
for key,value in dict_comprehension.items():
print(f"使用字典推导式遍历字典: 键 {key}, 值 {value}")
使用字典推导式遍历字典: 键值对:('a', 1)
使用字典推导式遍历字典: 键值对:('b', 2)
使用字典推导式遍历字典: 键值对:('c', 3)
使用字典推导式遍历字典: 键值对:('d', 4)
使用字典推导式遍历字典: 键 a, 值 1
使用字典推导式遍历字典: 键 b, 值 2
使用字典推导式遍历字典: 键 c, 值 3
使用字典推导式遍历字典: 键 d, 值 4
7.迭代器 (Iterator)
迭代器是访问集合元素的一种方式,是一个可以记住遍历位置的对象,从集合的第一个元素开始访问,直到所有元素被访问完结束,迭代器只会前进不能后退。
迭代器有两个基本方法iter()和next()。
字符串,列表或元组对象都可用于创建迭代器。
例💡:创建迭代器
iter(lst)就是创建了一个迭代器对象,通过next(it)不断获取下一个元素,如果获取到最后一个完成还要继续获取,则报错StopIteration(迭代器对象的一次性)
lst=[1,2,3,4]
it = iter(lst) # 创建迭代器对象
print (next(it)) # 1
print (next(it)) # 2
print (next(it)) # 3
print (next(it)) # 4
print (next(it)) #❌ StopIteration
例💡:迭代器对象可以使用常规for语句进行遍历
tup=(1,2,3,4)
it = iter(tup)
for e in it:
print (e, end=" ")
例💡:迭代器对象的一次性使用,无论怎么遍历,已经遍历的不能复用
lst = [1,2,3,4,5,6,7,8,9,0]
it = iter(lst)
print(next(it))
print(next(it))
for e in it:
print(f'for: ', e)
1
2
for: 3
for: 4
for: 5
for: 6
for: 7
for: 8
for: 9
for: 0
💡可迭代对象和迭代器的区别:
| 特性 | 可迭代对象 | 迭代器 |
|---|---|---|
| 定义 | 实现__iter__()方法的对象 |
实现__iter__()和__next__()方法的对象 |
| 功能 | 可以被迭代 | 可记住迭代状态并产生下一个值 |
| 内存使用 | 更多 | 惰性计算,节省 |
| 数据消耗 | 可多次迭代 | 只能迭代一次 |
| 例 | 列表,元组,字典,字符串 | 文件对象,生成器 |
8.生成器 (Generator)
简单理解:生成器就是一个迭代器
1.生成器是一个返回迭代器的函数,使用yield关键字,只能用于迭代操作,可以利用它进行惰性计算,调用一个生成器函数,就会返回一个迭代器对象。
2.当生成器中使用yield关键字时,函数的执行将会暂停,并将yield后面的表达式当作当前迭代的值返回。
3.每次调用生成器的next方法或使用for循环进行迭代时,函数会从上次暂停的地方继续执行,再到再次遇到yield关键字,这样,生成器函数可以逐步产生值,不需要一次性计算并返回所有结果。
特点:
- 惰性计算 只在需要时生成值
- 内存高效 不一次性的存储所有数据
- 一次性使用 遍历完成后就不能再次使用
例💡:
def countdown(n):
while n > 0:
#当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。
yield n
n = n - 1
# 创建生成器对象
generator = countdown(5)
print(type(generator)) # <class 'generator'> 生成器
# 通过迭代生成器获取值
print(next(generator)) # 输出: 5
print(next(generator)) # 输出: 4
print(next(generator)) # 输出: 3
# 使用 for 循环迭代生成器
for value in generator:
print(value) # 输出: 2 1
print(next(generator)) #❌ StopIteration
⚠️ 元组推导式只能得到生成器tup而不是元组tup,生成器误传进iter()进行迭代,返回的还是生成器tup本身
lst = [1,2,3,4,5,6,7,8,9,0]
tup = (s*10 for s in lst if s % 2 == 0)
it1 = iter(tup)
it2 = iter(tup)
print(id(tup))
print(id(it1))
print(id(it2))
1970972283424
1970972283424
1970972283424
生成器迭代后,不能再用tuple()生成元组
lst = [1,2,3,4,5,6,7,8,9,0]
tup = (s*10 for s in lst if s % 2 == 0)
print('迭代前', tuple(tup)) # 迭代前 (20, 40, 60, 80, 0)
for i in tup:
print( f'for- ',i )
print('迭代后', tuple(tup)) # 迭代后 ()
💡生成器与推导式的区别:
| 特性 | 推导式 | 生成器 |
|---|---|---|
| 内存使用 | 立即计算,存储所有元素在内存 | 惰性运算,不占用内存存储元素 |
| 返回类型 | 返回集合,列表等具体类型,元组除外 | 生成器对象 |
| 执行时机 | 立即执行,返回所有结果 | 按需,next()时 |
| 重用性 | 可多次使用 | 一次性,遍历后要重新构建 |
| 语法 | [] {}等明确符号和 in for if组成表达式 |
带yield函数 |
| 场景 | 数据量不大,需要立即得到结果 | 大量数据,内存敏感,只需遍历一次 |
内存占用对比:
生成器对象比推导式得到的具体数据结构对象节省内存的多
import sys
COUNT = 10000
large_list = [x for x in range(100 * COUNT)]
print("列表内存占用:", sys.getsizeof(large_list), "bytes") # 8448728 bytes
large_tup = (x for x in range(100 * COUNT))
print("生成器内存占用:", sys.getsizeof(large_tup), "bytes") # 192 bytes
执行时机对比:
推导式,整个计算,得到新的列表对象,立即执行,容易瞬间打满CPU/内存
def expensive_operation(x):
print(f"计算 {x} 的平方...")
return x * x
squares_list = [expensive_operation(x) for x in range(10)]
print(squares_list)
计算 0 的平方...
计算 1 的平方...
计算 2 的平方...
计算 3 的平方...
计算 4 的平方...
计算 5 的平方...
计算 6 的平方...
计算 7 的平方...
计算 8 的平方...
计算 9 的平方...
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
生成器对象,数据结构并没有实际生成每个成员,只有迭代时用到才产生,惰性执行
squares_gen = (expensive_operation(x) for x in range(10))
print('生成器对象初始化完成')
print(next(squares_gen))
print(next(squares_gen))
print(next(squares_gen))
for result in squares_gen:
print("for -----> ", result)
生成器对象初始化完成
计算 0 的平方...
0
计算 1 的平方...
1
计算 2 的平方...
4
计算 3 的平方...
for -----> 9
计算 4 的平方...
for -----> 16
计算 5 的平方...
for -----> 25
计算 6 的平方...
for -----> 36
计算 7 的平方...
for -----> 49
计算 8 的平方...
for -----> 64
计算 9 的平方...
for -----> 81
在需要高性能程序时,需要考虑使用生成器优化程序