Python 函数进阶
Python 函数进阶:从基础定义到闭包与装饰器
函数是 Python 编程的核心构建块。除了基本调用,Python 还提供了默认参数、可变参数、作用域控制、闭包、装饰器、递归等强大特性。本文通过一系列实用示例,系统讲解这些关键概念,助你写出更灵活、可维护的代码。
1. 基础函数定义与调用
def greet(name: str, age: int, gender: str, height: int):
print(f'{name} is {age} years old, gender is {gender}, height is {height}')
greet('Jason', 18, 'female', 100)
greet('Jason', 18, gender='male', height=100) # 关键字参数
- 支持位置参数和关键字参数混合使用;
- 函数默认返回
None(即使没有return)。
✅ 小技巧:使用关键字参数可提升代码可读性,尤其当参数较多时。
2. 函数返回值
def add(a: int, b: int) -> int:
print(f'We got {a} and {b}')
return a + b
print(f'Sum of 5 and 6 is {add(5, 6)}') # 输出: Sum of 5 and 6 is 11
- 使用
return显式返回结果; - 类型提示(如
-> int)有助于静态检查(配合mypy)。
3. 默认参数值
def greet(name: str, age: int, gender: str, height: int, msg='haha'):
print(f'{name} is {age} years old, gender is {gender}, height is {height}')
print(f'I want to say {msg}')
greet('Jason', 18, 'female', 100) # 使用默认 msg
greet('Jason', 18, gender='male', height=100, msg='hello') # 覆盖默认值
⚠️ 注意:默认参数应为不可变对象(如
str,int,None),避免使用[]或{},否则可能引发意外共享状态。
4. 可变参数:*args 与 **kwargs
*args:接收任意数量的位置参数(元组)
def greet(*args):
print(type(args)) # <class 'tuple'>
print(args) # ('jason', 'female', 18, 172)
greet('jason', 'female', 18, 172)
**kwargs:接收任意数量的关键字参数(字典)
def greet2(**kwargs):
print(type(kwargs)) # <class 'dict'>
print(kwargs) # {'name': 'Jason', 'age': 18, 'gender': 'male'}
greet2(name='Jason', age=18, gender='male')
混合使用(顺序很重要!)
def greet3(name, *args, age=18, **kwargs):
print(f'name is {name}, age is {age}')
print('Extra args:', args)
if 'f' in kwargs:
print(kwargs)
print('Gender:', kwargs.get('gender'))
greet3('Jason', 1, 'hello', age=18, gender='male')
📌 参数顺序规则:
def func(pos, *args, default=..., **kwargs)
5. 全局变量与作用域
n = 100
def test():
n = 100 # 创建局部变量 n,不影响全局
n += 1
print(n) # 101
test()
print(n) # 100(全局未变)
def test2():
global n # 声明使用全局变量
n += 1
print(n) # 101
test2()
print(n) # 101(全局被修改)
✅ 修改全局变量必须使用
global声明。
6. 递归:函数调用自身
基础递归(打印问候语)
def welcome(n):
if n == 0:
return
print('你好啊')
welcome(n - 1)
welcome(5) # 打印 5 次
递归计算阶乘
def compute(n):
if n == 1:
return 1
return n * compute(n - 1)
print(compute(5)) # 120
⚠️ 递归需有明确的终止条件,否则会导致栈溢出。
7. 递归优化:尾递归风格(模拟)
虽然 Python 不优化尾递归,但可通过累积参数改善可读性:
def fac(n, m=1):
"""计算 n!,m 为累积结果"""
if n == 1:
return m
return fac(n - 1, n * m)
print(fac(3)) # 6
print(fac(4)) # 24
print(fac(5)) # 120
8. 闭包(Closure)
闭包指内部函数引用外部函数变量,即使外部函数已执行完毕:
def count(n: list):
def add(m):
n.append(m)
return n
return add
f_add = count([])
res = f_add(6) # [6]
res = f_add(6) # [6, 6]
print(res) # [6, 6, 6, 6, 6]
add函数“捕获”了外部变量n;- 即使
count()已返回,n仍可通过f_add访问和修改。
🔒 闭包常用于实现状态保持、工厂函数、装饰器等。
9. 装饰器(Decorator)
装饰器用于增强函数功能而不修改其源码:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("pre")
res = func(*args, **kwargs)
print("post")
return res
return wrapper
@my_decorator
def add(n, m):
return f'hello, {n + m}'
res = add(4, 5)
print(res)
# 输出:
# pre
# post
# hello, 9
@my_decorator等价于add = my_decorator(add);- 装饰器本质是高阶函数 + 闭包。
10. for-else 结构
for 循环可搭配 else,仅在未被 break 中断时执行:
def is_sushu(n):
for i in range(2, n):
if n % i == 0:
return False
else:
return True # 注意:此处 else 属于 for,不是 if!
print(is_sushu(3)) # True
💡 更典型用法:
for item in items: if found(item): break else: print("Not found!")
11. 深拷贝 vs 浅拷贝
浅拷贝(list.copy())只复制顶层引用
list1 = [1, 2, 3, [3, 4]]
list2 = list1.copy()
list2[-1][-1] = 9
print(list1) # [1, 2, 3, [3, 9]] ← 内部列表也被修改!
深拷贝(copy.deepcopy)递归复制所有层级
import copy
list3 = copy.deepcopy(list1)
list3[-1][-1] = 10
print(list1) # [1, 2, 3, [3, 9]] ← 不受影响
print(list3) # [1, 2, 3, [3, 10]]
✅ 规则:
- 若对象包含可变子对象(如 list、dict),需用
deepcopy;- 否则
copy()或切片[:]足够。
总结:函数核心特性速查表
| 特性 | 关键语法 | 用途 |
|---|---|---|
| 默认参数 | def f(a, b=10): |
提供常用默认值 |
| 可变参数 | *args, **kwargs |
接收任意参数 |
| 作用域 | global |
修改全局变量 |
| 递归 | func(...) 调用自身 |
解决分治问题(如阶乘、树遍历) |
| 闭包 | 内部函数引用外部变量 | 保持状态、延迟计算 |
| 装饰器 | @decorator |
增强函数(日志、权限、缓存等) |
for-else |
for ...: ... else: ... |
处理“未找到”场景 |
| 深拷贝 | copy.deepcopy(obj) |
完全独立复制嵌套对象 |
🐍 编程哲学:
“Simple is better than complex.” —— 《The Zen of Python》
合理使用这些特性,让代码既强大又简洁。
希望这篇系统梳理能帮助你深入理解 Python 函数的高级用法!欢迎动手实践每个示例,并尝试组合不同特性(如“带装饰器的递归函数”)来加深理解。
本文由mdnice多平台发布
欢迎转载,不必注明出处

浙公网安备 33010602011771号