前置知识: Python

函数详解

6 minIntermediate

函数定义、参数类型、lambda 表达式与高阶函数。

1. 函数基本语法 (Basic Syntax)

函数是封装逻辑的可重用代码块,用于组织和简化代码。

1.1 定义与调用 (Definition & Invocation)

 # 基本函数定义
 def greet(name, msg="Hello"):
  """
  函数文档字符串 | Docstring
  Args:
  name (str): 用户名
  msg (str): 问候消息,默认为 "Hello"
  Returns:
  str: 格式化的问候消息
  """
  return f"{msg}, {name}!"
 # 调用函数
 print(greet("Alice")) # 输出: Hello, Alice!
 print(greet("Bob", "Hi")) # 输出: Hi, Bob!
 # 无返回值的函数
 def print_message(message):
  """打印消息"""
  print(f"Message: {message}")
 print_message("Hello, World!") # 输出: Message: Hello, World!
 # 多返回值函数
 def get_user_info():
  """返回用户信息"""
  name = "Alice"
  age = 30
  city = "New York"
  return name, age, city # 返回元组
 user_name, user_age, user_city = get_user_info()
 print(f"Name: {user_name}, Age: {user_age}, City: {user_city}")
 # 空函数
 def placeholder():
  """占位函数"""
  pass # 空语句

1.2 参数传递 (Parameter Passing)

Python 中采用引用传递 (Pass by Object Reference) 的方式传递参数:

  • 不可变对象 (int, str, tuple): 修改形参不会影响实参
  • 可变对象 (list, dict, set): 修改形参的内容会影响实参
 # 不可变对象示例
 def modify_immutable(x):
  x = x + 1
  print(f"Inside function: x = {x}")
 num = 10
 modify_immutable(num)
 print(f"Outside function: num = {num}") # 输出: 10(实参未改变)
 # 可变对象示例
 def modify_mutable(lst):
  lst.append(4)
  print(f"Inside function: lst = {lst}")
 my_list = [1, 2, 3]
 modify_mutable(my_list)
 print(f"Outside function: my_list = {my_list}") # 输出: [1, 2, 3, 4](实参被修改)
 # 重新绑定可变对象
 def rebind_mutable(lst):
  lst = [4, 5, 6] # 重新绑定局部变量
  print(f"Inside function: lst = {lst}")
 my_list = [1, 2, 3]
 rebind_mutable(my_list)
 print(f"Outside function: my_list = {my_list}") # 输出: [1, 2, 3](实参未改变)

2. 参数型 (Parameter Types)

Python 支持多种型的函数参数:

2.1 位置参数 (Positional Parameters)

位置参数是最基本的参数型,必须按顺序传递:

 def add(a, b):
  return a + b
 print(add(3, 5)) # 输出: 8
 # print(add(3)) # 错误: 缺少位置参数 b

2.2 关键字参数 (Keyword Parameters)

关键字参数允许通过参数名指定值,顺序可以任意:

 def greet(name, age):
  return f"Hello, {name}! You are {age} years old."
 print(greet(name="Alice", age=30)) # 输出: Hello, Alice! You are 30 years old.
 print(greet(age=25, name="Bob")) # 输出: Hello, Bob! You are 25 years old.

2.3 默认参数 (Default Parameters)

默认参数为参数提供默认值,当调用时未提供该参数时使用:

 def greet(name, msg="Hello", age=None):
  if age:
  return f"{msg}, {name}! You are {age} years old."
  return f"{msg}, {name}!"
 print(greet("Alice")) # 输出: Hello, Alice!
 print(greet("Bob", "Hi")) # 输出: Hi, Bob!
 print(greet("Charlie", age=25)) # 输出: Hello, Charlie! You are 25 years old.
 # 陷阱: 不要使用可变对象作为默认参数
 def add_item(item, items=[]): # 危险:默认参数在函数定义时只计算一次
  items.append(item)
  return items
 print(add_item(1)) # 输出: [1]
 print(add_item(2)) # 输出: [1, 2](意外:使用了同一个列表)
 # 正确的做法
 def add_item_safe(item, items=None):
  if items is None:
  items = []
  items.append(item)
  return items
 print(add_item_safe(1)) # 输出: [1]
 print(add_item_safe(2)) # 输出: [2](正确:每次创建新列表)

2.4 可变参数 (*args)

可变参数允许接收任意数量的位置参数,会将这些参数打包成一个元组:

 def sum_numbers(*args):
  """计算任意数量数字的和"""
  total = 0
  for num in args:
  total += num
  return total
 print(sum_numbers(1, 2, 3)) # 输出: 6
 print(sum_numbers(1, 2, 3, 4, 5)) # 输出: 15
 print(sum_numbers()) # 输出: 0
 # 解包序列作为可变参数
 numbers = [1, 2, 3, 4, 5]
 print(sum_numbers(*numbers)) # 输出: 15

2.5 关键字可变参数 (**kwargs)

关键字可变参数允许接收任意数量的关键字参数,会将这些参数打包成一个字典:

 def print_person(**kwargs):
  """打印人物信息"""
  for key, value in kwargs.items():
  print(f"{key}: {value}")
 print_person(name="Alice", age=30, city="New York")
 # 输出:
 # name: Alice
 # age: 30
 # city: New York
 # 解包字典作为关键字可变参数
 person_info = {"name": "Bob", "age": 25, "city": "London"}
 print_person(**person_info)

2.6 混合使用不同型的参数

参数定义的顺序必须是:位置参数 → 默认参数 → 可变参数 → 关键字可变参数

 def mixed_params(a, b, c=10, *args, **kwargs):
  print(f"a: {a}, b: {b}, c: {c}")
  print(f"args: {args}")
  print(f"kwargs: {kwargs}")
 mixed_params(1, 2, 3, 4, 5, 6, name="Alice", age=30)
 # 输出:
 # a: 1, b: 2, c: 3
 # args: (4, 5, 6)
 # kwargs: {'name': 'Alice', 'age': 30}

3. 匿名函数 (Lambda)

Lambda 函数是一种小型的匿名函数,使用 lambda 关键字定义:

3.1 基本语法

 # 基本语法: lambda arguments: expression
 add = lambda x, y: x + y
 print(add(5, 5)) # 输出: 10
 # 无参数
 greet = lambda: "Hello, World!"
 print(greet()) # 输出: Hello, World!
 # 单个参数
 square = lambda x: x ** 2
 print(square(4)) # 输出: 16
 # 多个参数
 max_num = lambda x, y: x if x > y else y
 print(max_num(10, 20)) # 输出: 20

3.2 Lambda 函数的应用场景

Lambda 函数常用于需要简短函数的场景,如作为高阶函数的参数:

 # 与 map() 结合
 numbers = [1, 2, 3, 4, 5]
 squared = list(map(lambda x: x ** 2, numbers))
 print(squared) # 输出: [1, 4, 9, 16, 25]
 # 与 filter() 结合
 even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
 print(even_numbers) # 输出: [2, 4]
 # 与 sorted() 结合
 students = [
  {"name": "Alice", "grade": 85},
  {"name": "Bob", "grade": 92},
  {"name": "Charlie", "grade": 78}
 ]
 # 按分数排序
 sorted_by_grade = sorted(students, key=lambda student: student["grade"], reverse=True)
 print(sorted_by_grade)
 # 与 reduce() 结合
 from functools import reduce
 product = reduce(lambda x, y: x * y, numbers)
 print(product) # 输出: 120
 # 作为返回值
 def make_adder(n):
  return lambda x: x + n
 add5 = make_adder(5)
 print(add5(10)) # 输出: 15

4. 装饰器 (Decorators)

装饰器是一种特殊的函数,用于修改其他函数的行为,而不改变其源代码:

4.1 基本装饰器

 def timer(func):
  """计算函数执行时间的装饰器"""
  import time
  def wrapper(*args, **kwargs):
  start_time = time.time()
  result = func(*args, **kwargs)
  end_time = time.time()
  print(f"{func.__name__} 执行时间: {end_time - start_time:.4f} 秒")
  return result
  return wrapper
 @timer # 等价于: slow_function = timer(slow_function)
 def slow_function():
  """模拟耗时操作"""
  import time
  time.sleep(1)
  print("Function executed")
 slow_function()

4.2 带参数的装饰器

 def repeat(n):
  """重复执行函数 n 次的装饰器"""
  def decorator(func):
  def wrapper(*args, **kwargs):
  for i in range(n):
  result = func(*args, **kwargs)
  return result
  return wrapper
  return decorator
 @repeat(3) # 传递参数给装饰器
 def say_hello(name):
  print(f"Hello, {name}!")
 say_hello("Alice")
 # 输出:
 # Hello, Alice!
 # Hello, Alice!
 # Hello, Alice!

4.3 保留原函数信息

使用 functools.wraps 保留原函数的元数据:

 import functools
 def my_decorator(func):
  @functools.wraps(func) # 保留原函数信息
  def wrapper(*args, **kwargs):
  print("Before function execution")
  result = func(*args, **kwargs)
  print("After function execution")
  return result
  return wrapper
 @my_decorator
 def example():
  """示例函数"""
  print("Function executed")
 example()
 print(f"Function name: {example.__name__}")
 print(f"Function docstring: {example.__doc__}")

4.4 装饰器

多个装饰器可以同时应用于一个函数:

 def decorator1(func):
  def wrapper(*args, **kwargs):
  print("Decorator 1 before")
  result = func(*args, **kwargs)
  print("Decorator 1 after")
  return result
  return wrapper
 def decorator2(func):
  def wrapper(*args, **kwargs):
  print("Decorator 2 before")
  result = func(*args, **kwargs)
  print("Decorator 2 after")
  return result
  return wrapper
 @decorator1
 @decorator2
 def my_function():
  print("Function executed")
 my_function()
 # 输出顺序:
 # Decorator 1 before
 # Decorator 2 before
 # Function executed
 # Decorator 2 after
 # Decorator 1 after

5. 高阶函数 (Higher-Order Functions)

高阶函数是指接收函数作为参数或返回函数的函数:

5.1 接收函数作为参数

 def apply_function(func, value):
  """应用函数到值"""
  return func(value)
 def square(x):
  return x ** 2
 def cube(x):
  return x ** 3
 print(apply_function(square, 5)) # 输出: 25
 print(apply_function(cube, 5)) # 输出: 125
 print(apply_function(lambda x: x + 1, 5)) # 输出: 6

5.2 返回函数

 def make_multiplier(n):
  """返回一个乘以 n 的函数"""
  def multiplier(x):
  return x * n
  return multiplier
 double = make_multiplier(2)
 triple = make_multiplier(3)
 print(double(5)) # 输出: 10
 print(triple(5)) # 输出: 15

5.3 内置高阶函数

5.3.1 map()

map() 函数对序列中的每个元素应用一个函数:

 # 基本用法
 numbers = [1, 2, 3, 4, 5]
 squared = list(map(lambda x: x ** 2, numbers))
 print(squared) # 输出: [1, 4, 9, 16, 25]
 # 多个序列
 numbers1 = [1, 2, 3]
 numbers2 = [4, 5, 6]
 summed = list(map(lambda x, y: x + y, numbers1, numbers2))
 print(summed) # 输出: [5, 7, 9]
 # 自定义函数
 def to_upper(s):
  return s.upper()
 words = ["hello", "world", "python"]
 upper_words = list(map(to_upper, words))
 print(upper_words) # 输出: ['HELLO', 'WORLD', 'PYTHON']

5.3.2 filter()

filter() 函数根据函数结果过滤序列中的元素:

 # 基本用法
 numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
 print(even_numbers) # 输出: [2, 4, 6, 8, 10]
 # 过滤非空字符串
 words = ["hello", "", "world", "", "python"]
 non_empty = list(filter(lambda s: s, words))
 print(non_empty) # 输出: ['hello', 'world', 'python']
 # 自定义函数
 def is_positive(n):
  return n > 0
 numbers = [-5, -3, 0, 2, 7, -1]
 positive_numbers = list(filter(is_positive, numbers))
 print(positive_numbers) # 输出: [2, 7]

5.3.3 reduce()

reduce() 函数对序列中的元素进行累积计算:

 from functools import reduce
 # 基本用法
 numbers = [1, 2, 3, 4, 5]
 sum_result = reduce(lambda x, y: x + y, numbers)
 print(sum_result) # 输出: 15
 # 带初始值
 product_result = reduce(lambda x, y: x * y, numbers, 10) # 初始值为 10
 print(product_result) # 输出: 1200 (10 * 1 * 2 * 3 * 4 * 5)
 # 连接字符串
 words = ["Hello", " ", "World", "!"]
 sentence = reduce(lambda x, y: x + y, words)
 print(sentence) # 输出: Hello World!
 # 查找最大值
 numbers = [3, 1, 4, 1, 5, 9, 2, 6]
 max_value = reduce(lambda x, y: x if x > y else y, numbers)
 print(max_value) # 输出: 9

6. 函数作用域 (Function Scope)

Python 中的变量作用域遵循 LEGB 规则:

  1. Local (L): 局部作用域,在函数内部定义的变量
  2. Enclosing (E): 嵌套作用域,在嵌套函数的外层函数中定义的变量
  3. Global (G): 全局作用域,在模块级别定义的变量
  4. Built-in (B): 内置作用域,Python 内置的变量和函数

6.1 局部作用域

 def my_function():
  local_var = "local"
  print(local_var) # 可以访问局部变量
 my_function()
 # print(local_var) # 错误: 无法访问局部变量

6.2 全局作用域

 global_var = "global"
 def my_function():
  print(global_var) # 可以访问全局变量
 my_function()
 print(global_var) # 可以访问全局变量

6.3 修改全局变量

 global_var = "global"
 def my_function():
  global global_var # 声明要修改全局变量
  global_var = "modified global"
  print(global_var)
 my_function()
 print(global_var) # 输出: modified global

6.4 嵌套作用域

 def outer_function():
  outer_var = "outer"
  def inner_function():
  nonlocal outer_var # 声明要修改嵌套作用域变量
  outer_var = "modified outer"
  print(outer_var)
  inner_function()
  print(outer_var) # 输出: modified outer
 outer_function()

7. 递归函数 (Recursive Functions)

递归函数是调用自身的函数,用于解决可以分解为相同子问题的问题:

7.1 基本递归

 def factorial(n):
  """计算阶乘"""
  if n <= 1:
  return 1
  return n * factorial(n - 1)
 print(factorial(5)) # 输出: 120
 # 斐波那契数列
 def fibonacci(n):
  """计算斐波那契数列第 n 项"""
  if n <= 1:
  return n
  return fibonacci(n - 1) + fibonacci(n - 2)
 print(fibonacci(10)) # 输出: 55

7.2 递归的注意事项

  • 基线条件: 必须有一个明确的终止条件
  • 递归深度: Python 默认递归深度限制为 1000
  • 性能: 某些递归实现可能效率低下,可考虑使用记忆化或迭代
 # 记忆化优化斐波那契
 from functools import lru_cache
 @lru_cache(maxsize=None)
 def fibonacci_memo(n):
  if n <= 1:
  return n
  return fibonacci_memo(n - 1) + fibonacci_memo(n - 2)
 print(fibonacci_memo(100)) # 快速计算大值
 # 迭代实现斐波那契
 def fibonacci_iterative(n):
  if n <= 1:
  return n
  a, b = 0, 1
  for _ in range(2, n + 1):
  a, b = b, a + b
  return b
 print(fibonacci_iterative(100)) # 更高效

8. 函数式编程 (Functional Programming)

函数式编程是一种编程范式,强调使用纯函数、不可变数据和高阶函数

8.1 纯函数

纯函数是指没有副作用且相同输入总是产生相同输出的函数:

 # 纯函数
 def add(a, b):
  return a + b
 # 非纯函数(有副作用)
 total = 0
 def add_to_total(x):
  global total
  total += x
  return total

8.2 不可变数据

函数式编程鼓励使用不可变数据,避免修改现有数据:

 # 不可变操作
 numbers = [1, 2, 3]
 # 创建新列表而不是修改原列表
 new_numbers = [x * 2 for x in numbers]
 print(numbers) # 原列表不变: [1, 2, 3]
 print(new_numbers) # 新列表: [2, 4, 6]
 # 使用元组(不可变)
 point = (1, 2)
 # point[0] = 3 # 错误: 元组不可修改

8.3 函数式编程工具

 from functools import reduce
 # 组合函数
 def compose(f, g):
  return lambda x: f(g(x))
 def add_one(x):
  return x + 1
 def multiply_by_two(x):
  return x * 2
 # 先加 1,再乘以 2
 add_one_then_multiply_by_two = compose(multiply_by_two, add_one)
 print(add_one_then_multiply_by_two(5)) # 输出: 12
 # 管道操作
 from functools import reduce
 def pipe(data, *functions):
  return reduce(lambda x, func: func(x), functions, data)
 result = pipe(
  5,
  lambda x: x + 1, # 6
  lambda x: x * 2, # 12
  lambda x: x - 3 # 9
 )
 print(result) # 输出: 9

9. 函数最佳实践

9.1 函数设计

  • 单一职责: 每个函数应该只做一件事情
  • 函数长度: 保持函数简洁,通常不超过 50 行
  • 命名规范: 使用小写字母和下划线,函数名应该描述其功能
  • 文档字符串: 为函数添加详细的文档字符串
  • 参数数量: 尽量减少参数数量,通常不超过 5 个

9.2 性能优化

  • 避免重复计算: 使用缓存或记忆化
  • 避免不必要的全局变量: 优先使用函数参数和返回值
  • 使用适当的数据结构: 选择合适的数据结构提高性能
  • 生成器: 对于大型数据集,使用生成器节省内存

9.3 代码风格

  • 缩进: 使用 4 个空格进行缩进
  • 空行: 在函数定义之间使用空行
  • 注释: 为复杂的逻辑添加注释
  • 类型提示: 使用型提示提高代码可读性
 # 使用类型提示
 def greet(name: str, age: int) -> str:
  """问候函数"""
  return f"Hello, {name}! You are {age} years old."
 # 类型提示的好处
 # 1. 提高代码可读性
 # 2. 支持静态类型检查
 # 3. 提供更好的代码补全

更新日志 (Changelog)

  • 2026-04-05: 深入细化装饰器与参数传递细节。
  • 2026-04-05: 扩写内容,增加详细的函数定义、参数型、Lambda函数应用、装饰器实现、高阶函数作用域、递归函数和函数式编程等内容。