1-函数定义、参数传递与作用域(LEGB)
1.1 简介
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。
函数代码块以def关键词开头,后接函数标识符名称和圆括号()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号:起始,并且缩进。
return [表达式]结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
1.2 创建与使用
# 1-函数的创建 # 1.1 语法格式: """ (1)定义一个函数 def 函数名(参数1, 参数2, ...): 函数体 return 返回值 (2)调用函数 函数名(参数1, 参数2, ...) """ # 需求:比较两个数的大小 # def 函数定义关键字 # compare 函数名---自定义,必须符合标识符的规则 # (a, b) 形参:局部变量,用于接收实参的值 # return 返回值---作用:1.结束函数的执行 2.将返回值传递给调用函数 def compare(a, b, c): # 函数体---业务逻辑 print("函数执行开始") if a > b: return a elif a < b: return b print("函数执行结束") # 调用函数---将实参传递给函数的形参 # 语法: 函数名(实参1, 实参2, ...) # 实参---实际传递给函数的值,也可以是变量、表达式等任意值 # 注意:实参的个数必须与形参的个数一致 num1 = 100 num2 = 20 max = compare(num1, num2) print(max)1.3 作用域
1.3.1定义:
作用域(scope) 指的是变量可以被访问的有效范围。Python 中主要按以下规则来决定一个变量在哪里能用(即 LEGB 规则):
1.3.2 分类
全局作用域:变量的定义位置在函数外部,作用域范围是整个程序局部作用域:变量的定义位置在函数内部,作用域范围是该函数内部全局变量:在函数外部定义的变量,可以在函数内部使用,也可以在函数外部使用局部变量:在函数内部定义的变量,只能在函数内部使用,不能在函数外部使用
1.4 函数参数的分类
# 函数参数的分类使用 # 分类:必需参数、关键字参数、默认参数、不定长参数 # ======================================== # 1. 必需参数(位置参数) # 调用函数时,实参的个数和顺序必须与形参一一对应 # ======================================== def add(a, b): return a + b # 正确:实参与形参个数、顺序一致 print(add(10, 20)) # print(add(20)) # 错误:实参个数与形参不一致(会报错) # print(add(10)) # ======================================== # 2. 关键字参数 # 调用函数时,通过 "参数名=值" 的形式传参,可以不按形参的顺序 # ======================================== def introduce(name, age): print(f"我叫{name},今年{age}岁") # 位置参数 introduce("小明", 18) # 关键字参数:可以不按顺序 introduce(age=18, name="小明") # ======================================== # 3. 默认参数(缺省参数) # 定义形参时直接赋值,调用函数时可以不给该参数传值 # 注意:默认参数要放在必备参数之后 # ======================================== def info(name, age=18): print(f"我叫{name},默认年龄{age}岁") # info("小红") # name 用实参,age 用默认值 18 info(age=20, name="小红") # 两个都用实参 # # ======================================== # 4. 不定长参数 # 传参个数不固定 # *args 接收任意多个位置参数,打包成一个元组 # **kwargs 接收任意多个关键字参数,打包成一个字典 # ======================================== def sum_all(*args): print(*args, type(args)) print(args[0]) total = 0 for n in args: total += n # return total print(total) sum_all(1, 2, 3) # 6 sum_all(1, 2, 3, 4, 5) # 15 def show_info(*args, age=18, **kwargs): print(args, type(args)) print(kwargs, type(kwargs)) print(age, type(age)) show_info("小明", 2026, age=20, city="北京")2-闭包机制与高级函数应用
2.1 闭包的介绍
核心概念:在一个函数内部再定义一个函数,内层函数用到了外层函数的变量,并且外层函数把内层函数返回出去,这就形成了闭包。
# 闭包函数 # 在一个函数内部再定义一个函数, # 内层函数用到了外层函数的变量, # 并且外层函数把内层函数返回出去, # 这就形成了闭包。 # 外层函数 def add(a, b): print(a, b) # 外层使用了a和b c = 100 # 内层函数 def inner(): # 内层函数用到了外层函数的变量, sum = a + b # 局部变量 return sum # print("内层函数对象inner:", inner) # 内层函数对象 # print("调用内层函数inner(),返回结果:", inner()) # 调用内层函数,返回结果 # 返回内层函数 return inner # 调用 result = add(1, 2) result()2.2 nonlocal与nonlocal的区别
global= 管模块最顶层的变量("我就是要最外面那个")。nonlocal= 管当前函数外层函数的变量("我要改我这个闭包外层的变量")。如果你的场景是闭包(函数套函数,内层要改外层),几乎总是用
nonlocal;只有在内层明确要改模块顶层的全局变量时才用global。
count = 100 # 真正的全局变量(模块顶层) def make_counter(): count = 0 # make_counter 的局部变量 def counter(): global count # 找到模块顶层的 count = 100 count += 1 # 改的是外层那个 100,不是这里的 0 return count return counterdef make_counter(): count = 0 def counter(): nonlocal count # 指向 make_counter 里的 count count += 1 return count return counter2.3 装饰器高级函数
核心概念:装饰器本质就是一个「接收函数、返回新函数」的函数,用于在不修改原函数代码的前提下,为其增加额外功能(如计时、日志、权限校验)。
不修改原函数的代码,只是在原函数的基础上,添加了新的功能。
# 装饰器---不修改原函数的代码,只是在原函数的基础上,添加了新的功能。 # **核心概念**: # 装饰器本质就是一个闭包函数, # 用于在不修改原函数代码的前提下,为其**增加额外功能**(如计时、日志、权限校验)。 # 不修改原函数的代码,只是在原函数的基础上,添加了新的功能。 def my_decorator(func): def wrapper(*args, **kwargs): # 不定长参数,适配任意函数 print("在函数执行前做点事...") result = func(*args, **kwargs) # 调用原函数 print("在函数执行后做点事...") return result # 把原函数的返回值返回出去 return wrapper # 自动语法糖调用装饰器 @装饰器函数---@闭包函数名称 @my_decorator def say_hello(): print("Hello!") @my_decorator def say_goodbye(): print("Goodbye!") @my_decorator def say_Hi(): print("Hi!") say_goodbye()3.模块化、包管理与标准库导入
3.1 模块化
一个.py文件就是一个独立的模块
# mymath.py """我的数学工具模块""" PI = 3.14159 def add(a, b): return a + b class Circle: def __init__(self, r): self.r = r def area(self): return PI * self.r ** 23.2 标准导入
导包的常用方式
1.直接导入模块import---相同包下或者内置模块导入
import mymath print(mymath.add(1, 2))2-from 包名 import 指定内容(变量,函数,类)as 别名 ---导入指定的函数、类、模块等
from mymath import add, Circle print(add(1, 2))3.导入时起别名
import mymath as mm print(mm.add(1, 2))3.3 python包和目录的区别
本质是多了__init__.py文件用来对于python模块的管理
project/ ├── main.py └── utils/ # 这是一个包 ├── __init__.py # 包的标志文件(可以空着) ├── string_tools.py └── file_tools.py# 方式一:完整路径导入 from utils.string_tools import split_words # 方式二:相对导入(只能在包内部使用) # file_tools.py 内部引用同级模块 from .string_tools import split_words4.datetime 模块的使用方式
作用:datetime是 Python 标准库中用于处理日期和时间的核心模块。它提供了面向对象的接口,可以方便地获取、创建、计算和格式化日期时间。
核心类:
| 类名 | 作用 | 示例 |
|---|---|---|
datetime.datetime | 同时包含日期和时间 | 2026-10-31 14:30:00 |
datetime.date | 仅日期 | 2026-10-31 |
datetime.time | 仅时间 | 14:30:00 |
datetime.timedelta | 时间差(用于运算) | 加 3 天、减 2 小时 |
4.1获取当前时间
from datetime import datetime, date, time, timedelta now = datetime.now() # 2026-10-31 14:30:00.123456(本地时间) today = date.today() # 2026-10-31 utc_now = datetime.utcnow() # UTC 时间4.2自定义创建时间
dt = datetime(2026, 10, 31, 14, 30, 0) # 指定年月日时分秒 d = date(2026, 10, 31) # 只指定日期4.3时间运算(加减天数/时长)
dt = datetime(2026, 10, 31) print(dt + timedelta(days=3)) # 2026-11-03 00:00:00 print(dt - timedelta(hours=2)) # 2026-10-30 22:00:00 # 两个时间相减得到时间差 diff = datetime(2026, 11, 5) - datetime(2026, 10, 31) print(diff.days) # 54.4格式化与解析(字符串 ↔ 时间)
dt = datetime.now() # 时间 -> 字符串 s = dt.strftime("%Y-%m-%d %H:%M:%S") # "2026-10-31 14:30:00" # 字符串 -> 时间 parsed = datetime.strptime("2026-10-31", "%Y-%m-%d")实例:
5.shutil方法的基本使用
删除:shutil.retree()
移动:shutil.move()
复制:shutil.copytree()
6.文件I/O与pathlib路径操作
6.1 文件基本操作
打开文件---open(文件路径,打开模式,编码格式)
常用打开模式:r:只读模式,默认值w:写入模式,会覆盖文件内容a:追加模式,不会覆盖文件内容b:二进制模式,用于处理图片、视频等二进制文件+:读写模式,用于读写文件
常用编码格式:utf-8:默认值,用于处理中文gbk: 用于处理中文,不支持处理英文
f = open("文件1", "r", encoding="utf-8") # 读取文件内容 # read() -- 读取文件所有内容 # read(读取字节数) -- 读取指定字节数的内容 text = f.read(2) print(text) # 读取文件内容 # f.read() -- 读取文件所有内容,返回一个字符串 # f.readline() -- 读取文件第一行,返回一个字符串 # f.readlines() -- 读取文件所有行,返回一个列表 # f.read(size) -- 读取指定字节数的内容 # 文件写入操作 # 1-打开文件 # f = open('文件3','w',encoding='utf-8') f = open('文件3', 'a', encoding='utf-8') # 2-写入内容 f.write('hello world') # 3-关闭文件 f.close()示例:
6.2图片文件复制操作
一般使用分块读写,分块读写是指不一次性把整个文件读入内存,而是按固定大小的"块"(chunk)循环读取、写出。它是处理大文件(大图片、视频、日志)的标准做法。
分块读写内存占用恒定(约等于块大小),1GB 图片也只占几 MB,可逐块处理、显示进度、可中断,可分块发送、断点续传,不会出现大文件复制卡顿、无反馈,网络传输超时。
with open('文件1', 'rb') as f1, open('文件2', 'wb') as f2: chunk = f1.read(1024 * 64) while chunk: f2.write(chunk) current_size += len(chunk) chunk = f1.read(1024 * 64) print()6.3 os模块的基本使用
os(Operating System,操作系统)是 Python 内置模块,提供与操作系统交互的接口:操作文件、路径、目录,读取环境变量等。它不依赖第三方库,直接import os即可。
6.3.1 os.path常用操作
import os p = "images/头像.jpg" print(os.path.basename(p)) # 头像.jpg 取末级文件名 print(os.path.dirname(p)) # images 取所在目录 print(os.path.splitext(p)) # ('images/头像', '.jpg') 主名与扩展名分开 print(os.path.exists(p)) # True/False 路径是否存在 print(os.path.isfile(p)) # 是否为文件 print(os.path.isdir("images")) # 是否为目录 # 拼接路径,跨平台会自动用正确的分隔符 new_p = os.path.join("images", "备份", "头像.jpg") print(new_p) # images\备份\头像.jpg (Windows) 或 images/备份/头像.jpg (Linux/Mac)6.3.2 目录与文件操作常用函数
os.mkdir("bak") # 创建单层目录(父目录必须存在) os.makedirs("a/b/c") # 递归创建多层目录 os.listdir("images") # 列出目录下所有文件名 os.remove("头像-复制.jpg") # 删除文件 os.rename("旧名.jpg", "新名.jpg") # 重命名/移动文件 os.getcwd() # 获取当前工作目录(绝对路径) os.chdir("images") # 切换当前工作目录 os.path.getsize("头像.jpg") # 获取文件大小(字节)注意:
不同系统的路径分隔符不同:Windows 用\(反斜杠),Linux/Mac 用/(正斜杠)。手写"images/" + name在 Linux 没问题,在 Windows 上也可运行但不够规范;而os.path.join会自动选择当前系统正确的分隔符,所以跨平台代码比字符串更安全。
7.lambda函数的基本使用
Lambda 函数(匿名函数)是一种简洁的定义小型函数的方式,核心特点是无需 def 关键字、无需函数名、单行表达式。
基本语法:
lambda 参数列表: 表达式
# 普通函数 def add(x, y): return x + y # lambda 等价写法 add = lambda x, y: x + y print(add(3, 5)) # 8:前面是参数(可省,可多个):后面是表达式,自动作为返回值
注意事项
- 只能写表达式,不能写多行语句、
if/else块、for循环。比如lambda x: if x>0: return x是非法的。 - 不要滥用:如果逻辑超过一行/比较复杂,应该用
def定义,可读性更好。 - lambda 本质只是个函数对象,可赋值给变量,也可直接作为参数传入。
8.time模块的基本使用
time是 Python 标准库中用于处理时间与系统时钟的底层模块。核心概念是时间戳(timestamp)——从 1970-01-01 00:00:00(UTC)到现在的秒数。
8.1获取当前时间(时间戳)
import time ts = time.time() # 时间戳(float 秒数) print(ts) # 1779340000.123456 print(type(ts)) # <class 'float'>8.2程序暂停 ——time.sleep(最常用)
import time print("开始") time.sleep(2) # 阻塞 2 秒 print("结束")8.3格式化时间 ——strftime
import time # 先把时间戳转成 struct_time,再格式化 loc = time.localtime() s = time.strftime("%Y-%m-%d %H:%M:%S", loc) print(s) # 2026-10-31 14:30:009.datetime和time模块的区别
| 维度 | datetime模块 | time模块 |
|---|---|---|
| 设计定位 | 面向对象的数据类型,用于表示和计算日期时间 | 底层系统服务,提供函数式的时间接口和转换 |
| 核心形态 | 对象(datetime,date,time,timedelta) | 函数 + 基础数据结构(浮点数时间戳、struct_time元组) |
| 日期运算 | 支持直观的加减运算(如date + timedelta) | 不直接支持日期对象的算术运算,通常需手动换算时间戳 |
| 时区支持 | 原生支持带时区的对象(tzinfo) | 时区信息依赖系统环境,处理相对底层 |
| 独有功能 | 日期组成部分的提取与替换、ISO 日历操作 | sleep()延时、perf_counter()高精度计时 |
如果你需要在程序里表示一个具体的日期、做日期加减、比较两个日期的大小,或者需要处理带时区的跨地域时间,应该用datetime。如果你只是想获取当前时间戳、格式化输出时间字符串、让程序暂停一会儿,或者测量一段代码跑了多久,用time模块更直接。