Python 函数与编程范式
Python 的函数是一等公民——可以赋值给变量、作为参数传递、从其他函数返回。这种设计使 Python 天然支持函数式编程,同时保持面向对象和过程式的灵活性。
函数基础
定义函数
def 函数名(参数列表):
"""文档字符串"""
函数体
def fib(n):
"""输出限定数值内的斐波那契数列"""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a + breturn 语句退出函数并返回值。未显式 return 时返回 None。
参数传递
Python 中一切都是对象。参数传递的行为取决于对象是否可变:
- 不可变对象(int、str、tuple):函数内部重新赋值不影响外部——类似”值传递”
- 可变对象(list、dict、set):函数内部修改会影响外部——类似”引用传递”
def modify(x, lst):
x = x + 1 # 新对象,外部不受影响
lst.append(4) # 原地修改,外部受影响
a = 10
b = [1, 2, 3]
modify(a, b)
# a 还是 10,b 变成了 [1, 2, 3, 4]参数系统
默认值参数
def add(a=0, b=0, c=0):
return a + b + c
add(1, 2) # 3
add(1, 2, 3) # 6可变参数 *args
接收任意数量的位置参数,打包为元组:
def add2(*args):
total = 0
for val in args:
total += val
return total
add2(1, 2, 3) # 6关键字参数 **kwargs
接收任意数量的键值参数,打包为字典:
def add2(**kwargs):
print(kwargs)
add2(name="halo") # {'name': 'halo'}仅限位置参数 /
/ 之前的参数必须按位置传递:
def pos_only_arg(arg, /):
print(arg)
pos_only_arg(1) # 正确
pos_only_arg(arg=1) # TypeError仅限关键字参数 *
* 之后的参数必须按键值传递:
def kwd_only_arg(*, arg):
print(arg)
kwd_only_arg(arg=1) # 正确
kwd_only_arg(1) # TypeError参数顺序
def f(pos_only, /, standard, *, kwd_only):
pass
# 调用示例
f(1, 2, kwd_only=3)
f(1, standard=2, kwd_only=3)作用域:global 与 nonlocal
- 全局变量:函数体外声明,整个程序可见
- 局部变量:函数体内声明,仅函数内部可见
x = 10 # 全局
def func():
y = 5 # 局部
global x
x = 20 # 修改全局
func()
print(x) # 20nonlocal 用于嵌套函数中修改外层(但不是全局)变量:
def outer():
x = 10
def inner():
nonlocal x
x = 20
inner()
print(x) # 20yield 与生成器
包含 yield 的函数是生成器函数——调用时返回迭代器,惰性产生值,省内存:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 取前 10 个斐波那契数
for _, val in zip(range(10), fibonacci()):
print(val)每次 yield 暂停函数并保存状态,下次迭代从暂停处继续。
lambda 匿名函数
单表达式匿名函数,语法糖:
double = lambda x: x * 2
double(5) # 10
# 等价于
def double(x):
return x * 2常用作 map、filter、sorted 的 key 参数。
函数式编程
函数式编程(FP)用数学函数方式构建计算——纯函数、不可变数据、函数组合。
核心工具
map — 对每个元素应用函数:
squared = list(map(lambda x: x**2, [1, 2, 3, 4]))
# [1, 4, 9, 16]filter — 按条件筛选:
evens = list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5]))
# [2, 4]reduce — 累积计算:
from functools import reduce
product = reduce(lambda x, y: x * y, [1, 2, 3, 4])
# 24partial — 固定部分参数:
from functools import partial
def multiply(x, y):
return x * y
double = partial(multiply, 2)
double(4) # 8高阶函数
接受或返回函数的函数:
def greet(type_):
if type_ == 'hello':
return lambda name: "Hello, " + name
return lambda name: "Hi, " + name
greeting = greet('hello')
greeting('Alice') # 'Hello, Alice'纯函数与不可变性
纯函数满足两个条件:
- 相同输入必定产生相同输出
- 没有副作用(不修改外部状态、不 I/O)
# 纯函数
def add(x, y):
return x + y
# 不纯——修改了外部变量
counter = 0
def increment():
global counter
counter += 1
return counterFP 风格中数据是不可变的——不修改原数据,而是产生新副本:
# 错误(FP 视角):原地修改
lst = [1, 2, 3]
lst.append(4)
# 正确:返回新列表
new_lst = lst + [4]装饰器
装饰器在不修改原函数代码的情况下增加功能——本质是接受函数、返回函数的高阶函数。
def my_decorator(func):
def wrapper():
print("调用前")
func()
print("调用后")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
# 调用前
# Hello!
# 调用后带参数的装饰器:
def repeat(num):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(num=4)
def greet(name):
print(f"Hello, {name}")
greet("Alice") # 打印四次装饰器常见用途:日志、计时、权限检查、缓存(functools.lru_cache)。
闭包
闭包是能记住创建时所在作用域变量的函数:
def outer_function(x):
def inner_function(y):
return x + y # inner 记住了 x
return inner_function
closure = outer_function(10)
closure(5) # 15递归
函数调用自身解决更小的问题实例:
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
factorial(5) # 120递归 vs 迭代:
| 维度 | 递归 | 迭代 |
|---|---|---|
| 直观性 | 对树遍历等问题更自然 | 对数组/链表更自然 |
| 内存 | 每次调用占用栈空间 | 通常更省内存 |
| 风险 | 可能栈溢出 | 无栈溢出风险 |
| 效率 | 大量递归不如迭代 | 简单循环更高效 |
Python 默认递归深度限制约 1000,可调整但不推荐。能用迭代时优先迭代。
关联
- 范式: 函数式编程 — FP 核心原则在 Python 中的表达
- 范式: 过程式与声明式 — Python 的声明式编程