前言
茫茫人海选中了我,一看就是个有品的人
一键三连哦老爷们
本篇开始于2025年初,我的大三
语言概述与特点
Python的历史与发展
- 1989年,荷兰程序员吉多·范罗苏姆为解决当时编程语言复杂、可读性差的问题,开始设计Python,1991年正式发布。
- 名字源自喜剧《蒙提·派森的飞行马戏团》,强调“优雅、明确、简单”,语法接近自然语言,强制缩进提升可读性。
- 2008年发布Python 3.0,是不兼容旧版本的重大升级,逐步取代Python 2(2020年停止维护)。
- 凭借开发效率高、生态丰富(如数据分析库Pandas、AI框架TensorFlow),在大数据、人工智能、Web开发等领域爆发式增长,成为最流行的编程语言之一,也是初学者常用的入门语言。
动态语言特性与解释型语言的优劣
动态语言(如Python、JavaScript)和解释型语言(如Python、Ruby)是两个相关但不同的概念:动态语言强调类型检查在运行时进行,变量类型可动态变更;解释型语言强调无需预先编译为机器码,由解释器逐行执行。两者常重叠(如Python既是动态语言也是解释型语言),其优劣势可分别总结如下:
-
动态语言特性的核心特点: 变量无强制类型声明,类型检查在运行时进行,支持动态修改对象结构(如添加属性/方法)。
-
动态语言特性的优势:
- 开发效率高:无需写类型声明,代码更简洁,适合快速迭代和原型开发(如Python一行代码实现复杂功能)。
- 灵活性强:可动态调整变量类型和对象结构,适配多变的业务需求(如JavaScript中对象可随时添加属性)。
- 学习门槛低:语法更接近自然语言,初学者易上手。
-
动态语言特性的劣势:
- 运行时错误风险高:类型错误(如字符串与数字相加)只能在运行时发现,可能导致线上故障。
- 性能损耗:运行时类型检查增加额外计算开销,执行效率通常低于静态类型语言(如Java、C#)。
- 重构难度大:大型项目中,类型不明确可能导致修改一处代码引发连锁错误,维护成本高。
-
解释型语言的核心特点: 源代码直接由解释器逐行解析执行,无需编译为机器码(或仅进行部分即时编译)。
-
解释型语言的优势:
- 跨平台性好:依赖解释器而非底层机器码,一次编写可在多平台运行(如Python代码在Windows/Linux上无需修改)。
- 开发周期短:修改代码后无需重新编译,可立即运行,适合快速测试和调试。
- 部署简单:直接部署源代码,无需处理编译后的二进制文件,降低环境配置复杂度。
-
解释型语言的劣势:
- 执行速度较慢:逐行解释比编译型语言(如C、Go)的预编译机器码执行效率低(尤其计算密集型任务)。
- 依赖解释器:运行环境必须安装对应解释器,增加部署依赖。
- 代码保密性差:源代码直接暴露,不如编译型语言的二进制文件难以逆向。
-
总结:
动态语言和解释型语言的优势集中在开发效率、灵活性和跨平台性,适合快速开发、脚本任务、Web应用等场景;劣势则体现在运行效率、错误检查和大型项目维护,因此在高性能、高可靠性要求的场景(如操作系统、实时系统)中,静态编译型语言(如C、Rust)仍占主导。
跨平台能力与丰富的标准库
-
跨平台:Python代码能在Windows、Linux、macOS等系统上直接运行,解释器会处理不同系统的差异,实现"一次编写,到处运行"。
-
标准库丰富:自带大量模块,涵盖文件操作、网络通信、数据处理等功能,无需额外安装就能完成多数任务,即"电池已包含"理念。
应用领域(Web开发、数据分析、人工智能等)
-
数据分析与科学计算:借助Pandas、NumPy等库处理数据,Matplotlib、Seaborn可视化数据,是科研和商业分析的常用工具。
-
人工智能与机器学习:TensorFlow、PyTorch等主流框架基于Python,广泛用于图像识别、自然语言处理等AI任务。
-
Web开发:Django、Flask等框架简化网站搭建,豆瓣、Instagram等均采用Python开发。
-
自动化运维与脚本:用于编写批量处理脚本、自动化测试、服务器管理等,提高运维效率。
-
爬虫开发:通过Requests、Scrapy等库抓取网页数据,应用于信息聚合、数据分析等场景。
-
教育领域:语法简单易懂,是初学者入门编程的首选语言,也常用于高校计算机课程。
-
游戏开发:可用于游戏脚本编写(如《文明IV》)、游戏测试等环节。
-
嵌入式系统与物联网:在树莓派等平台上,用于控制硬件、开发物联网应用。
以上只是Python的一部分功能,请记住“Python无所不能”,剩下的功能请在后续的学习探索中慢慢发掘吧
开发环境搭建
Python解释器安装
安装Python解释器的步骤简单直观,以下是主流系统的安装方法:
Windows系统:
- 访问官网:https://www.python.org/downloads/,点击"Download Python X.X.X"(X为最新版本)
- 运行安装包,勾选"Add Python to PATH"(关键,自动配置环境变量)
- 点击"Install Now",等待完成即可
macOS系统:
- 方法1:官网下载对应版本的.pkg安装包,双击安装
- 方法2:通过Homebrew(包管理工具)安装,终端输入:
brew install python3
Linux系统:
- 多数Linux(如Ubuntu)预装Python,终端输入
python3
可查看版本 - 如需安装/更新,终端输入:
sudo apt install python3
(Debian/Ubuntu)或sudo yum install python3
(CentOS)
验证安装:
安装完成后,打开终端(Windows用命令提示符或PowerShell),输入python
(Windows)或python3
(macOS/Linux),出现Python版本信息即成功。
如需退出解释器,输入exit()
或按Ctrl+Z(Windows)/Ctrl+D(macOS/Linux)。
常用IDE推荐(PyCharm、VS Code)
第一个Python程序:Hello World
print('helloworld')
基础语法结构
变量命名规范与动态类型
- 变量命名规范:
- 变量名必须以字母或下划线开头,不能以数字开头。
- 只能包含字母、数字和下划线。
- 避免使用编程语言的关键字。
- 使用描述性名称:变量名应反映其用途。
- 动态类型 :
动态类型是指在程序运行时才确定变量类型的特性。与静态类型不同,动态类型允许变量在运行时改变类型。其核心特点有:
- 变量无需声明类型:直接赋值即可
- 类型可以动态改变:同一个变量可以存储不同类型的数据。
- 运行时类型检查:错误(如类型不匹配)通常在运行时被发现。
#动态类型示例
variable = 10 # 初始为整数类型
print(type(variable)) # 输出: <class 'int'>
variable = "hello" # 运行时改变为字符串类型
print(type(variable)) # 输出: <class 'str'>
#尝试操作可能引发运行时错误
try:
result = variable + 5 # 字符串和整数相加,会报错
except TypeError as e:
print(f"错误: {e}") # 输出: 错误: can only concatenate str (not "int") to str
基本数据类型(int, float, str, bool)
1.查询数据类型:type(数据名)
2.数据类型:
2.1数值类型
2.1.1整数类型:
引导符号 | 例 | 输出 | |
---|---|---|---|
十进制 | 无 | num=987 | 987 |
二进制 | 0b或0B | num=ob1010101 | 85 |
八进制 | 0o或0O | num=0o765 | 501 |
十六进制 | 0x或0X | num=0x87ABF | 555711 |
2.1.2浮点数类型:
浮点型运算:有一定概率运算后增加一些不确定的尾数,可以利用round函数保留所需要的位数。
print(0.1+0.2) #输出结果是0.30000000000000004
print(round(0.1+0.2,1)) #输出结果是0.3
print(round(0.52+0.1314,3)) #输出结果为0.651
print(round(0.52+0.1314,1)) #输出结果为0.7
print(round(0.7)) #输出结果为1
round函数在处理以5结尾的数字时采用的是银行家算法,即当一个数字恰好以5结尾时,会将其舍入到最接近的偶数。如,print(round(2.5)),其输出结果为2
2.1.3复数类型:
复数是由实数部分和虚数部分组成的数,通常表示为 a + bi 的形式
x=123+456j
print('实数部分为:',x.real)
print('虚数部分为:',x.image)
2.2字符串类型
2.2.1转义字符:
转义字符 | 作用 |
---|---|
\n | 换行 |
\t | 横向跳到下一个制表位 |
" | " |
’ | ’ |
\ | \ |
转义字符前加R或r | 将转义字符无效化 |
2.2.2字符串的索引与切片:
s='helloworld'
print(s[0],s[-10],s[4]) #输出结果为h h o
print(s[2:7],s[-8:-3]) #输出结果为llowo llowo
print(s[:5],s[5:]) #输出结果为hello world
2.2.3操作符:
操作符 | 作用 |
---|---|
x+y | 连接字符串x和字符串y |
xn或nx | 复制n次字符串x |
x in s | 判断字符串x是否为字符串s的子串(True or False) |
2.3布尔类型
布尔类型是用来表示真值或者假值的数据类型。在Python中用True和False表示,其中True表示整数1,False表示整数0。
3.数据类相间的转换
函数作用:
int(x) | 将x转换为整数类型 |
---|---|
float(x) | 将x转换为浮点数类型 |
str(x) | 将x转换为字符串类型 |
chr(x) | 将x转换为一个字符 |
ord(x) | 将一个字符x转换为其对应的整数值 |
hex(x) | 将一个字符x转换为一个十六进制字符串 |
oct(x) | 将一个字符x转换为一个八进制字符串 |
bin(x) | 将一个字符x转换为一个二进制字符串 |
流程控制语句
条件语句(if-elif-else结构与三元表达式以及模式匹配)
- if-elif-else结构
num=eval(input('请输入密码:'))
if num==5201314:
print('密码正确,你好先生')
elif num==5211314:
print('密码正确,你好女士')
else:
print('密码错误')
- 三元表达式
在Python中,三元表达式可以被看作是if-else语句的简化版本。
num=eval(input('请输入密码:'))
print('密码正确,你好先生')if num==5201314 else(print('密码正确,你好女士')if num==5211314 else print('密码错误'))
从代码复杂度上来看三元表达式显然更简洁。然而,这并不意味着任何情况下都应该使用三元表达式。如果条件或者返回值的计算逻辑很复杂,那么使用if-else语句可能会更好,因为它的结构更清晰,更易于理解。
3. 模式匹配
score=input('请输入成绩等级:')
match score:
case 'A':
print('优秀')
case 'B':
print('及格')
case 'C':
print('不及格')
case _ :
pass
循环结构(for与while循环的使用场景)
- for循环
s=0
for i in range(1,11): #range函数:产生一个[n,m)的整数序列
s+=i
print('1到10的累加和为:',s)
- for…else…语句
for循环的变种,当for循环正常循环结束后,执行else语句。
numbers = [4, 6, 8, 9, 10]
target = 7
for num in numbers:
if num == target:
print(f"找到了目标数字 {target}")
break
else: # 循环正常结束(未被 break)时执行
print(f"列表中没有找到目标数字 {target}")
- while循环
s=0
i=1 #初始化变量
while i<=100: #条件判断
s+=i #语句块
i+=i #改变变量
print('1到100的累加值为:',s)
- while…else…语句
while循环的变种,当while循环正常循环结束后,执行else语句。
attempts = 0
while attempts < 3:
user_input = input("请输入一个数字(如 123):")
if user_input.isdigit(): #str.isdigit()所有字符都是数字
print(f"有效数字:{user_input}")
break
else:
print("输入无效,请重试。")
attempts += 1
else: # 循环正常结束(未 break)时执行
print("连续3次输入无效,程序退出。")
循环控制关键字(break, continue, pass)
- break: 直接结束程序运行。
- continue: 跳过本次循环的后续代码,并继续执行下一次循环操作。
- pass: 只起到占位符的作用,使语法结构完整、不报错。
- 示例:斐波那契数列实现
斐波那契数列是一个经典的数学序列,其中每个数字都是前两个数字的和,通常以 0 和 1 开始。
- 方法一:
def fibonacci_recursive(n):
if n <= 0:
return []
elif n == 1:
return [0]
elif n == 2:
return [0, 1]
else:
seq = fibonacci_recursive(n-1)
seq.append(seq[-1] + seq[-2])
return seq
# 示例:生成前10个斐波那契数
print(fibonacci_recursive(10)) # 输出: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
- 方法二:
def fibonacci_iterative(n):
if n <= 0:
return []
elif n == 1:
return [0]
seq = [0, 1]
while len(seq) < n:
seq.append(seq[-1] + seq[-2])
return seq
# 示例:生成前10个斐波那契数
print(fibonacci_iterative(10)) # 输出: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
- 方法有很多,可参考AI或其他文章进行思路开拓。
核心数据结构
列表(list)
- 定义: 列表是指一系列的按特定顺序排列的元素组成。列表是Python中内置的可变序列,列表中的元素可以是任意数据类型。
- 列表的创建方式:
- 直接创建:列表名=[元素1,元素2,…,元素n]
- 使用内置函数list()创建:列表名=list(序列)
- 列表的删除: del 列表名
- enumerate(枚举)函数与列表:
for index,item in enumerate(lst) #输出index和item
- 列表中的遍历操作
#for循环
for i in lst:
print(i)
#根据索引进行遍历
for i in range(0,len(lst)):
print(i,lst[i])
#用enumerate函数进行遍历
for index,item in enumerate(lst):
print(index,item)
- 列表的操作方法
操作符/函数 | 作用 |
---|---|
lst.append(x) | 在列表lst最后增加一个元素 |
lst.insert(inder,x) | 在列表中第index位置增加一个元素 |
lst.clear() | 清除列表lst中的所有元素 |
lst.pop(index) | 将列表lst中第index元素删除 |
lst.remove(x) | 将列表lst中出现的第一个元素删除 |
lst.reverse(x) | 将列表lst中的元素反转 |
lst.copy() | 拷贝列表中的所有元素生成一个新的列表 |
- 列表排序
#使用sort方法在原列表上进行更改
#lst.sort(key=None,reverse=False)
#key代表排序规则,reverse代表排序方式,False代表升序
lst=['banana','apple','Cat','Orange']
lst.sort()
print(lst) #输出:['Cat','Orange','apple','banana']
lst.sort(reverse=True)
print(lst) #输出:['banana','apple','Orange','Cat']
lst.sort(key=str.lower) #字符转为小写后比较
print(lst) #输出:['apple','banana','Cat','Orange']
#使用内置函数sorted()生成一个新列表
#sorted(iterable,key=None,revers=False)
#iterable表示排序的对象
new__lst=sorted(lst)
new__lst=sorted(lst,reverse=True)
new__lst=sorted(lst,key=str.lower)
#输出与sort方法的输出相同
- 列表生成式
#lst=[expression for item in range()]
#lst=[expression for item in range() if condition]
#expression是列表中数据的获取方法,item是元素个数,condition是判断条件
import random
lst=[item for item in range(1,11)]
print(lst) #输出:[1,2,3,4,5,6,7,8,9,10]
lst=[item*item for item in range(1,11)]
print(lst) #输出:[1,4,9,16,25,36,49,64,81,100]
lst=[random.randint(1,100) for _ in range(1,11)] #randint:生成随机整数
print(lst) #输出:[50,25,31,62,46,54,88,84,86,91]
lst=[i for i in range(10) if i%2==0]
print(lst) #输出:[0,2,4,6,8]
- 二维列表
#读取二维列表
for row in lst:
for item in row:
pass
#生成二维列表
lst=[[j for j in range(5)] for i in range(4)] #j代表几列,i代表几行
for j in lst: #这个二维列表有几行
for i in j: #这个二维列表每行有几列
print(i,end='\t')
print()
元组(tuple)的特性与使用场景
- 定义: 元组是Python中内置的不可变序列,用()定义元组,元素与元素间使用英文逗号进行分隔,只有一个元素时逗号也不能省略。
- 元组的创建方式
- 用()直接创建:元组名=(元素1,元素2,…,元素n)
- 使用内置函数tuple()创建:元组名=tuple(序列)
- 元组的删除: del 元组名
- 元组中的索引操作:
#查找
t=(1,2,3,4,5)
print(t[0]) #输出:1
#切片
t2=t[0:5:2] #从元组t的第0位开始取,取到第4位,中间间隔为2
print(t2) #输出(1,3,5)
5.元组的遍历:
#for循环
for item in t:
print(item)
#根据索引进行遍历
for i in range(len(t)):
print(i,t[i])
#使用enumerate函数枚举遍历
for index,item in enumerate(t):
print(index,item)
- 元组的生成式
元组名=(i for i in range(a,b))
元组名=tuple(序列)
元组名=(i for i in range(a,b) if 条件)
- 依次读取__next__
t=(1,2,3)
print(t.__next__()) #输出:1
print(t.__next__()) #输出:2
print(t.__next__()) #输出:3
print(t) #输出:()
- 元组与列表的区别
元组 | 列表 |
---|---|
不可变序列 | 可变序列 |
无法实现添加、删除、修改元素等操作 | 可用append()、pop()等方法实现添加、删除、修改元素等操作 |
支持切片访问元素,不支持修改操作 | 支持切片访问和修改列表中的元素 |
访问和处理速度快 | 访问和处理速度慢 |
可以作为字典的键 | 不能作为字典的键 |
字典(dict)的键值对管理与高效查找
- 定义: 字典类型是根据一个信息去查找另一个信息的方式构成了“键值对”,他表示了索引作用的键和对应的值构成的成对关系。
- 字典的创建方式
- 使用{}直接创建:d={key1:value1,key2:value2,…}
- 通过映射函数创建字典,使用内置函数dict()创建:
v=zip(lst1,lst2)
d=dict(v)
- 使用参数创造:d=dict(key1:value1,key2:value2,…)
- 字典的删除: del 字典名
- 字典元素的取值: d[key]或d.get(key)
- 字典元素的遍历:
#遍历出key与value的元组
for element in d.items():
pass
#分别遍历出key和value
for key,value in d.items():
pass
- 字典的操作方法:
操作方法 | 描述说明 |
---|---|
d.key | 获取所有的key数据 |
d.value | 获取所有的value数据 |
d.pop(key,default) | key存在时获取对应的value,同时删除这对值,否则获取默认值 |
d.popitem | 随机从字典中取出一个key-value对,结果为元组类型,同时将该key-value从字典中删除 |
d.clear | 清空字典中所有的key-value对 |
d[key]=value | 添加 |
- 字典生成式
d={key:value for item in range()}
d={key:value for key,value in zip(lst1,lst2)}
集合(set)的去重与集合运算
- 定义: Python中集合与数学中的集合概念一致,是一个无序的不重复元素序列,集合中只能存储不可变数据类型,在Python中用{}定义。与列表、字典一样,都是Python中的可变数据类型。
- 集合的创建方式:
- 使用{}直接创建:s={element1,element2,…,element N}
- 使用内置函数set()创建:s=set(可迭代对象)
- 集合的删除: del 集合名
- 集合的操作符:
操作符 | 作用 |
---|---|
A&B | 集合A与集合B的交集 |
A|B | 集合A与集合B的并集 |
A-B | 集合A与集合B的差集A-A&B |
A^B | 集合A与集合B的补集A+B-A&B |
- 集合的操作方法:
操作方法 | 作用 |
---|---|
s.add(x) | 如果x不在集合中,则将x添加到集合s |
s.remove(x) | 如果x在集合中,则将其删除,反之则报错 |
s.clear(x) | 清除集合中所有元素 |
- 集合的遍历:
#for循环
for item in s:
pass
#使用enumerate函数
for index,item in enumerate(s):
print(index,item)
- 集合的生成式:
s={i for i in range(a,b)}
s={i for i in range(a,b) if 条件}
列表、元组、字典、集合的区别
数据类型 | 序列类型 | 元素可否重复 | 是否有序 | 定义符号 |
---|---|---|---|---|
列表list | 可变序列 | 可重复 | 有序 | [] |
元组tuple | 不可变序列 | 可重复 | 有序 | () |
字典dict | 可变序列 | key不可重复,value可重复 | 无序 | {key:value} |
集合set | 可变序列 | 不可重复 | 无序 | {} |
函数与模块化编程
函数定义与参数传递(位置参数、关键字参数)
- 函数的定义: 函数是将一段实现功能的完整代码使用函数名称进行封装,通过函数名称进行调用,以此达到一次编写、多次调用的目的。
- 自定义函数:
def 函数名称(参数列表):
函数体
[return返回值列表]
- 函数调用: 函数名称(参数列表)
- 参数:
-
位置参数:是指调用时的参数个数和顺序必须与定义的参数个数相同。
-
关键字参数:是在函数调用时,使用‘形参名称=值’的方式进行传参,传递参数顺序可以与定义时参数的顺序不同。
-
默认值参数:是在函数定义时,直接对形式参数进行赋值,在调用时如果该参数不传值,将使用默认值,如果改参数传值,则使用传递的值。
-
可变参数:
- 个数可变的位置参数:在参数前加一颗星(*参数名),函数调用时可接收任意个数的实际参数,并放到一个元组中。
- 个数可变的关键字参数:在参数前加两颗星(**参数名),函数调用时可接收任意个‘参数=值‘形式的参数,并放到一个字典中。
返回值与多返回值的元组解包
- .返回值return: 如果函数的运行结果需要在其它函数中使用,那么这个函数就应该被定义成带返回值的函数。函数的运行结果使用return关键字进行返回, return可以出现在函数的任意一个位置用于结束函数。返回值可以是一个值或多个值,如果返回值是多个,结果是一个元组类型。
- 元组解包的基本用法
name, age, city = get_user_info()
print(name) # 输出:Alice
print(age) # 输出:30
print(city) # 输出:Beijing
#变量数量与元组元素数量必须一致
- 元组解包的进阶用法:处理数量不匹配的情况
#使用星号(*)表达式捕获多个元素
# 示例:获取前1个元素,剩余元素用列表接收
user_info = ("Alice", 30, "Beijing", "female", "programmer")
name, *others = user_info
print(name) # 输出:Alice
print(others) # 输出:[30, 'Beijing', 'female', 'programmer']
# 示例:获取中间元素,前后用列表接收
*before, city, *after = user_info
print(before) # 输出:['Alice', 30]
print(city) # 输出:Beijing
print(after) # 输出:female, programmer(注意:如果after不加'*'这里after只接收最后1个元素)
#用_忽略不需要的元素
user_info = ("Alice", 30, "Beijing")
name, _, city = user_info # 忽略age
print(name) # 输出:Alice
print(city) # 输出:Beijing
#结合*和_忽略多个元素
user_info = ("Alice", 30, "Beijing", "female", "programmer")
name, *_, job = user_info # 忽略中间的30、Beijing、female
print(name) # 输出:Alice
print(job) # 输出:programmer
lambda表达式的适用场景
- lambda 表达式(匿名函数) 是 Python 中一种简洁的函数定义方式,其语法为lambda 参数: 表达式。适用于需要简单函数且仅使用一次的场景。
- 常见场景:作为 “一次性” 函数参数
#对复杂结构(如字典、元组)排序时,用 lambda 指定排序键:
students = [("Alice", 20), ("Bob", 18), ("Charlie", 22)]
# 按年龄排序(第二个元素)
sorted_by_age = sorted(students, key=lambda x: x[1])
print(sorted_by_age) # 输出:[('Bob', 18), ('Alice', 20), ('Charlie', 22)]
#筛选可迭代对象中符合条件的元素:
numbers = [1, 2, 3, 4, 5, 6]
# 筛选偶数
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # 输出:[2, 4, 6]
#对可迭代对象中的元素做转换:
numbers = [1, 2, 3, 4]
# 计算每个数的平方
squared = list(map(lambda x: x **2, numbers))
print(squared) # 输出:[1, 4, 9, 16]
- 常见场景: 简化函数返回值
#当函数需要返回另一个简单函数时,lambda 可以替代def定义的嵌套函数,使代码更紧凑。
def make_adder(n):
# 返回一个“加n”的函数
return lambda x: x + n
add5 = make_adder(5)
print(add5(3)) # 输出:8(3+5)
print(add5(10)) # 输出:15(10+5)
- 常见场景: 作为字典 / 列表中的 “简单逻辑” 元素
# 在字典或列表中需要嵌入简单的操作逻辑时,lambda 可以避免单独定义函数,使代码更集中。
# 用字典存储不同的计算逻辑
operations = {
"add": lambda a, b: a + b,
"subtract": lambda a, b: a - b,
"multiply": lambda a, b: a * b
}
print(operations["add"](2, 3)) # 输出:5
print(operations["subtract"](5, 2)) # 输出:3
.
模块导入机制(import与from…import区别)
- import 语句:
- import 模块名 [as 别名],导入整个模块,使得模块中的所有公开成员(函数、类、变量等)可以通过「模块名。成员名」的方式访问。
- 导入的是整个模块,不会污染当前作用域(成员需通过模块名访问)
- 适合需要使用模块中多个成员的场景 - 可以通过 as 关键字指定别名,简化代码书写
import math # 导入 math 模块
print(math.pi) # 通过模块名访问成员
print(math.sqrt(16)) # 调用模块中的函数
# 使用别名简化访问
import math as m
print(m.pi) # 等价于 math.pi
- from…import语句:
- from 模块名 import 成员名 [as 别名] 或 from 模块名 import *,直接导入模块中的指定成员(或所有成员),可以直接通过「成员名」访问,无需前缀模块名。
- 直接导入成员,使用时无需模块名前缀,代码更简洁
- 可能导致命名冲突(如果当前作用域已有同名变量 / 函数)
- from…import * 会导入模块中所有公开成员(以下划线 _ 开头的私有成员除外),但可读性差,不建议在生产代码中使用
# 导入指定成员
from math import pi, sqrt
print(pi) # 直接使用成员名
print(sqrt(16))
# 为成员指定别名
from math import pi as圆周率
print(圆周率)
# 导入所有成员(不推荐)
from math import *
print(cos(0)) # 可以直接使用 math 中的所有公开成员
- import与from…import核心区别总结
维度 | import 模块 | from 模块 import 成员 |
---|---|---|
访问方式 | 必须通过 模块名.成员名 | 直接使用 成员名 |
作用域污染 | 不会污染(成员在模块命名空间) | 可能污染(成员直接进入当前作用域) |
适用场景 | 使用模块中多个成员 | 仅使用模块中少数几个成员 |
命名冲突风险 | 低(需通过模块名区分) | 高(可能与当前作用域成员重名 |
文件操作与异常处理
文件读写模式(r/w/a与二进制模式)
-
打开函数open(): 打开一个已存在的文件或传建一个新文件。open(name,mode,encoding)
-
文本模式:
- 文本模式用于处理文本文件(如 .txt、.py 等),读写内容为字符串(str 类型),会自动处理换行符(跨平台转换)。
模式 | 含义 | 特点 |
---|---|---|
r | 只读模式(默认) | 文件必须已存在,否则报错;指针位于文件开头 |
w | 只写模式 | 若文件不存在则创建;若已存在则清空原有内容;指针位于文件开头 |
a | 追加模式 | 若文件不存在则创建;写入内容追加到文件末尾;指针位于文件末尾 |
r+ | 读写模式 | 文件必须已存在;可读写,指针从开头开始 |
w+ | 读写模式 | 清空文件后读写(类似 w 但可读) |
a+ | 读写模式 | 追加内容,且可读取(但读操作需手动移动指针) |
# 1. 读取文件(r模式)
with open("test.txt", "r", encoding="utf-8") as f:
content = f.read() # 读取全部内容(字符串)
print(content)
# 2. 写入文件(w模式)
with open("test.txt", "w", encoding="utf-8") as f:
f.write("Hello, World!") # 覆盖原有内容
# 3. 追加内容(a模式)
with open("test.txt", "a", encoding="utf-8") as f:
f.write("\nAppend this line.") # 新增内容到末尾
-
文本模式操作的相关方法:
- read()方法: 文件对像.read(num),多次调用时,下一次会在上一次结束处读取。num为从文件中读取数据的长度(单位:字节),如果没有num则读取所有。
- readlines()方法: 按照行的方式把整个文件中的内容进行一次性读取,并返回为一个列表,其中每一行的数据为一个元素。列表名=文件对象.readlines()
- for循环读取文件行: for line in open(‘python.txt’,‘r’):print(line)
- flush()方法: 文件对象.flush(),将内容刷新,把内容真正写入文件,close也有相同效果
- 二进制模式:
- 二进制模式用于处理非文本文件(如图片、音频、视频、压缩包等),读写内容为字节流(bytes 类型),不处理换行符,需显式指定 b 标志。
模式 | 含义 | 对应文本模式 |
---|---|---|
rb | 二进制只读模式(默认) | r |
wb | 二进制只写模式 | w |
ab | 二进制追加模式 | a |
rb+/wb+/ab+ | 二进制读写模式 | r+/w+/a+ |
# 1. 读取图片(二进制文件)
with open("image.png", "rb") as f:
data = f.read() # 读取字节流(bytes类型)
# 2. 复制图片(二进制读写)
with open("image.png", "rb") as src, open("copy.png", "wb") as dst:
dst.write(src.read()) # 直接写入字节流
- 文本模式与二进制模式的区别:
维度 | 文本模式 | 二进制模式 |
---|---|---|
操作对象 | 字符串(str) | 字节流(bytes) |
编码要求 | 需要指定 encoding(如 utf-8) | 不需要指定编码(直接操作原始字节) |
适用文件 | 文本文件(.txt、.py 等) | 非文本文件(图片、音频、视频等) |
换行处理 | 自动转换(如 \n 与 \r\n) | 不处理,原样读写 |
- close()方法: 将内容刷新并关闭文件对象
with上下文管理器的资源自动释放
- with语句能自动处理资源的分配与释放,避免因忘记关闭资源而导致的内存泄漏或文件损坏等问题。当处理文件、网络连接、数据库连接等有限资源时,with 语句的核心优势是无论代码块正常执行还是发生异常,都会确保资源被正确释放。
# 风险:若中间代码报错,可能导致文件未关闭
f = open("test.txt", "r")
content = f.read()
f.close() # 必须手动调用,否则资源可能泄露
# 安全:无论是否发生异常,文件都会自动关闭
with open("test.txt", "r") as f:
content = f.read()
# 离开 with 代码块后,f 已自动关闭,无需手动操作
- with 语句的实现依赖于 上下文管理器协议,即对象必须实现两个特殊方法:
- enter():进入 with 代码块时调用,返回需要管理的资源(如文件对象)。
- exit():离开 with 代码块时调用(无论正常退出还是异常退出),负责释放资源。
class MyFile:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file # 返回资源给 as 后的变量
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close() # 自动释放资源
# 处理异常(可选)
if exc_type:
print(f"发生异常:{exc_val}")
return False # 不抑制异常,让其继续传播
# 使用自定义上下文管理器
with MyFile("test.txt", "w") as f:
f.write("Hello, Context Manager!")
- with语句的使用场景:
- 文件操作
with open("data.csv", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
- 数据库连接
import sqlite3
with sqlite3.connect("mydb.db") as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
# 离开代码块后,连接自动关闭
- 网络连接
import socket
with socket.socket() as s:
s.connect(("example.com", 80))
s.send(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
# 套接字自动关闭
- 锁机制
import threading
lock = threading.Lock()
with lock:
# 临界区代码(自动获取和释放锁)
pass
常见异常类型(IOError, ValueError等)
- 基础异常类
- Exception:所有非系统退出类异常的基类,几乎所有自定义异常都继承自它。
- BaseException:所有异常的顶层基类,包括 Exception 和系统退出类异常(如 SystemExit)。
- 常见具体异常类型
异常类型 | 触发场景 | 示例 |
---|---|---|
IOError | 输入/输出操作失败(如文件未找到、权限不足) | 尝试打开不存在的文件 open(“nonexist.txt”) |
FileNotFoundError | 尝试打开不存在的文件(Python 3 新增,IOError 的子类) | open(“missing.txt”, “r”) |
ValueError | 传入的值类型正确但不符合要求 | int(“abc”)(字符串无法转换为整数) |
TypeError | 操作或函数应用于不适当类型的对象 | “2” + 2(字符串与整数拼接) |
IndexError | 序列索引超出范围 | [1,2,3][5](列表索引越界) |
KeyError | 字典中查找不存在的键 | {“a”:1}[“b”](访问不存在的字典键) |
NameError | 引用未定义的变量 | print(undefined_var)(变量未声明) |
ZeroDivisionError | 除数为零 | 10 / 0(数学上的除以零错误) |
AttributeError | 尝试访问对象不存在的属性 | “string”.nonexist_attr(字符串无此属性) |
SyntaxError | 代码语法错误(编译时异常) | if True: print(“hi”) 缺少缩进 |
IndentationError | 缩进错误(Python 特有的语法错误) | 代码块缩进不一致 |
ImportError | 导入模块失败 | import nonexist_module(模块不存在) |
KeyboardInterrupt | 用户按下 Ctrl+C 中断程序 | 运行时强制终止程序 |
- 异常处理示例
使用 try…except 捕获并处理异常:
try:
# 可能触发异常的代码
num = int(input("请输入数字:"))
result = 10 / num
print(f"结果:{result}")
except ValueError:
print("错误:输入不是有效的数字")
except ZeroDivisionError:
print("错误:除数不能为零")
except Exception as e:
# 捕获其他未预料的异常
print(f"发生未知错误:{e}")
- 注意
- 异常类型反映了错误的具体原因,针对性捕获能让代码更健壮。
- 避免使用 except Exception 捕获所有异常(可能掩盖真正的问题),应优先捕获具体异常。
- 调试时,异常的堆栈信息(traceback)会显示错误类型和位置,是排查问题的关键。
try-except-finally的完整处理流程
- 基本结构
try:
# 可能发生异常的代码块(核心逻辑)
risky_operation()
except 异常类型1 [as 变量名]:
# 若发生「异常类型1」,执行此处代码(处理异常)
handle_error_type1()
except (异常类型2, 异常类型3) [as 变量名]:
# 若发生「异常类型2」或「异常类型3」,执行此处代码
handle_error_type2_or_3()
else:
# 若 try 块无异常,执行此处代码(可选)
no_error_operation()
finally:
# 无论是否发生异常,都会执行此处代码(释放资源等)
must_execute_operation()
-
执行流程详解
-
try 块优先执行:
程序首先执行 try 中的代码,这是可能发生异常的核心逻辑。 -
若 try`块发生异常:
- 立即中断 try块执行,跳转到对应的 except块匹配异常类型。
- 若找到匹配的 except 块,执行其中的异常处理代码。
- 若未找到匹配的 except 块,异常会向上传播(可能导致程序终止)。
- 无论是否匹配到 except,最终都会执行 finally 块。
- 若 try 块无异常:
- 执行完 try 块后,跳过所有 except 块。
- 若有 else 块,执行 else 中的代码(else 是无异常时的附加逻辑)。
- 最后执行 finally 块。
- finally 块的必然性:
无论 try 块是否异常、except 块是否匹配、甚至 return/break 语句,finally 块一定会执行,常用于释放资源(如关闭文件、断开连接)。
-
-
实例演示
def read_file_safely(filename):
file = None # 初始化变量,避免未定义错误
try:
file = open(filename, "r", encoding="utf-8")
content = file.read()
print("文件内容:", content[:100]) # 打印前100字符
return "读取成功" # 无异常时返回
except FileNotFoundError:
print(f"错误:文件 '{filename}' 不存在")
return "读取失败" # 异常时返回
except UnicodeDecodeError as e:
print(f"错误:文件编码异常 - {e}")
return "读取失败"
else:
print("额外操作:文件读取无异常,记录日志") # 仅无异常时执行
finally:
# 无论是否异常,确保文件关闭
if file:
file.close()
print("资源释放:文件已关闭")
# 测试:文件存在且正常
read_file_safely("test.txt")
# 测试:文件不存在
read_file_safely("nonexist.txt")
- 关键特性
- except 多分支:可按异常类型精准处理,避免一刀切捕获所有异常。
- else 块作用:分离「核心逻辑」和「无异常时的附加逻辑」,使代码更清晰。
- finally不可替代:即使在 try 或 except 中使用 return,finally仍会执行(如下):
def demo(): try: return 1 # 尝试返回 finally: print("finally 执行了") # 仍会执行 demo() # 输出:finally 执行了,返回值 1
- 使用场景
- try:包裹可能出错的核心代码(如文件操作、网络请求)。
- except:针对性处理可预见的异常(如文件不存在、网络超时)。
- else:处理无异常时的附加逻辑(如日志记录、结果校验)。
- finally:必做的收尾工作(如关闭文件/连接、释放锁、清理临时文件)。
面向对象编程基础
类与对象的概念解析
- 类(Class): 类是对一类事物共同特征和行为的抽象描述,它不特指某个具体的事物,而是定义了这类事物"是什么"(属性)和"能做什么"(方法)。
- 属性(Attribute):类中定义的变量,用于描述事物的特征。例如"人"类的属性可以是姓名、年龄、性别等。
- 方法(Method):类中定义的函数,用于描述事物的行为。例如"人"类的方法可以是走路、说话、吃饭等。
- 对象(Object): 对象是类的具体实例,是根据类创建的具体个体。它具有类中定义的属性和方法,并且属性有具体的值。一个类可以创建多个对象,每个对象的属性值可以不同,但都遵循类定义的结构。
- 面向对象的核心意义
- 封装性: 类将属性和方法封装在一起,对外隐藏实现细节,只暴露必要的接口。
- 复用性: 通过类可以快速创建多个对象,避免重复代码。
- 扩展性: 基于已有类可以创建新类(继承),实现功能的扩展。
- 代码示例(Python)
# 定义一个"人"类(模板)
class Person:
# 属性(特征)
def __init__(self, name, age):
self.name = name # 姓名
self.age = age # 年龄
# 方法(行为)
def speak(self):
print(f"我叫{self.name},今年{self.age}岁")
# 创建对象(具体实例)
person1 = Person("张三", 20) # 第一个对象
person2 = Person("李四", 30) # 第二个对象
# 调用对象的方法
person1.speak() # 输出:我叫张三,今年20岁
person2.speak() # 输出:我叫李四,今年30岁
#在这个例子中,`Person`是类,`person1`和`person2`是根据该类创建的两个不同对象,它们都有`name`、`age`属性和`speak()`方法,但属性值不同。
构造方法(init)与实例属性
- 构造方法(_init_): 构造方法是类中一个特殊的方法,用于在创建对象时初始化对象的属性。
-
特点:
- 当通过类创建对象时,_init_ 会被自动调用。
- 第一个参数必须是self,代表当前正在创建的对象本身。
- 可以定义额外参数,用于为对象的属性赋值。
-
作用:
- 为新创建的对象设置初始状态(属性值)。
- 执行对象创建时必需的初始化操作(如打开文件、连接数据库等)。
- 实例属性: 实例属性是属于具体对象的属性,每个对象的实例属性可以有不同的值。它们通常在构造方法中通过 self.属性名 定义。
- 特点:
- 每个对象的实例属性独立存储,修改一个对象的属性不会影响其他对象。
- 必须通过对象(或 self)访问,如 p.name 或 self.name。
- 构造方法与实例属性的关系: 构造方法是定义和初始化实例属性的主要场所。通过 _init_ 方法的参数,可以在创建对象时为实例属性赋值,使每个对象一创建就具备具体的属性值。
class Person:
# 构造方法:初始化实例属性
def __init__(self, name, age): # name和age是外部传入的参数
self.name = name # 定义并初始化实例属性name
self.age = age # 定义并初始化实例属性age
def introduce(self):
# 通过self访问实例属性
print(f"我叫{self.name},今年{self.age}岁")
# 创建对象时,自动调用__init__,传入参数初始化属性
p1 = Person("张三", 20)
p2 = Person("李四", 30)
# 访问实例属性
print(p1.name) # 输出:张三
print(p2.age) # 输出:30
# 调用方法(方法内部使用了实例属性)
p1.introduce() # 输出:我叫张三,今年20岁
- 关键点说明
- self 的作用:self 是构造方法(及所有实例方法)的第一个参数,代表当前对象。通过 self.属性名 定义的属性,会成为该对象的实例属性。
- 默认参数:构造方法可以使用默认参数,使创建对象时某些属性可选:
class Person: def __init__(self, name, age=18): # age默认值为18 self.name = name self.age = age p = Person("王五") # 不传入age,使用默认值18 print(p.age) # 输出:18
- 实例属性的动态添加:除了在 _init_ 中定义,也可以在对象创建后动态添加实例属性(但不推荐,会导致代码混乱):
p1 = Person("张三", 20) p1.gender = "男" # 动态添加gender属性
继承与方法重写(super()函数使用)
- 继承(Inheritance): 继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,并可以在此基础上添加新的属性或方法,或修改父类的方法。
- 作用:
- 代码复用:无需重复编写父类已有的代码。
- 功能扩展:在父类基础上添加新功能。
- 多态实现:为不同子类的同名方法提供统一调用接口。
# 父类(基类)
class Parent:
def parent_method(self):
print("这是父类的方法")
# 子类(派生类),继承自Parent
class Child(Parent):
def child_method(self):
print("这是子类的方法")
# 子类对象可以调用父类和自身的方法
c = Child()
c.parent_method() # 输出:这是父类的方法(继承自父类)
c.child_method() # 输出:这是子类的方法(自身方法)
- 方法重写(Override): 子类的"个性化改造"
当子类需要对父类的方法进行修改或扩展时,可以定义与父类同名的方法,这称为方法重写。
- 场景:
- 父类方法的逻辑不满足子类需求。
- 需要在父类方法基础上添加新逻辑。
class Animal:
def speak(self):
print("动物发出声音")
# 子类Dog重写speak方法
class Dog(Animal):
def speak(self): # 与父类方法同名
print("汪汪汪")
# 子类Cat重写speak方法
class Cat(Animal):
def speak(self): # 与父类方法同名
print("喵喵喵")
dog = Dog()
dog.speak() # 输出:汪汪汪(调用重写后的方法)
cat = Cat()
cat.speak() # 输出:喵喵喵(调用重写后的方法)
- super()函数: super() 用于在子类中调用父类的方法或属性,尤其在方法重写时,可以保留父类的逻辑并添加子类特有的逻辑。
- 常见用法:
-
在子类构造方法中调用父类构造方法
确保父类的属性被正确初始化。 -
在重写的方法中调用父类的同名方法
复用父类逻辑,再添加子类特有的逻辑。
-
#在构造方法中使用super()
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, school):
# 调用父类的__init__方法,初始化name和age
super().__init__(name, age)
# 子类新增属性
self.school = school
def introduce(self):
print(f"我叫{self.name},{self.age}岁,在{self.school}上学")
s = Student("张三", 18, "北京大学")
s.introduce() # 输出:我叫张三,18岁,在北京大学上学
#在重写方法中使用super()
class Animal:
def move(self):
print("动物在移动")
class Bird(Animal):
def move(self):
# 先调用父类的move方法
super().move()
# 再添加子类特有的逻辑
print("鸟在飞翔")
bird = Bird()
bird.move()
# 输出:
# 动物在移动
# 鸟在飞翔
- 关键点说明
- super()的本质:super() 并非直接调用"父类",而是调用继承链中的下一个类(适用于多继承场景)。
- 参数传递:在super()调用中,无需手动传递self参数,Python会自动处理。
- 多继承中的super(): 在多继承(如class C(A, B))中,super() 会按照MRO(方法解析顺序) 调用下一个类的方法,避免方法调用冲突。
魔术方法(如__str__, len)的实用案例
- _str_():自定义对象的字符串表示
_str_() 用于定义对象被print()或str()转换时的字符串格式,让对象的输出更具可读性。
#定义一个Book类,打印时显示书籍的基本信息
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
# 自定义字符串表示
def __str__(self):
return f"《{self.title}》- 作者:{self.author}({self.pages}页)"
book = Book("Python编程", "张三", 300)
print(book) # 自动调用__str__(),输出:《Python编程》- 作者:张三(300页)
print(str(book)) # 同样调用__str__(),输出同上
- _len_():让对象支持len()函数
_len_() 用于定义当调用len(obj)时的返回值,通常用于表示对象的"长度"或"数量"。
#定义一个ShoppingCart类,用len()获取购物车中商品数量
class ShoppingCart:
def __init__(self):
self.items = [] # 存储商品的列表
def add_item(self, item):
self.items.append(item)
# 定义len()的返回值为商品数量
def __len__(self):
return len(self.items)
cart = ShoppingCart()
cart.add_item("苹果")
cart.add_item("香蕉")
print(len(cart)) # 自动调用__len__(),输出:2
- _getitem_()和__setitem__():让对象支持索引操作
这两个方法用于使对象可以像列表或字典一样通过[ ]进行取值和赋值。
#定义一个StudentList类,支持用索引访问学生
class StudentList:
def __init__(self):
self.students = []
# 支持obj[index]取值
def __getitem__(self, index):
return self.students[index]
# 支持obj[index] = value赋值
def __setitem__(self, index, value):
self.students[index] = value
students = StudentList()
students.students = ["张三", "李四", "王五"]
print(students[0]) # 调用__getitem__(),输出:张三
students[1] = "赵六" # 调用__setitem__()
print(students[1]) # 输出:赵六
- _add_():自定义对象的加法运算
_add_() 用于定义两个对象相加(+)时的逻辑。
#定义一个Vector类,实现向量的加法
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
# 自定义加法:两个向量的x和y分别相加
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(4, 5)
v3 = v1 + v2 # 自动调用__add__()
print(v3) # 输出:Vector(6, 8)
- _bool_():自定义对象的布尔值判断
_bool_() 用于定义对象在布尔判断(如 if obj:)时的返回值,默认情况下所有对象都为True。
#定义一个Account类,余额为0时视为False
class Account:
def __init__(self, balance=0):
self.balance = balance
# 余额为0时返回False,否则返回True
def __bool__(self):
return self.balance > 0
acc1 = Account(100)
acc2 = Account(0)
if acc1:
print("账户1有余额") # 会执行
if acc2:
print("账户2有余额") # 不会执行
- 魔术方法的核心价值
- 增强可读性:如_str_()让对象的输出更直观。
- 模拟内置类型:通过_len_()、_getitem_()等让自定义类像列表、字典一样使用。
- 简化逻辑:将特定操作(如加法、判断)封装在魔术方法中,使代码更简洁。
标准库常用模块
os和sys模块的系统交互
- os模块: 主要用于与操作系统进行交互,提供了访问文件系统、环境变量、进程管理等功能,它更偏向于操作系统层面的操作。
#os模块常用功能
import os
# 获取当前工作目录
current_dir = os.getcwd()
print(f"当前工作目录: {current_dir}")
# 列出目录中的文件和文件夹
files = os.listdir(current_dir)
print(f"目录内容: {files}")
# 创建目录
new_dir = "test_dir"
os.mkdir(new_dir)
# 重命名文件/目录
os.rename(new_dir, "new_test_dir")
# 删除目录
os.rmdir("new_test_dir")
# 获取环境变量
path_var = os.environ.get("PATH")
print(f"PATH环境变量: {path_var}")
# 执行系统命令
os.system("echo Hello from system command!")
- sys模块: 主要用于与Python解释器本身进行交互,提供了与解释器相关的配置和操作,比如命令行参数、解释器版本信息、标准输入输出等。
#sys模块常用功能
import sys
# 获取命令行参数
print(f"命令行参数: {sys.argv}")
# 获取Python解释器版本信息
print(f"Python版本: {sys.version}")
# 获取系统平台
print(f"系统平台: {sys.platform}")
# 标准输出重定向
print("这是标准输出")
sys.stdout.write("这也是标准输出\n")
# 退出程序
# sys.exit(0) # 0表示正常退出,非0表示异常退出
# 获取模块搜索路径
print(f"模块搜索路径: {sys.path}")
datetime模块的时间处理
-
datetime 模块: datetime 模块是处理日期和时间的核心工具,提供了简洁且功能丰富的类来操作时间,包括日期计算、格式转换、时区处理等。
-
datetime的核心类:
- date: 处理年、月、日(日期)
- time: 处理时、分、秒、微秒(时间)
- datetime: 同时处理日期和时间(最常用)
- timedelta: 表示时间间隔(用于日期加减)
- tzinfo/timezone: 处理时区(Python 3.2+ 新增 timezone 简化时区操作)
-
常用功能示例:
#获取当前时间
from datetime import datetime, date, time
# 获取当前日期时间(datetime对象)
now = datetime.now()
print("当前时间:", now) # 输出:2023-10-15 14:30:45.123456
# 获取当前日期(date对象)
today = date.today()
print("当前日期:", today) # 输出:2023-10-15
# 单独获取年、月、日、时、分、秒
print("年:", now.year) # 2023
print("月:", now.month) # 10
print("日:", now.day) # 15
print("时:", now.hour) # 14
print("分:", now.minute) # 30
print("秒:", now.second) # 45
#创建指定时间
from datetime import datetime, date, time
# 创建指定日期时间(datetime)
dt = datetime(2023, 10, 1, 8, 30, 0)
print("指定时间:", dt) # 2023-10-01 08:30:00
# 创建指定日期(date)
d = date(2023, 12, 25)
print("指定日期:", d) # 2023-12-25
# 创建指定时间(time)
t = time(18, 45, 30)
print("指定时间:", t) # 18:45:30
#时间格式转换(字符串与datetime互转)
#strftime():将 datetime 转为字符串(格式化输出)
#strptime():将字符串转为 datetime(解析输入)
from datetime import datetime
# datetime -> 字符串(格式化)
now = datetime.now()
str1 = now.strftime("%Y-%m-%d %H:%M:%S") # 年-月-日 时:分:秒
str2 = now.strftime("%Y年%m月%d日 %H时%M分") # 中文格式
print("格式化后:", str1) # 2023-10-15 14:30:45
print("中文格式:", str2) # 2023年10月15日 14时30分
# 字符串 -> datetime(解析)
str_time = "2023-10-01 08:30:00"
dt = datetime.strptime(str_time, "%Y-%m-%d %H:%M:%S")
print("解析后的时间:", dt) # 2023-10-01 08:30:00
"""
常用格式化符号
%Y:四位数年份(如 2023)
%m:两位数月份(01-12)
%d:两位数日期(01-31)
%H:24小时制小时(00-23)
%M:分钟(00-59)
%S:秒(00-59)
"""
# 时间间隔计算(timedelta)
#timedelta 用于表示时间差,可直接与 datetime 进行加减运算。
from datetime import datetime, timedelta
now = datetime.now()
# 计算3天后的时间
future = now + timedelta(days=3)
print("3天后:", future) # 2023-10-18 14:30:45.123456
# 计算1小时30分钟前的时间
past = now - timedelta(hours=1, minutes=30)
print("1小时30分钟前:", past) # 2023-10-15 13:00:45.123456
# 计算两个时间的差
delta = future - past
print("时间差(天):", delta.days) # 3
print("时间差(总秒数):", delta.total_seconds()) # 270000.0(3天×86400秒)
#时区处理
#使用 pytz 库(需安装:pip install pytz)或 Python 3.9+ 的 zoneinfo 处理时区。
from datetime import datetime
import pytz # 第三方时区库
# 获取纽约时间(UTC-4/UTC-5,随季节变化)
ny_tz = pytz.timezone('America/New_York')
ny_time = datetime.now(ny_tz)
print("纽约时间:", ny_time.strftime("%Y-%m-%d %H:%M:%S"))
# 获取北京时区(UTC+8)
bj_tz = pytz.timezone('Asia/Shanghai')
bj_time = datetime.now(bj_tz)
print("北京时间:", bj_time.strftime("%Y-%m-%d %H:%M:%S"))
json模块的数据序列化
- json模块: 提供了对 JSON 数据格式的序列化(将 Python 对象转换为 JSON 字符串)和反序列化(将 JSON 字符串转换为 Python 对象)功能,是处理 JSON 数据的核心工具。
2.json模块中的核心函数:
- json.dumps():将 Python 对象序列化为 JSON 字符串
- json.dump():将 Python 对象序列化为 JSON 字符串并写入文件
- json.loads():将 JSON 字符串反序列化为 Python 对象
- json.load():从文件中读取 JSON 字符串并反序列化为 Python 对象
- Python 与 JSON 类型对应关系: 序列化时,Python 类型会被转换为对应的 JSON 类型
Python 类型 | JSON 类型 |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
- ** 序列化(Python → JSON)**
import json
# 定义一个 Python 字典(可序列化的对象)
data = {
"name": "Alice",
"age": 30,
"is_student": False,
"hobbies": ["reading", "hiking"],
"address": {
"city": "New York",
"zipcode": "10001"
},
"score": None
}
# 使用 dumps() 转为 JSON 字符串
json_str = json.dumps(data)
print("JSON 字符串:", json_str)
# 输出:{"name": "Alice", "age": 30, "is_student": false, "hobbies": ["reading", "hiking"], "address": {"city": "New York", "zipcode": "10001"}, "score": null}
# 格式化输出(更易读)
pretty_json = json.dumps(data, indent=4, ensure_ascii=False)
print("格式化 JSON:")
print(pretty_json)
"""
dumps() 常用参数:
indent:指定缩进空格数,美化输出
ensure_ascii:默认 True(非 ASCII 字符转义),设为 False 可保留中文等字符
sort_keys:设为 True 可按 key 排序
"""
- 反序列化(JSON → Python)
import json
# JSON 字符串
json_str = '''
{
"name": "Bob",
"age": 25,
"is_student": true,
"hobbies": ["coding", "gaming"],
"address": {
"city": "London",
"zipcode": "SW1A 1AA"
},
"score": null
}
'''
# 使用 loads() 转为 Python 字典
python_data = json.loads(json_str)
print("Python 对象类型:", type(python_data)) # <class 'dict'>
print("姓名:", python_data["name"]) # Bob
print("爱好:", python_data["hobbies"][0]) # coding
- 与文件交互
import json
data = {"name": "Charlie", "age": 35}
# 序列化并写入文件(dump())
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
# 从文件读取并反序列化(load())
with open("data.json", "r", encoding="utf-8") as f:
loaded_data = json.load(f)
print("从文件读取的数据:", loaded_data) # {'name': 'Charlie', 'age': 35}
7.处理复杂对象(自定义序列化)
默认情况下,json 模块只能序列化标准 Python 类型。如果需要序列化自定义类对象,需定义 default 函数 或实现类的 _dict_ 方法。
示例:序列化自定义类
import json
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# 自定义序列化函数
def person_serializer(obj):
if isinstance(obj, Person):
return {"name": obj.name, "age": obj.age, "type": "Person"}
raise TypeError(f"无法序列化 {type(obj)} 类型的对象")
# 创建自定义对象
person = Person("David", 40)
# 使用 default 参数指定序列化函数
json_str = json.dumps(person, default=person_serializer, indent=4)
print(json_str)
# 输出:
# {
# "name": "David",
# "age": 40,
# "type": "Person"
# }
random模块的随机数生成
-
random 模块: random 模块提供了丰富的随机数生成功能,可用于生成随机整数、浮点数、随机选择序列元素等场景。用户可以根据根据场景选择合适的函数,例如抽奖可用 choice() 或 sample(),洗牌可用 shuffle(),数值模拟可用 gauss() 等。
-
生成随机浮点数:
- random.random(): 生成 [0.0, 1.0) 之间的随机浮点数
- **random.uniform(a, b):**生成 [a, b] 或 [b, a] 之间的随机浮点数(取决于 a 和 b 的大小)
import random
# 生成 [0.0, 1.0) 之间的随机浮点数
print(random.random()) # 示例:0.783421569
# 生成 [1.5, 3.5] 之间的随机浮点数
print(random.uniform(1.5, 3.5)) # 示例:2.8912345
- 生成随机整数:
- random.randint(a, b): 生成 [a, b] 之间的整数(包含 a 和 b)
- random.randrange(start, stop[, step]): 从指定范围中按步长随机选择整数(类似 range() 用法)
import random
# 生成 1-10 之间的随机整数(包含1和10)
print(random.randint(1, 10)) # 示例:7
# 从 0-20 中随机选择偶数(步长为2)
print(random.randrange(0, 21, 2)) # 示例:14
- 随机选择元素:
- random.choice(seq): 从非空序列中随机选择一个元素
- random.choices(seq, weights=None, k=1): 从序列中随机选择 k 个元素(可带权重,允许重复)
import random
fruits = ["苹果", "香蕉", "橙子", "草莓"]
# 随机选择一个水果
print(random.choice(fruits)) # 示例:香蕉
# 带权重随机选择(草莓被选中概率更高)
print(random.choices(fruits, weights=[1, 1, 1, 3], k=2)) # 示例:['草莓', '橙子']
- 打乱序列顺序:
- random.shuffle(seq): 原地打乱序列(修改原序列,无返回值)
import random
nums = [1, 2, 3, 4, 5]
random.shuffle(nums) # 原地打乱
print(nums) # 示例:[3, 1, 5, 2, 4]
- 随机抽样(无重复):
- random.sample(seq, k): 从序列中随机选择 k 个不重复的元素
import random
cards = ["红桃A", "黑桃K", "方块Q", "梅花J", "大王"]
# 随机抽取2张不重复的牌
print(random.sample(cards, 2)) # 示例:['黑桃K', '梅花J']
- 随机种子(确保结果可复现):
- random.seed(a=None): 设置随机数种子,相同种子会生成相同的随机序列(用于调试或复现结果)
import random
# 设置种子
random.seed(10)
print(random.randint(1, 100)) # 结果固定为 73
# 再次设置相同种子,结果相同
random.seed(10)
print(random.randint(1, 100)) # 仍然输出 73
- 生成高斯分布随机数:
- random.gauss(mu, sigma): 生成符合高斯分布(正态分布)的随机数,mu 是均值,sigma 是标准差
import random
# 生成均值为0,标准差为1的高斯随机数
print(random.gauss(0, 1)) # 示例:0.283456
注意事项
- random 模块生成的是伪随机数(基于种子的确定性算法),不适用于加密场景
- 加密级随机数需使用 secrets 模块(Python 3.6+)
- 多线程环境下,random 模块可能存在线程安全问题,可使用 random.getstate() 和 random.setstate() 保存/恢复状态
结束语
本篇内容到此就结束了,如果你已经很好地理解了本篇的内容,那么恭喜你,你可以自豪的说:“我学过Python了”。是不是有点失望,我学了这么久怎么才是学过,我明明已经会了。回忆一下开头,Python这门语言包含了丰富的标准库,这些标准库构成了Python无所不能的美名。单单学完本篇,你只是拿到了前往各种库的钥匙,所以前方的区域已经对你开放,继续探索吧旅行者^_^