python6(函数、封包&解包、命名空间&作用域、高阶函数)
在前文探讨Python数据类型的基础上,今天我们继续学习python的函数、封包&解包、命名空间&作用域、高阶函数;本节将系统性地讲解函数的定义与使用、参数传递机制、命名空间与作用域规则,以及高阶函数等进阶特性。函数是结构化编程的核心构件,合理运用函数能够显著提升代码的模块化程度、可读性与可维护性。
一、 自定义函数
函数是一段组织良好、可重复使用的代码逻辑。定义函数即声明其名称、参数接口及执行体。
-
基本语法:
def 函数名(参数1, 参数2): # 函数体 结果 = 参数1 + 参数2 return 结果 -
函数调用与引用:函数名本身即指向函数对象的引用,可赋值给其他变量,从而实现间接调用。
def plus(num): print(num + 1) plus(1) # 输出 2 func = plus # 函数对象赋值 func(1) # 输出 2 -
无参函数:不依赖外部输入,执行固定逻辑。
-
带参函数:通过参数传递外部数据,决定函数的执行结果。
-
return语句:用于返回函数执行结果。可返回单个值、表达式或多个值(实际以元组形式返回)。若未显式书写return,函数默认返回None。同时,return会立即终止当前函数的执行流程。
二、 文档注释与类型标注
良好的函数应附带清晰的说明信息,便于他人理解与使用。
-
文档注释(docstring):使用三引号字符串写在函数体开头,可通过
函数名.__doc__或help(函数名)查看。def my_abs(x): """返回数值 x 的绝对值。""" return x if x > 0 else -x -
类型标注(Type Hints):Python 3.5+ 支持在函数定义时标注参数和返回值的预期类型,旨在提升代码可读性并辅助IDE进行静态检查,但不会在运行时强制类型约束。
from typing import List def greet(names: List[str]) -> str: return "Hello, " + " ".join(names)
三、 参数传递机制
参数传递是函数调用的核心环节,理解其规则有助于编写健壮的接口。
-
可变对象与不可变对象:
- 传递不可变对象(如
int、str、tuple)时,函数内部对形参的修改不会影响外部实参,因为传递的是值的副本(实际是引用的副本,但因对象不可变,修改会生成新对象)。 - 传递可变对象(如
list、dict)时,函数内部通过形参引用的修改会直接影响外部对象,需谨慎处理。
- 传递不可变对象(如
-
参数分类:
- 必需参数(位置参数):调用时须按定义顺序传入,数量必须匹配。
- 关键字参数:以
形参名=值形式传入,顺序可调换。 - 默认参数:在定义时为形参赋予默认值,调用时可省略。
- 不定长参数:
*args:接收任意数量的位置参数,打包为元组。**kwargs:接收任意数量的关键字参数,打包为字典。
def func(a, b, *args, **kwargs): print(a, b, args, kwargs) func(1, 2, 3, 4, name="Tom", age=18) # 输出: 1 2 (3, 4) {'name': 'Tom', 'age': 18}
-
特殊分隔符
/与*:/之前的参数为仅限位置参数,不能以关键字形式传入。*之后的参数为仅限关键字参数,必须以关键字形式传入。- 此机制有助于强制调用规范,提高接口清晰度。
四、 匿名函数(lambda)
lambda 表达式用于创建简短的匿名函数,通常用于需要一次性简单逻辑的场景,如作为高阶函数的参数。
# 常规函数
def add(x, y):
return x + y
# lambda 等效形式
lambda x, y: x + y
# 作为排序 key 使用
print(sorted([-4, 2, 3], key=lambda x: abs(x))) # 按绝对值排序
五、 封包与解包
-
封包(Packing):Python 自动将多个值组合为元组。
a = 1, 2, 3 # a 为 (1, 2, 3) -
解包(Unpacking):将可迭代对象中的元素分配给多个变量。
- 赋值解包:支持
*收集剩余元素。a, *b, c = (1, 2, 3, 4, 5) print(a, b, c) # 1 [2, 3, 4] 5 - 函数调用解包:
*作用于列表/元组,将其展开为位置参数。**作用于字典,将其展开为关键字参数。
def func(a, b, c): print(a, b, c) my_list = [1, 2, 3] func(*my_list) # 等效于 func(1, 2, 3) my_dict = {'a': 1, 'b': 2, 'c': 3} func(**my_dict) # 等效于 func(a=1, b=2, c=3)
- 赋值解包:支持
六、 命名空间与作用域
命名空间是名称(变量、函数等)到对象的映射。作用域决定了名称在代码中的可访问范围。
-
LEGB 查找顺序:
- Local:函数内部局部作用域。
- Enclosing:外层嵌套函数的作用域(闭包环境)。
- Global:当前模块的全局作用域。
- Built-in:Python 内置名称作用域。
-
global与nonlocal声明:- 在函数内部若需修改全局变量,须使用
global声明。 - 在嵌套函数中若需修改外层函数的变量,须使用
nonlocal声明。
- 在函数内部若需修改全局变量,须使用
P.S.:在函数内对变量进行赋值操作时,Python 默认将其视为局部变量。若在赋值前尝试访问该变量,会引发“引用前赋值”错误。
a = 1 def func(): print(a) # 报错:UnboundLocalError a = 2
七、 常用高阶函数
高阶函数指以函数作为参数或返回值的函数,是函数式编程的重要工具。
-
filter:根据条件筛选可迭代对象中的元素。result = filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5]) print(list(result)) # [2, 4] -
map:对可迭代对象中的每个元素应用同一函数。result = map(lambda x: x**2, [1, 2, 3]) print(list(result)) # [1, 4, 9] -
reduce:对可迭代对象中的元素进行累积操作(Python 3 中位于functools模块)。from functools import reduce result = reduce(lambda x, y: x + y, range(1, 101)) print(result) # 5050
八、 递归函数
递归函数指在函数体内部调用自身。它适用于可分解为相同子问题的场景,如树结构遍历、分治算法等。
-
关键要素:
- 递归边界(终止条件):明确何时停止递归。
- 递归递推(缩小问题规模):将当前问题转化为规模更小的同类问题。
-
注意事项:
- Python 默认递归深度限制为 1000,过深递归会引发
RecursionError。 - 未优化的递归可能包含大量重复计算,可通过记忆化(缓存已计算结果)提升效率。
- 在实际工程中,循环实现通常具有更好的性能和可控性,仅在处理天然递归结构(如文件目录、树形数据)时,递归才显现其表达优势。
- Python 默认递归深度限制为 1000,过深递归会引发
收尾:
以上内容涵盖了Python函数的基础定义到高阶抽象。初学阶段可能对参数传递、作用域规则等感到抽象,建议通过实际编码逐步加深理解。
下图为本文知识点的思维导图(示意):
祝编码顺利。如有疑问,欢迎进一步探讨。
更多推荐


所有评论(0)