人工智能学习中深度学习之python基础之迭代器、生成器、文件处理和模块等
前言:
迭代器和生成器主要是更高效,更优雅的方式处理大量数据,一边计算,一边返回结果,好处是可以节省内存并不会大量占用cpu。之后也进行补充了文件处理等其他模块的知识
常用生成器区域:读取巨大文件时,如果读取时采用for进行返回所有行再进行操作需要消耗大量内存很有可能撑爆服务器,采取惰性读取的方式极大的节省了内存,需要的时候再获取。
1.迭代器、生成器和装饰器
1.迭代器
定义:迭代器需要包含两个方法_iter_和_next_,只要包含这两个方法的对象就是迭代器
__iter__和__next__称之为特殊方法或魔法方法
1.__iter__():返回迭代器对象本身。(可以理解为初始化迭代器)
2.__next__():返回下一个元素,如果没有元素则抛出StopIteration
迭代器和可迭代对象的区别
1.可迭代对象:任何支持for循环的对象,列表,元组,字典,字符串,集合
2.迭代器:具有__next__()方法,每次返回一个元素,使用iter()生成迭代器
# hasattr函数作用是查看一个对象是否有某个属性或者方法my_list = [1,2,3,4,5]
my_str = 'hello world'
my_int = 123
print(hasattr(my_list,'__iter__')) #True
print(hasattr(my_str,'__iter__')) #True
print(hasattr(my_int,'__iter__')) #False#迭代器的案例
nums = [1,2,3]
it = iter(nums)print(next(it)) #1
print(next(it)) #2
print(next(it)) #3
print(next(it)) #报错 StopIteration自定义迭代器案例(斐波那契数列)
#斐波那契数列
class FibonacciIterator:def __init__(self, max_count):self.a,self.b = 0,1self.count = 0self.max_count = max_countdef __iter__(self):return selfdef __next__(self):if self.count >= self.max_count:raise StopIterationself.a, self.b = self.b, self.a + self.bself.count += 1return self.afib = FibonacciIterator(10)
for item in fib:print(item,end=" ")#1 1 2 3 5 8 13 21 34 55 2.生成器
定义:生成器是一种特殊的迭代器,他通过yield语句返回数据。不同于函数一次全部返回结果,生成器会“暂停”并在下次调用时继续执行。
原理:生成器函数执行会返回一个生成器对象。每次调用next()时,执行到yield就暂停并返回一个值。
def count_up_to(n):count = 1while count <= n:yield countcount += 1w = count_up_to(3)
print(next(w)) #1
print(next(w)) #2
print(next(w)) #3
print(next(w)) #StopIterationyield 和 return 的区别
| 关键字 | 作用 | 是否保存状态 | 返回值 | 适用场景 |
| return | 终止函数 | 否 | 立即返回值 | 普通函数 |
| yield | 生成值,暂停函数 | 是 | 迭代时返回下一个值 | 需要逐步生成数据的情况 |
#斐波那契数列案例
def fibonacci(n):a,b = 0,1while a < n:yield aa,b = b,a+bfor num in fibonacci(20):print(num)#0 1 1 2 3 5 8 13 生成无线序列的案例
#无线生成序列def infinite():num = 1while True:yield numnum = num+1count = infinite()
print(next(count))
print(next(count))
for _ in range(5):print(next(count))'''
1
2
3
4
5
6
7
'''生成器常用读取大文件路径案例
filename = r'C:\Users\Excub\PycharmProjects\PythonProject_1019\Python_100.py' def read_large_file(filename):with open(filename, 'r',encoding='utf-8') as f:for line in f:yield line.strip()for line in read_large_file(filename):print(line)
3.生成器表达式
原理:类似列表推导式,但最外层用()括起来,生成生成器,只在需要时生成数据(节省内存)
简单理解:将列表推导式以生成器形式产出即可。
#案例
wang = (i**2 for i in range(5))
wang_list = list(i**2 for i in range(5))print(wang) #<generator object <genexpr> at 0x000002A4D615DBE0>
print(wang_list) #[0, 1, 4, 9, 16]print(next(wang)) #0
for num in wang:print(num,end=',') #1,4,9,16,| 对比项 | 迭代器(Iterator) | 生成器(Generator) |
| 定义 | 需要实现__iter__()和__next__()方法 | 使用yield定义 |
| 状态保护 | 手动管理 | 自动保存状态 |
| 内存占用 | 可能较高 | 节省内存(惰性计算) |
| 代码复杂度 | 需要维护内部变量 | 代码更简洁 |
| 示例 | 自定义class迭代器 | yield生成斐波那契数列 |
4.闭包函数和装饰器
本质:嵌套在外部函数中的内部函数。满足以下两个条件
1.内部函数引用了外部函数中定义的变量或参数
2.外部函数的返回值是这个内部函数(不是函数结果,是函数本身)
3.闭包函数的判断通过__closuure__来判断是否为闭包
闭包的核心作用:
1.保存上下文状态:让函数能记得他创建的环境(比如说累计计数,保存配置),不用依赖全局变量
2.实现数据封装:外部无法直接修改闭包引用的变量,只能通过内部函数间接操作,保证数据安全
累计计数器案例
def outer():# 外部函数的变量:被内部函数引用count = 0 # 记录调用次数,不会被外部直接修改def inner():# 关键:用nonlocal声明“要修改外部函数的变量”(否则视为局部变量)nonlocal countcount += 1print(f"函数被调用了 {count} 次")# 外部函数返回内部函数(不是inner(),是函数本身)return inner# 1. 调用外部函数,得到内部函数(此时count=0被“打包”进inner) counter = outer() # 2. 调用内部函数,每次调用都会修改“打包”的count counter() # 输出:函数被调用了 1 次 counter() # 输出:函数被调用了 2 次 counter() # 输出:函数被调用了 3 次 # 3.查看是否为闭包函数 print(counter.__closure__) #(<cell at 0x00000245F6807D90: int object at 0x00007FFE2EA149F8>,)上述代码关于闭包函数的注意点
1.函数嵌套且外层函数的返回值是内层函数本身
2.内部函数修改外部函数中的变量时使用nonlocal关键字
3.函数调用时首先调用外部函数所赋值的变量需再加()才能再次调用出来
装饰器的本质:基于闭包实现“函数包装工具”核心作用是:不修改原函数代码的前提下,给原函数添加额外的功能(日志,记时,权限校验)
核心逻辑:装饰器的本质是一个 “函数”,它接收一个 “原函数” 作为参数,通过闭包返回一个 “包装后的新函数”
- 执行原函数的核心逻辑。
- 在原函数执行前后,添加额外功能(比如计时、打印日志)。
装饰器和闭包的关系:
- 闭包是 “技术基础”:装饰器利用闭包的 “保存上下文” 能力,存储额外功能需要的变量(比如累计耗时、调用次数)。
- 装饰器是 “应用场景”:闭包可以做很多事(比如计数器),而装饰器是闭包在 “函数增强” 场景下的典型应用。
装饰器的经典案例(给函数添加计时功能)分为三步走
1.定义装饰器函数(基于闭包函数的基础上)
2.给原函数添加语法糖@,作用是把下面的函数作为参数传给装饰器,再把装饰器返回的新函数赋值给原函数名
3.调用原函数(实际执行的是装饰后的函数)
1.案例装饰器的计时器
import time# 装饰器:接收被装饰的函数作为参数(func) def outer(func):# 内部函数:接收原函数的参数(*args, **kwargs)def inner(*args, **kwargs):start = time.time() # 记录开始时间# 核心:调用被装饰的原函数,并获取返回值result = func(*args, **kwargs)end = time.time() # 记录结束时间elapsed = end - start # 计算耗时# 打印计时信息(函数名应为原函数名func.__name__)print(f'函数 {func.__name__} 执行时间:{elapsed:.10f} 秒')return result # 返回原函数的计算结果return inner # 装饰器返回包装后的inner函数# 用@outer装饰add_函数(等价于 add_ = outer(add_)) @outer def add_(a, b):time.sleep(1) # 模拟耗时操作return a + b# 调用装饰后的add_(实际执行的是inner函数) result = add_(2, 3) print(f'函数返回值:{result}') # 直接打印结果,无需再调用2.统计函数调用次数
def count_calls(func):call_count = 0def wrapper(*args,**kwargs):nonlocal call_countcall_count = call_count + 1res = func(*args,**kwargs)print(f'函数{func.__name__}已经被调用{call_count}次,结果是{res}')return resreturn wrapper@count_calls def multiply(a, b):return a * bprint(multiply(2,3)) print(multiply(4,5))3.需要传参的装饰器则需要在原闭包函数基础上添加外层函数
如下述例子(超时警告的装饰器)
具体思路如下:外层(接收装饰器参数)→ 中层(接收被装饰函数)→ 内层(包装逻辑)
import time# 外层:接收装饰器的参数threshold(明确关键字参数更清晰) def timeout_warning(threshold):# 中层:接收被装饰的函数funcdef decorator(func):# 内层:包装逻辑(接收原函数的参数)def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs) # 调用原函数end_time = time.time()elapsed = end_time - start_time # 计算耗时# 判断是否超时并打印信息if elapsed > threshold:print(f"警告:函数[{func.__name__}]执行耗时[{elapsed:.6f}]秒,超过阈值[{threshold}]秒!")else:print(f"函数[{func.__name__}]执行耗时[{elapsed:.6f}]秒,未超时(阈值[{threshold}]秒)")return result # 返回原函数结果return wrapper # 中层返回内层包装函数return decorator # 外层返回中层装饰器函数# 用装饰器装饰函数(正确传递threshold参数) @timeout_warning(threshold=0.5) # 阈值0.5秒 def slow_func():time.sleep(1) # 实际耗时1秒(超时)return "slow task done"@timeout_warning(threshold=2) # 阈值2秒 def fast_func():time.sleep(0.5) # 实际耗时0.5秒(未超时)return "fast task done"# 测试 print(slow_func()) print(fast_func())4.核心实例给累加器添加次数统计
#装饰器函数 def count_accumulate(func):count = 0def decorator(n):nonlocal countcount += 1res = func(n)print(f"累加器已调用{count}次,当前累加值:{res}")return resreturn decorator#原函数 def create_accumulator(init_value):sum_ = init_value@count_accumulatedef add(n:int):nonlocal sum_sum_ += nreturn sum_return add#测试用例 a = create_accumulator(100) b = create_accumulator(0)a(20) #累加器已调用1次,当前累加值:120 b(30) #累加器已调用1次,当前累加值:30
重点理解:关于闭包函数和装饰器直接的关系需要明白以下几点(以上述例题4为例)
1.装饰器本质上就是闭包函数的延申,其本质就是闭包函数,哪个函数需要装饰就需要在该函数前加上@语法糖,就是上文的@count_accumulate,注意:语法糖仅修饰当前的函数,放到父函数前无法修饰子函数。
2.装饰器外参数的说明,装饰器的外层函数中的参数func本质上是传入需要装饰的函数的函数名,如上述例题四中此处的func形参,代表的就是add函数名称,如果需要装饰别的函数则该形参也可以理解为相应的函数名称。
3.装饰器内参数的说明,装饰器本质的闭包函数其外函数返回值为内函数,所以内函数的名称不重要,其内函数的参数值是重点,如例题四中的decorator(n)中的n,他指代的是外层函数func的参数,其本质也是需要装饰的对象的参数,即需装饰的函数add(n:int)中的n等价于装饰器中的内函数的参数。因为此处也是形参所以为了增加兼容性常常使用*args,**kwargs来作为万能形参来使用,本质上是待修饰函数的参数。
4.装饰器内部函数的实现:现在实现装饰器内部函数,其本质是将装饰器外部函数的参数(函数名称)和内层函数中的(参数)两者组合起来共同构建一个通用的func(*args,**kwargs)函数,在装饰器的内层函数中用变量接收,如例4中的res = func(n),然后在此基础上进行进一步装饰,比如说统计次数啊,或者是添加调用耗时啊等,最终装饰器内层函数return res,外层函数return 内层函数名。
5.函数调用实现功能:最终在使用的时候需要按照正常闭包函数的使用规则使用,先将原函数赋值于一个变量,再通过变量(赋值)来进行使用,从而达到正确调用闭包函数和其装饰器的功效
整体思路如此,需要注意如果要用万能参数*args,**kwargs,其返回值是元组,需要args[0]来获取使用的,装饰器中如果外层函数中有定义临时变量则内层函数如果仅调用不改变则直接用就好,如果要修改其值则需要使用nonlocal关键字声明,之后修改才有效。
#带参数的装饰器案例,三层嵌套,如下述例题,仅供参考
''' 1. 使用带参数的函数装饰器,记录 f(x) = x**2 + 1 函数,中 100,200,... 1000 的结果。日志【记录1:每 100 次,调用 f(100) 结果为 10001】'''def log_decorator(n):def middle(func):def inner(*args,**kwargs): # x是输入值(100,200,...,1000)result = func(*args,**kwargs)if args[0]%n == 0:print(f"记录{args[0]//n}:每{n}次,调用{func.__name__}({args[0]})结果为{result}")return resultreturn innerreturn middle@log_decorator(200) #带参数装饰器使用语法糖必须要()
def f(x):# 核心函数:计算x² + 1return x ** 2 + 1# 测试:计算x=100,200,...,1000时的结果(会自动记录日志)
for x in [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]:f(x)
2.文件操作和异常处理
1.文件操作
概念:文件操作主要围绕 “打开 - 操作 - 关闭” 三个步骤,Python 中通过内置的open()函数实现,核心是掌握不同模式、常用方法及上下文管理器的使用。
1.文件的读写权限和操作类型
r:只读模式(默认),文件不存在则报错。w:写入模式,覆盖原有内容,文件不存在则创建。a:追加模式,在文件末尾添加内容,文件不存在则创建。r+/w+/a+:读写模式,区别在于对原有内容的处理和指针初始位置。b:二进制模式(如rb/wb),用于处理图片、视频等非文本文件。2.常用文件对象方法
read(size):读取指定字节数的内容,无参数则读取全部。readline():读取一行内容,包括换行符\n。readlines():读取所有行,返回列表(每行作为一个元素)。write(content):写入内容,文本模式需传入字符串,二进制模式需传入字节流。close():关闭文件,必须执行(否则可能导致数据丢失)
常用的文件读写模板
# 1.使用with管理文件# 读取文件(with自动关闭,无需close())
path = r'C:\Users\Excub\PycharmProjects\PythonProject_1019\10.29\text1.txt'
with open(path, "r", encoding="utf-8") as file:content2 = file.readlines() # 按行读取,返回列表for line in content2: # 遍历每行并去除换行符print("每行内容:", line.strip())
'''
每行内容: 123
每行内容: 456
每行内容: 789
'''#2.写入多行数据# 写入多行内容
with open("test1.txt", "a", encoding="utf-8") as file:lines = ["\n第一行追加", "第二行追加", "第三行追加"]file.writelines(lines) # 批量写入列表中的字符串'''第一行追加第二行追加第三行追加
'''3.二进制文件操作(复制图片)
# 复制一张图片(需提前准备一张名为"source.jpg"的图片)
with open("1.jpg", "rb") as src_file: # 二进制读img_data = src_file.read() # 读取图片字节流with open("2.jpg", "wb") as dst_file: # 二进制写dst_file.write(img_data) # 写入字节流,生成复制图print("图片复制完成!")'''
图片复制完成!
'''
2.异常处理核心知识
概念:用于捕获程序运行中的错误(如文件不存在、除以零等),避免程序直接崩溃,核心是掌握try-except结构及常见异常类型。
1.常见错误类型:
FileNotFoundError:文件不存在时触发(如读取不存在的文件)。IOError:输入输出错误(如磁盘空间不足、权限不够)。ZeroDivisionError:除以零错误。TypeError:类型错误(如将字符串与数字相加)。ValueError:值错误(如int("abc"),类型正确但值无效)。Exception:所有异常的父类,可捕获几乎所有异常(不推荐单独使用,应精准捕获)。2.异常处理结构说明:
try:包裹可能出现异常的代码块。except [异常类型]::捕获指定异常并处理,可多个except捕获不同异常。else:try块无异常时执行(可选)。finally:无论是否有异常,都会执行(常用于释放资源,如关闭文件,可选)。3.主动抛出异常:使用
raise语句主动触发指定异常(如参数不符合要求时)
结合文件操作和异常处理的案例
#案例1:
# 功能:向文件写入数据,若写入失败则提示并记录错误
def write_to_file(file_path, content):try:with open(file_path, "w", encoding="utf-8") as file:file.write(content)except FileNotFoundError:print(f"错误:路径 '{file_path}' 不存在!")except PermissionError:print(f"错误:无权限写入文件 '{file_path}'!")except Exception as e:# 捕获其他未预料到的异常,用e获取异常信息print(f"写入失败:未知错误 - {str(e)}")else:print(f"数据成功写入文件 '{file_path}'!")finally:# 无论成功与否,都执行(此处可加日志记录等操作)print("文件写入操作已结束\n")# 测试:正常情况
write_to_file("data.txt", "这是测试数据123")
# 测试:无权限路径(如Windows的C盘根目录,Linux的/root)
write_to_file("C:/test.txt", "测试无权限写入")#案例2:
# 功能:计算两个数的除法,若除数为0则主动抛异常
def divide(a, b):if b == 0:# 主动抛出ValueError,附带详细错误信息raise ValueError("除数不能为0,请重新输入!")return a / b# 调用函数并捕获主动抛出的异常
try:result = divide(10, 0)print("结果:", result)
except ValueError as e:print("计算错误:", str(e)) # 输出:计算错误:除数不能为0,请重新输入!
3.开发常用组合案例
# 功能:读取一个文本文件,统计文件的行数、单词数(简易统计),并处理可能的异常
def count_file_info(file_path):line_count = 0word_count = 0try:with open(file_path, "r", encoding="utf-8") as file:for line in file: # 按行遍历文件(更节省内存,适合大文件)line_count += 1# 统计每行单词数(按空格分割,去除空字符串)words = [word for word in line.strip().split() if word]word_count += len(words)except FileNotFoundError:return f"错误:文件 '{file_path}' 不存在"except UnicodeDecodeError:return f"错误:文件 '{file_path}' 不是UTF-8编码的文本文件"except Exception as e:return f"未知错误:{str(e)}"else:return f"文件统计结果:\n行数:{line_count}\n单词数:{word_count}"# 测试(使用之前创建的test.txt)
result = count_file_info("test.txt")
print(result)
# 测试不存在的文件
result2 = count_file_info("missing.txt")
print(result2)3.模块(Module)
概念:模块是一个包含 Python 代码(变量、函数、类等)的 .py 文件,用于封装功能,实现代码复用。
主要讲述一下random模块和os模块的使用。random 模块和 os 模块是 Python 中非常实用的内置模块。
1.random 用于生成随机数、随机选择等操作,在游戏、抽样、模拟等场景中高频使用
2.os 模块用于与操作系统交互,处理文件路径、目录操作等,是文件 / 目录管理的核心工具。
3.time 时间模块:返回时间戳以及其他常见时间格式
4.sys模块:主要用于与 Python 解释器交互,提供对解释器环境、命令行参数、标准输入输出等的访问和控制。
5.re模块:主要用于处理正则表达式的核心工具,常用于字符串的匹配,查找,替换等操作
6.json模块:json 模块是处理 JSON 数据的核心工具,用于实现 Python 数据与 JSON 格式的相互转换。
7.csv模块:python处理csv文件就类似于处理excel文件一样
1.random 模块
重点区分:
1.choice 每次只取一个,且可能重复;sample 取多个,且元素不重复。区别在于choices可以取多个key值决定。
2.sample(seq, k) 是取出不放回(无放回抽样):从序列 seq 中随机选择k 个不重复的元素(k 必须小于等于序列长度),最终返回一个包含 k 个独特元素的列表。
1.基础随机数的生成
random.random():生成[0.0, 1.0)之间的浮点数。random.uniform(a, b):生成[a, b]或[b, a]之间的随机浮点数(取决于a和b的大小)2.整数的随机生成
random.randint(a, b):生成[a, b]之间的整数(包含a和b)。3.序列随机操作
random.choice(seq):从非空序列seq中随机选择一个元素。random.choices(seq, weights=None, k=1):从序列中随机选择k个元素(可带权重,允许重复)。random.shuffle(seq):原地打乱序列seq(仅对可变序列有效,如列表)。random.sample(seq, k):从序列中随机选择k个不重复的元素(返回新列表,原序列不变)。4.随机种子
random.seed(x):设置随机种子x(相同种子会生成相同的随机序列,用于复现结果)。
实际案例
import random#案例 1:基础随机数与整数生成# 生成[0.0, 1.0)的浮点数
print("random():", random.random()) # 示例:0.7648237291540083# 生成[1.5, 3.5]的浮点数
print("uniform(1.5, 3.5):", random.uniform(1.5, 3.5)) # 示例:2.89124567321# 生成[1, 10]的整数
print("randint(1, 10):", random.randint(1, 10)) # 示例:7# 从range(0, 20, 2)中随机选一个(即0,2,4,...,18)
print("randrange(0, 20, 2):", random.randrange(0, 20, 2)) # 示例:14#案例 2:序列随机操作(抽奖 / 抽样场景)
import random# 场景1:从列表中随机选1个元素(如抽奖)
participants = ["张三", "李四", "王五", "赵六", "钱七"]
winner = random.choice(participants)
print("抽奖 winner:", winner) # 示例:王五# 场景2:从列表中随机选3个元素(允许重复,如抽奖可重复中奖)
lucky_draw = random.choices(participants, k=3)
print("可重复抽奖结果:", lucky_draw) # 示例:['李四', '张三', '李四']# 场景3:打乱列表(如洗牌)
cards = ["红桃A", "方块K", "黑桃Q", "梅花J"]
random.shuffle(cards) # 原地打乱
print("打乱后的牌:", cards) # 示例:['黑桃Q', '红桃A', '梅花J', '方块K']# 场景4:随机选2个不重复元素(如抽样)
sample = random.sample(participants, k=2)
print("不重复抽样:", sample) # 示例:['赵六', '钱七']#案例 3:固定随机种子
import random# 不设置种子:每次运行结果不同
print("无种子第1次:", random.randint(1, 100)) # 示例:56
print("无种子第2次:", random.randint(1, 100)) # 示例:89# 设置种子后:相同种子会生成相同序列
random.seed(10) # 固定种子为10
print("种子10第1次:", random.randint(1, 100)) # 结果固定为73
print("种子10第2次:", random.randint(1, 100)) # 结果固定为4
random.seed(10) # 重新设置相同种子
print("再次种子10第1次:", random.randint(1, 100)) # 仍为73(复现)
2.os模块
模块作用:可实现路径处理、目录创建 / 删除、文件重命名、环境变量获取等功能,跨平台性强(Windows/Linux/macOS 通用)。
1.路径操作os.path子模块
os.getcwd():获取当前工作目录(Current Working Directory)。os.path.abspath(path):返回path的绝对路径。os.path.join(path1, path2, ...):拼接多个路径(自动处理不同系统的路径分隔符,如/或\)。os.path.dirname(path):获取path的目录部分。os.path.basename(path):获取path的文件名部分。os.path.exists(path):判断path是否存在。os.path.isfile(path)/os.path.isdir(path):判断path是文件还是目录。2.目录操作
os.chdir(path):切换当前工作目录到path。os.listdir(path):返回path目录下的所有文件和子目录(列表形式)。os.mkdir(path):创建单级目录(父目录不存在则报错)。os.makedirs(path):递归创建多级目录(父目录不存在则自动创建)。os.rmdir(path):删除单级空目录(目录非空则报错)。os.removedirs(path):递归删除多级空目录(从子到父,遇到非空目录则停止)。3.文件操作
os.rename(src, dst):重命名文件 / 目录(src改名为dst)。os.remove(path):删除文件(不能删除目录)。
3.time模块
概念:时间模块处理日期,常用time,datetime,calender等,其中datetime模块的功能最全面,常用于日常开发。
常用函数:
1.time.time():获得当前的时间戳,(从 1970-01-01 00:00:00 UTC 到现在的秒数,浮点数)
import time print(time.time()) # 示例:1761802187.58440022.time.localtime([timestamp]),将时间戳转换为本地时间元组
local_time = time.localtime() # 不传入参数则用当前时间戳 print(local_time) ''' time.struct_time(tm_year=2025, tm_mon=10, tm_mday=30, tm_hour=5, tm_min=32, tm_sec=8, tm_wday=3, tm_yday=303, tm_isdst=0) ''' # 元组包含:年、月、日、时、分、秒、周几(0=周一)、年内天数、夏令时标志3.time.strftime(format,[t]:将时间元组格式化为字符串) 常用
格式符:
%Y(年)、%m(月)、%d(日)、%H(时,24 小时制)、%M(分)、%S(秒)# 格式化当前本地时间 print(time.strftime("%Y-%m-%d %H:%M:%S")) # 2025-10-30 15:30:454.time.sleep(secs) :程序休眠秒数
time.sleep(2) # 暂停2秒
datetime 模块详解(重点)
date:处理日期(年、月、日)time:处理时间(时、分、秒、微秒)datetime:同时处理日期和时间(最常用)timedelta:处理时间间隔(用于日期加减)from datetime import datetime, date, time# 获取当前日期时间(最常用) now = datetime.now() print(now) # 2025-10-30 15:35:22.123456# 指定日期时间 dt = datetime(2023, 12, 31, 23, 59, 59) print(dt) # 2023-12-31 23:59:59
strftime与strptimeprint(now.strftime("%Y年%m月%d日 %H:%M:%S")) # 2025年10月30日 15:35:22#strptime(date_string, format):将字符串解析为 datetime 对象 dt_str = "2023-01-01 10:00:00" dt = datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S") print(dt) # 2023-01-01 10:00:00
timedelta类(时间间隔)from datetime import datetime, timedeltanow = datetime.now()# 计算1天后的时间 one_day_later = now + timedelta(days=1) print(one_day_later) # 2025-10-31 15:35:22.123456# 计算3小时30分钟前的时间 past = now - timedelta(hours=3, minutes=30) print(past) # 2025-10-30 12:05:22.123456# 时间差计算(两个datetime相减得到timedelta) delta = one_day_later - now print(delta.days) # 1(天数) print(delta.seconds) # 0(秒数,不足1天的部分)
4.sys模块
常用的sys调用的内置函数
命令行参数 sys.argv获取运行脚本时的命令行参数 解释器信息 sys.version、sys.version_info查看 Python 版本信息 环境与路径 sys.path、sys.platform模块搜索路径、操作系统平台信息 标准流控制 sys.stdin、sys.stdout、sys.stderr标准输入、输出、错误流(替代 input)程序退出 sys.exit()终止程序运行并返回状态码 递归与限制 sys.getrecursionlimit()获取 / 设置递归深度限制
sys.argv 是一个列表,存储运行 Python 脚本时传入的命令行参数
import sys# 打印所有命令行参数
print("脚本名:", sys.argv[0])
print("参数列表:", sys.argv[1:])
# 计算参数个数
print("参数总数:", len(sys.argv) - 1)#案例
python demo.py hello 123 "python sys"#输出
脚本名: demo.py
参数列表: ['hello', '123', 'python sys']
参数总数: 3sys.path 是一个列表,存储 Python 解释器查找模块的路径(导入模块时的搜索顺序)。
sys.platform:返回当前的操作系统win32,linux,darwin
import sysplatform = sys.platform print(f"当前平台:{platform}")常用的程序退出sys.exit([status])
import sysdef check_condition():# 模拟条件检查return Falseif not check_condition():print("条件不满足,程序退出")sys.exit(1) # 异常退出(状态码 1)print("程序正常执行完成") sys.exit(0) # 正常退出(可省略,默认 0)
sys.getsizeof(obj):返回对象占用的内存大小import sys print(sys.getsizeof("hello")) # 54(字符串 "hello" 的内存大小) print(sys.getsizeof([1, 2, 3])) # 88(列表的内存大小)
5.re模块
常用re匹配的字符列表
.匹配任意单个字符(除换行 \n)a.b匹配acb、a1b*前一个字符匹配 0 次或多次 ab*匹配a、ab、abb+前一个字符匹配 1 次或多次 ab+匹配ab、abb?前一个字符匹配 0 次或 1 次(非贪婪) ab?匹配a、ab^匹配字符串开头 ^abc匹配abc123$匹配字符串结尾 abc$匹配123abc[]字符集,匹配其中任意一个字符 [abc]匹配a、b、c[^]否定字符集,匹配不在其中的字符 [^0-9]匹配非数字()分组,提取子串或限定范围 (ab)+匹配abab\d匹配数字(等价于 [0-9])\d{3}匹配 3 位数字\D匹配非数字(等价于 [^0-9])\w匹配字母、数字、下划线( [a-zA-Z0-9_])\w+匹配单词\W匹配非单词字符 \s匹配空白字符(空格、Tab、换行等) \S匹配非空白字符 {n}前一个字符匹配恰好 n 次 a{3}匹配aaa{n,}前一个字符匹配至少 n 次 a{2,}匹配aa、aaa{n,m}前一个字符匹配 n 到 m 次 a{1,3}匹配a、aa、aa
re模块核心函数
re.match(pattern,string):从字符串开头匹配,如果开头不匹配则返回None
import re
result = re.match(r'abc', 'abc123') # 匹配成功
print(result.group()) # 输出:abc(获取匹配结果)result = re.match(r'abc', 'xabc123') # 开头不匹配,返回 Nonere.search(pattern, string):在字符串任意位置匹配第一个符合规则的子串(无需从开头开始)
result = re.search(r'\d+', '年龄:18,身高:175') # 匹配第一个数字
print(result.group()) # 输出:18re.findall(pattern, string):返回字符串中所有符合规则的子串,以列表形式返回。
result = re.findall(r'\d+', '年龄:18,身高:175') # 匹配所有数字
print(result) # 输出:['18', '175']re.sub(pattern, repl, string):替换字符串中符合规则的子串(repl 为替换后的内容)。
# 替换所有数字为 *
result = re.sub(r'\d+', '*', '年龄:18,身高:175')
print(result) # 输出:年龄:*,身高:*re.split(pattern, string):按匹配的规则分割字符串,返回列表。
# 按逗号或空格分割
result = re.split(r'[, ]', 'a,b c,d')
print(result) # 输出:['a', 'b', 'c', 'd']re关键用法细节讲解
1.原始字符串r' ':正则表达式前加r表示原始字符串,避免python转义字符
2.分组提取group():用 () 分组后,可通过 group(n) 提取第 n 个分组内容(group(0) 是整个匹配结果)
result = re.search(r'年龄:(\d+),身高:(\d+)', '年龄:18,身高:175')
print(result.group(1)) # 18(第一个分组)
print(result.group(2)) # 175(第二个分组)3.贪婪与非贪婪模式
- 贪婪(默认):尽可能匹配最长的子串(如
.*会匹配到最后)。 - 非贪婪:加
?表示尽可能短(如.*?)。
# 贪婪模式(默认)
print(re.search(r'<.*>', '<a>b<c>').group()) # 输出:<a>b<c>(匹配到最后)
# 非贪婪模式(加 ?)
print(re.search(r'<.*?>', '<a>b<c>').group()) # 输出:<a>(匹配最短)re 模块核心是 “规则匹配”,重点掌握:
- 常用元字符(
\d、*、+、[]、()等)。 - 四大函数:
match(开头匹配)、search(任意位置匹配)、findall(全匹配)、sub(替换)。 - 分组提取和非贪婪模式的使用。
6.json模块
JSON与Python数据类型的对应关系如下
JSON 类型 Python 类型 对象( {})字典( dict)数组( [])列表( list)字符串( "")字符串( str)数字(整数) 整数( int)数字(浮点数) 浮点数( float)trueTruefalseFalsenullNone
序列化:Python ->Json (json.dumps())
import json# Python 字典
data = {"name": "Alice","age": 25,"is_student": False,"hobbies": ["reading", "coding"],"address": None
}# 转换为 JSON 字符串
json_str = json.dumps(data)
print(json_str)
# 输出:{"name": "Alice", "age": 25, "is_student": false, "hobbies": ["reading", "coding"], "address": null}常用的参数:indent 和ensure_ascii
indent:格式化输出(指定缩进空格数,便于阅读)print(json.dumps(data, indent=2)) # 缩进2个空格,格式化显示
ensure_ascii:默认True(非 ASCII 字符转义),设为False保留原字符data = {"name": "张三"} print(json.dumps(data, ensure_ascii=False)) # 输出:{"name": "张三"}
反序列化:JSON ->Python (json.loads())
import jsonjson_str = '''
{"name": "Bob","age": 30,"scores": [90.5, 88, 95]
}
'''# 转换为 Python 字典
data = json.loads(json_str)
print(data["name"]) # 输出:Bob
print(data["scores"][0]) # 输出:90.5(类型为 float)文件操作:json.dump() 和 json.load()
# 1.写入json文件 json.dump()data = {"name": "Charlie", "age": 28}
with open("data.json", "w", encoding="utf-8") as f:json.dump(data, f, indent=2, ensure_ascii=False) # 直接写入文件#2.读取JSON文件 json.load()with open("data.json", "r", encoding="utf-8") as f:data = json.load(f) # 直接从文件读取并转换为 Python 数据
print(data["name"]) # 输出:Charlie注意事项:
1.如 tuple(元组)、set(集合)、自定义类等,序列化时会报错。需先转换为支持的类型(如元组转列表)
data = (1, 2, 3) # 元组
print(json.dumps(list(data))) # 转为列表后序列化:[1, 2, 3]2.解析错误:会抛出 json.JSONDecodeError
try:json.loads('{"name": "Alice", age: 25}') # 错误:age 未加引号
except json.JSONDecodeError as e:print("解析错误:", e)7.csv模块
1.常见的csv读取方式
import csv# 读取 CSV 文件 with open("data.csv", "r", encoding="utf-8") as f:reader = csv.reader(f) # 创建 reader 对象header = next(reader) # 获取表头(第一行)print("表头:", header) # 输出:['name', 'age', 'city']# 遍历数据行for row in reader:print(f"姓名:{row[0]},年龄:{row[1]},城市:{row[2]}")2.写入csv文件方式
import csvdata = [["name", "age", "city"], # 表头["Charlie", 35, "Paris"],["Diana", 28, "Tokyo"] ]# 写入 CSV 文件 with open("output.csv", "w", encoding="utf-8", newline="") as f:writer = csv.writer(f) # 创建 writer 对象writer.writerows(data) # 写入所有行(也可用 writerow() 单行写入)
- 注意:
newline=""避免 Windows 系统写入时产生空行。3.字典的读取方式
1.csv.DictReader 读文件:with open("data.csv", "r", encoding="utf-8") as f:reader = csv.DictReader(f) # 按字典格式读取for row in reader:# 用表头作为键获取值print(f"姓名:{row['name']},城市:{row['city']}")4.字典的写入方式
1.csv.DictWriter 写文件:# 定义表头 headers = ["name", "age", "city"] data = [{"name": "Eve", "age": 22, "city": "Sydney"},{"name": "Frank", "age": 40, "city": "Berlin"} ]with open("dict_output.csv", "w", encoding="utf-8", newline="") as f:writer = csv.DictWriter(f, fieldnames=headers) # 指定表头writer.writeheader() # 写入表头writer.writerows(data) # 写入数据行
4.包(Package)
概念:包是包含多个模块的目录,用于组织多个相关模块(类似文件夹),必须包含 __init__.py 文件(Python 3.3+ 可省略,但建议保留以明确标识为包)。
常规包的格式:
mypackage/ # 包目录 ├── __init__.py # 包初始化文件(可空,或定义包的公共接口) ├── module1.py # 子模块1 ├── module2.py # 子模块2 └── subpackage/ # 子包├── __init__.py└── module3.py # 子包的子模块包中的__init__.py的作用
1.表示该目录为Python包
2.控制包的导入行为(定义__all__变量指定for package import *时导入的模块)
3.执行包初始化代码(设置版本号、加载配置)
# mypackage/__init__.py __version__ = "1.0.0" # 定义包版本# 限制 from mypackage import * 时导入的模块 __all__ = ["module1", "module2"] # 仅导入这两个模块# 自动导入常用模块(简化用户使用) from . import module1
1.包的导入方式
# 导入包中的模块
import mypackage.module1
mypackage.module1.func1()# 导入模块并自定义别名
from mypackage import module2 as m2
m2.func2()# 导入子包中的模块
from mypackage.subpackage import module3
module3.func3()# 通过 __init__.py 简化导入(推荐)
# 在 mypackage/__init__.py 中定义:from . import module1
import mypackage
mypackage.module1.func1() # 直接通过包名访问模块5.小结:
该部分知识比较多且有些杂乱无章,很难全部记住各模块的使用和具体参数作用,建议先记个大概,等真正项目需要用的时候,再参考本文总结的知识点和相应的例子进一步解决问题,本文仅笔者在一周左右的学习中总结出来的一些知识点,仅供大家参考,如果有地方出错和描述不对的地方,希望大家能够不吝赐教!!!万分感谢!
