惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
IT之家
IT之家
T
The Blog of Author Tim Ferriss
V
V2EX
博客园 - 聂微东
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
U
Unit 42
Vercel News
Vercel News
L
LangChain Blog
博客园 - 司徒正美
H
Help Net Security
Recent Announcements
Recent Announcements
Recorded Future
Recorded Future
V
Visual Studio Blog
Jina AI
Jina AI
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
Y
Y Combinator Blog
C
Check Point Blog
博客园 - 三生石上(FineUI控件)
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
The Register - Security
The Register - Security
The GitHub Blog
The GitHub Blog
B
Blog RSS Feed
F
Fortinet All Blogs
B
Blog
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
云风的 BLOG
云风的 BLOG
爱范儿
爱范儿
MongoDB | Blog
MongoDB | Blog
F
Full Disclosure
有赞技术团队
有赞技术团队
罗磊的独立博客
博客园_首页
MyScale Blog
MyScale Blog
aimingoo的专栏
aimingoo的专栏
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
N
Netflix TechBlog - Medium
Engineering at Meta
Engineering at Meta
量子位
I
InfoQ
小众软件
小众软件
P
Proofpoint News Feed

Liu Zijian's Blog | 一个技术博客

使用Certbot自动续签HTTPS证书 使用Filebeat采集Nginx日志到ES Python的协程 Python中的异常 Python中的类和对象 Python的函数 Spring AI集成多模态模型 LangChain4j多模态 LangChain Tools工具使用 Python中的模块和包 Python全局环境和虚拟环境(venv) LangChain Prompt提示词工程 LangChain4j Tools工具使用 基于Dify搭建AI智能体应用 LangChain4j RAG检索增强生成 Spring AI实现MCP Server Spring AI集成MCP Client LangChain4j Prompt提示词工程 Spring AI使用知识库增强对话功能 Spring AI实现一个智能客服 Spring AI实现一个简单的对话机器人 实现MinIO数据的每日备份 自己实现一个DNS服务 简单理解AI智能体 大模型和大模型应用 LangChain开篇 LangChain4j开篇 一个解析Excel2007的POI工具类 DataPermissionInterceptor源码解读 TenantLineInnerInterceptor源码解读 BaseMultiTableInnerInterceptor源码解读 Spring AI开篇 SQL解析工具JSQLParser 芋道源码解读之多租户 芋道源码解读之数据权限 芋道源码解读开篇 Java实现将数据导出为Word文档 OA系统的天数该怎样计算 安装MySQL8 安装MySQL5.7 RockyLinux9环境下编译MySQL8 MySQL字符集及底层原理 Java实现LDAP登录 Docker Compose IPv4和IPv6 使用虚拟机安装一个K8s集群 使用GraalVM原生编译打包SpringBoot工程 Nginx防止目录穿越 Java线程的状态 Nginx防盗链设置 使用python将excel表格转换为SQL INSERT Redis的公共操作命令 Redis数据结构之Bitfleid Redis数据结构之Bitmap Redis数据结构之GEO Redis数据结构之Hash Redis数据结构之HyperLogLog Redis数据结构之List Redis数据结构之Set Redis数据结构之Stream Redis数据结构之String Redis数据结构之ZSet 使用python压缩图片 利用Python实现Hexo站点的持续集成 Nginx设置HTTPS监听 firewalld防火墙工具的使用 Linux信号(signal)机制 MySQL5.7x 主从复制 用IP自签发一个HTTPS证书 基于Hexo实现一个静态的个人博客 RockyLinux9环境下编译MySQL5.7 Docker离线安装 MySQL数据定义语言 Docker与联合文件系统 Docker的网络 Docker的镜像操作 MySQL存储过程 MyBatis-Plus开篇 MySQL变量 MySQL视图 MySQL事务 MySQL插入修改和删除 MySQL查询 MySQL系统命令 Docker的容器操作 Docker的安装和配置 Docker容器数据卷 浅谈OAuth2.0授权原理 JVM开篇 浅谈Linux(Unix)的I/O模型 一个通用的CloseableHttpClient工厂类 JUC可重入锁ReentrantLock JUC读写锁ReadWriteLock Java的单例 Java泛型 Java8的新特性 最近最少使用算法(LRU) MySQL函数 SpringBoot配置和启动 volatile作用分析
Python的数据结构,推导式、迭代器和生成器
Liu Zijian · 2026-01-01 · via Liu Zijian's Blog | 一个技术博客

未完待续

【新年开篇】让我们拿出跃马扬鞭的勇气,激发万马奔腾的活力,保持马不停蹄的干劲,一起为梦想奋斗、为幸福打拼,把宏伟愿景变成美好现实。

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

在需要高性能程序时,需要考虑使用生成器优化程序