Python函数从入门到实战_CSDN博客
Python 函数从入门到实战 —— 完整学习笔记
📅 学习周期:2025年5月11日 - 5月18日
🏷️ 标签:Python、函数、lambda、闭包、递归、数据处理
📝 本文整理自学习笔记,涵盖 Python 函数的核心知识点与实战练习
📑 目录
- 一、函数基础与参数传递
- 二、浅拷贝与深拷贝
- 三、函数说明文档
- 四、函数返回值
- 五、函数的嵌套调用
- 六、闭包
- 七、函数作用域
- 八、global 与 nonlocal 关键字
- 九、递归函数
- 十、匿名函数(lambda)
- 十一、实战练习与批改
- 十二、总结速查表
一、函数基础与参数传递
Python 函数的参数传递方式非常灵活,共有 7 种传参方式:
1.1 位置参数
根据形参与实参的先后位置一一匹配,调用时数量必须保持一致。
def func(a, b, c):
print(a, b, c)
func(1, 2, 3) # 输出: 1 2 3
1.2 关键字传参
通过关键字参数确定每个变量传入的值,顺序可以随意。
def func2(name, age):
print(name, age)
func2(name='张三', age=18) # 输出: 张三 18
func2(age='19', name='ls') # 输出: ls 19
1.3 默认值传参
形式参数自带默认值。如果实参传参则覆盖默认值。
⚠️ 注意:非默认值参数必须在默认值参数之前,目的是减少歧义。
def func3(name, age=18):
print(name, age)
func3(name='zs', age=19) # 输出: zs 19(覆盖默认值)
1.4 不定长传参(*args)
格式:*变量名。加了 * 的参数会以 元组 的形式导入。
⚠️ 不定长参数的后面必须使用关键字传参,否则参数会被不定长参数截取。
def func4(name, *age, sex):
print(name, age, sex)
func4('zs', 1, 2, 3, sex='男')
# 输出: zs (1, 2, 3) 男
1.5 可变长参数(**kwargs)
格式:**变量名。加了 ** 的参数会以 字典 的形式导入。
⚠️ 可变长参数后不能再有参数传参。
def func5(**kwargs):
print(kwargs)
func5(a=1, b=2, c=3) # 输出: {'a': 1, 'b': 2, 'c': 3}
1.6 解包传参
- 元组使用
*解包:解包后实参与形参数量一致,底层通过位置参数传参 - 字典使用
**解包:形参中的 key 要与解包后参数名一致,底层通过关键字传参
def func5(a, b, c):
print(a, b, c)
tuple_f = (1, 2, 3)
func5(*tuple_f) # 解包元组
dict_f = {'a': 1, 'b': 2, 'c': 3}
func5(**dict_f) # 解包字典
🔍 **d 字典拆包详解
**d 就像把一个箱子里的东西全部倒出来:
d = {'apple': 2, 'banana': 1}
# ✅ 用 **d 拆包,合并字典
new_dict = {**d, 'cherry': 3}
print(new_dict)
# {'apple': 2, 'banana': 1, 'cherry': 3}
1.7 强制使用位置参数或关键字参数
/前的参数必须使用位置参数*后的参数必须使用关键字传参
def func7(a, b, /, c, d, e, f, *, g, h):
print(a, b, c, d, e, f, g, h)
func7(1, 2, 3, 4, 5, 6, g=7, h=8)
func7(1, 2, c=3, d=4, e=5, f=6, g=7, h=8)
二、浅拷贝与深拷贝
2.1 浅拷贝(copy)
拷贝父对象,不会拷贝对象内部的子对象,拷贝后只有第一层是独立的。
def func1(list_fun):
list_fun.append(7)
if __name__ == '__main__':
list1 = [1, 2, 3, 4, 5, 6]
list2 = list1.copy() # 浅拷贝
func1(list2)
print(list1) # [1, 2, 3, 4, 5, 6] — 原列表不受影响
2.2 深拷贝(deepcopy)
完全拷贝父对象及其子对象,拷贝后所有层都是独立的。
import copy
def func1(list_fun):
list_fun[3].append(7)
if __name__ == '__main__':
list1 = [1, 2, 3, [4, 5, 6]]
list2 = copy.deepcopy(list1) # 深拷贝
func1(list2)
print(list1) # [1, 2, 3, [4, 5, 6]] — 原列表完全不受影响
2.3 底层原理
| 类型 | 内层嵌套列表地址 | 修改内层是否影响原列表 |
|---|---|---|
| 浅拷贝 | 与源列表一致 | ✅ 会影响 |
| 深拷贝 | 单独创建新空间 | ❌ 不影响 |
三、函数说明文档
通过 help(函数名) 可以获取函数说明文档。
def adult(age):
'''
根据年龄判断是否成年
:param age: 年龄
:return: True 成年 / False 未成年
'''
if age >= 18:
return True
else:
return False
if __name__ == '__main__':
help(adult) # 查看说明文档
print(adult(18)) # True
四、函数返回值
在函数中使用 return 关键字可以返回结果并结束正在执行的函数。
# 1) 不带表达式的 return → 返回 None
def func1():
return
# 2) 没有 return 语句 → 返回 None
def func2():
pass
# 3) 使用变量接收返回值
def func3(list1):
sum_list = 0
for i in list1:
sum_list += i
return sum_list
if __name__ == '__main__':
result = func3([1, 2, 3])
print(result) # 6
五、函数的嵌套调用
在一个函数中调用另一个函数,内层函数执行完后才继续执行外层函数。底层原理是栈的先进后出。
def func1():
print("在func1函数中执行")
func2()
def func2():
print("在func2函数中执行")
if __name__ == '__main__':
func1()
# 输出:
# 在func1函数中执行
# 在func2函数中执行
调用过程:
func1()进栈执行func2()进栈执行func2()结束出栈func1()结束出栈
六、闭包
6.1 什么是闭包?
闭包允许内部函数访问外部函数的变量,即使外部函数已经执行完毕。
6.2 闭包的三个必要条件
- 在函数中定义另一个函数
- 外层函数的返回值是内层函数对象
- 在内层函数访问了外层函数定义的变量
def fun1():
a = 10
def fun2():
print(a)
return a
return fun2
if __name__ == '__main__':
print(fun1()()) # 10 10
6.3 闭包原理
a 的生命周期被延长——当内部函数 fun2 什么时候释放,a 就什么时候释放。
七、函数作用域
Python 有 4 种作用域,查找顺序为 L → E → G → B:
| 作用域 | 含义 | 说明 |
|---|---|---|
| L (Local) | 局部作用域 | 函数内部 |
| E (Enclosing) | 嵌套作用域 | 闭包函数外的函数中 |
| G (Global) | 全局作用域 | 模块级别 |
| B (Built-in) | 内建作用域 | Python 内置 |
⚠️ Python 中只有模块、类、函数才会引入新的作用域。
a = 30
def fun1():
# a = 10
def fun2():
# a = 20
print(a) # 从 E → G 找到 a = 30
return fun2
if __name__ == '__main__':
fun1()() # 30
八、global 与 nonlocal 关键字
8.1 global —— 修改全局变量
在函数内部给变量赋值时,Python 默认把它当局部变量。要修改全局变量需用 global 声明。
var1 = 100
def fun1():
global var1
var1 += 100
print(var1)
if __name__ == '__main__':
print(var1) # 100
fun1() # 200
print(var1) # 200(全局变量被修改)
修改可变类型
全局变量为可变类型时,函数不需要 global 也可以修改:
list_1 = [11, 22, 33]
def fun1():
global list_1
list_1[:] = [44, 55, 66] # 切片赋值修改原列表
if __name__ == '__main__':
fun1()
print(list_1) # [44, 55, 66]
8.2 nonlocal —— 修改嵌套作用域变量
nonlocal 用于内部作用域修改外部(嵌套/闭包)作用域的变量。
def fun1():
a = 10
print(a) # 10
def fun2():
nonlocal a
a = 20
print(a) # 20
fun2()
print(a) # 20(被修改了)
if __name__ == '__main__':
fun1()
九、递归函数
9.1 递归的本质
函数自己调用自己,必须有终止条件。
9.2 示例:求阶乘
def factorial(n):
if n == 1 or n == 0:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
9.3 示例:递归求和
def recursive_sum(n):
if n == 1:
return 1
return n + recursive_sum(n - 1)
print(recursive_sum(10)) # 55
9.4 示例:递归反转字符串
def reverse_string(s):
if len(s) <= 1:
return s
return s[-1] + reverse_string(s[:-1])
print(reverse_string("hello")) # "olleh"
十、匿名函数(lambda)
10.1 基本语法
lambda 参数1, 参数2, ...: 表达式(返回值)
lambda 自带 return,不需要也不能写 return。
square = lambda x: x ** 2
print(square(5)) # 25
add = lambda a, b: a + b
print(add(1, 2)) # 3
10.2 普通函数 vs 匿名函数
# 普通函数 # 匿名函数
def square(x): square = lambda x: x ** 2
return x ** 2
def add(a, b): add = lambda a, b: a + b
return a + b
10.3 lambda 与内置函数搭配
搭配一:filter() — 过滤
从可迭代对象中筛选出满足条件的元素。
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 筛选偶数
res = filter(lambda x: x % 2 == 0, numbers)
print(list(res)) # [2, 4, 6, 8, 10]
搭配二:map() — 映射(批量处理)
对每个元素执行相同操作。
numbers = [1, 2, 3, 4, 5]
# 每个数求平方
res = map(lambda x: x ** 2, numbers)
print(list(res)) # [1, 4, 9, 16, 25]
# 判断奇偶
res = map(lambda x: "偶数" if x % 2 == 0 else '奇数', numbers)
print(list(res)) # ['奇数', '偶数', '奇数', '偶数', '奇数']
搭配三:sorted() — 自定义排序
words = ['python', 'c', 'java', 'go']
res = sorted(words, key=lambda x: len(x))
print(res) # ['c', 'go', 'java', 'python']
students = [
{'name': '小明', 'age': 20},
{'name': '小红', 'age': 18},
{'name': '小刚', 'age': 25}
]
res = sorted(students, key=lambda x: x['age'])
print(res) # 按年龄升序
搭配四:max() / min() — 找最值
students = [
{'name': '小明', 'score': 90},
{'name': '小红', 'score': 75},
{'name': '小刚', 'score': 95}
]
best = max(students, key=lambda x: x['score'])
print(best) # {'name': '小刚', 'score': 95}
10.4 搭配 reduce() — 累计算
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# 求乘积
print(reduce(lambda x, y: x * y, numbers)) # 120
# 求和
print(reduce(lambda x, y: x + y, numbers)) # 15
# 求最大值
print(reduce(lambda x, y: x if x > y else y, numbers)) # 5
10.5 lambda 速查表
| 搭配函数 | 用途 | 示例 |
|---|---|---|
filter() | 过滤 | filter(lambda x: x > 0, lst) |
map() | 批量处理 | map(lambda x: x**2, lst) |
sorted() | 自定义排序 | sorted(lst, key=lambda x: x['age']) |
max() | 找最大 | max(lst, key=lambda x: x['score']) |
min() | 找最小 | min(lst, key=lambda x: x['score']) |
reduce() | 累计算 | reduce(lambda x, y: x*y, lst) |
💡 一句话记忆:lambda 就是"临时小函数",哪里需要一行逻辑,就地写一个,用完即丢。
十一、实战练习与批改
练习 1:filter + map + sorted 链式调用
scores = [45, 82, 55, 90, 38, 76, 61, 99, 48, 70]
# 筛选及格 → 加5分(不超过100)→ 从高到低排序
result = list(sorted(
map(lambda x: 100 if x + 5 > 100 else x + 5,
filter(lambda x: x >= 60, scores)),
reverse=True
))
print(result) # [100, 95, 87, 81, 76, 71]
练习 2:数据清洗
data = [
{'name': ' Alice ', 'age': 25, 'city': '北京'},
{'name': ' Bob ', 'age': -1, 'city': ''},
{'name': ' Charlie ', 'age': 30, 'city': '上海'},
{'name': ' David ', 'age': 0, 'city': '广州'},
{'name': ' Eve ', 'age': 22, 'city': ''}
]
# 1. 去掉 name 前后空格(返回完整字典)
cleaned = map(lambda x: {'name': x['name'].strip(), 'age': x['age'], 'city': x['city']}, data)
# 2. 过滤 age <= 0
cleaned = filter(lambda x: x['age'] > 0, cleaned)
# 3. 过滤 city 为空
cleaned = filter(lambda x: x['city'] != '', cleaned)
# 4. 按 age 排序
result = sorted(cleaned, key=lambda x: x['age'])
print(list(result))
⚠️ 易错点:
map中要返回完整字典,不能只取一个字段,否则会丢失其他数据。
练习 3:reduce 统计词频
from functools import reduce
text = "apple banana apple cherry banana apple date cherry banana apple"
words = text.split()
word_count = reduce(
lambda d, word: {**d, word: d.get(word, 0) + 1},
words,
{}
)
print(word_count)
# {'apple': 4, 'banana': 3, 'cherry': 2, 'date': 1}
逐步拆解:
初始值:d = {}
第1步:word='apple' → d中没有apple → d={'apple': 1}
第2步:word='banana' → d中没有banana → d={'apple': 1, 'banana': 1}
第3步:word='apple' → d中有apple=1 → d={'apple': 2, 'banana': 1}
...
最终:{'apple': 4, 'banana': 3, 'cherry': 2, 'date': 1}
练习 4:学生成绩管理系统
students = [
{'name': '张三', 'scores': [90, 85, 92]},
{'name': '李四', 'scores': [78, 65, 88]},
{'name': '王五', 'scores': [95, 90, 98]},
{'name': '赵六', 'scores': [60, 72, 55]},
{'name': '钱七', 'scores': [88, 76, 90]},
{'name': '孙八', 'scores': [78, 65, 88]}
]
def get_avg(students):
"""计算每个学生的平均分"""
avg_dict = {}
for student in students:
avg = round(sum(student['scores']) / len(student['scores']), 1)
avg_dict[student['name']] = avg
return avg_dict
def get_ranking(avg_dict):
"""按平均分排名"""
ranking = sorted(avg_dict.items(), key=lambda x: x[1], reverse=True)
for num, (name, score) in enumerate(ranking, start=1):
print(f'第{num}名:{name} {score}分')
return ranking
def get_unique_scores(students):
"""去重成绩"""
all_scores = set()
for student in students:
for score in student['scores']:
all_scores.add(score)
return sorted(list(all_scores), reverse=True)
def get_subject_toppers(students):
"""每科最高分"""
max_score = {}
for student in students:
for num, score in enumerate(student['scores'], start=1):
key = f'第{num}科'
if key not in max_score or score > max_score[key][1]:
max_score[key] = (student['name'], score)
return max_score
def get_pass_rate(students, pass_line=60):
"""及格率统计"""
pass_dict = {}
total_pass = 0
total_subjects = 0
for student in students:
passed = list(filter(lambda x: x >= pass_line, student['scores']))
pass_dict[student['name']] = len(passed)
total_pass += len(passed)
total_subjects += len(student['scores'])
rate = round(total_pass / total_subjects * 100, 1)
return pass_dict, f'{rate}%'
十二、总结速查表
知识点总览
| 序号 | 知识点 | 核心要点 |
|---|---|---|
| 1 | 参数传递 | 位置、关键字、默认值、*args、**kwargs、解包、强制位置/关键字 |
| 2 | 浅拷贝与深拷贝 | copy() 只拷贝第一层;deepcopy() 完全独立 |
| 3 | 函数说明文档 | help(函数名) 查看 |
| 4 | 返回值 | return 返回结果并结束函数;无 return 返回 None |
| 5 | 嵌套调用 | 先进后出的栈机制 |
| 6 | 闭包 | 三个条件:内嵌函数、返回内层、内层访问外层变量 |
| 7 | 作用域 | L → E → G → B 查找顺序 |
| 8 | global/nonlocal | global 修改全局;nonlocal 修改嵌套作用域 |
| 9 | 递归 | 自己调用自己 + 必须有终止条件 |
| 10 | 匿名函数 | lambda + filter/map/sorted/max/min/reduce |
函数设计原则
输入 → 函数处理 → 输出(return)
def 函数名(参数):
局部变量 = ... # 内部创建
... # 不修改原始数据
return 结果 # 用 return 返回
常见易错点
| 错误 | 说明 | 正确做法 |
|---|---|---|
| 修改原始数据 | i['scores'] = ... 把列表改成了数字 | 用临时变量计算 |
| 只用 print 不用 return | 结果拿不到,无法传递给其他函数 | 用 return 返回 |
| 滥用全局变量 | 函数间互相影响 | 函数内部创建局部变量 |
Python 用 null | Python 里不存在 null | 用 None 或 '' |
| filter 条件符号错误 | x > 60 漏掉 60 | x >= 60 |
📌 学习建议:建议完成顺序为 递归基础 → 阶乘 → 字符串递归 → 综合项目,循序渐进地掌握函数编程。
本文整理于 2026年5月20日,如需交流欢迎留言讨论!
更多推荐
所有评论(0)