进阶-python函数相关

6 minute read

Python 函数全面详解

一、函数基础概念

1. 什么是函数?

函数是可重用的代码块,用于执行特定任务。它具有以下特点:

  • 接收输入(参数)
  • 执行操作
  • 返回输出(返回值)
  • 提高代码的模块性可重用性

2. 函数定义与调用

# 定义函数
def greet(name):
    """打印问候语(文档字符串)"""
    return f"Hello, {name}!"

# 调用函数
result = greet("Alice")
print(result)  # Hello, Alice!

# 无参数函数
def say_hello():
    print("Hello World!")

# 无返回值函数(返回None)
def do_nothing():
    pass

二、函数参数详解

1. 参数类型对比

参数类型 语法 描述 示例
位置参数 def func(a, b) 按位置传递 func(1, 2)
关键字参数 func(a=1, b=2) 按参数名传递 func(b=2, a=1)
默认参数 def func(a, b=5) 提供默认值 func(1)a=1, b=5
可变位置参数 def func(*args) 接收任意数量位置参数 func(1,2,3)args=(1,2,3)
可变关键字参数 def func(**kwargs) 接收任意数量关键字参数 func(a=1,b=2)kwargs={'a':1,'b':2}
仅限关键字参数 def func(*, a, b)def func(*args, a, b) 必须用关键字传递 func(a=1, b=2)
仅限位置参数 def func(a, b, /) 必须用位置传递 func(1, 2)

2. 完整参数语法

def complex_func(pos1, pos2, /, pos_or_kw, *, kw1, kw2=10):
    """
    参数说明:
    - pos1, pos2: 仅限位置参数
    - pos_or_kw: 位置或关键字参数
    - kw1, kw2: 仅限关键字参数(kw2有默认值)
    """
    print(f"pos1={pos1}, pos2={pos2}, pos_or_kw={pos_or_kw}, kw1={kw1}, kw2={kw2}")

# 调用示例
complex_func(1, 2, 3, kw1=4)  # 正确
complex_func(1, 2, pos_or_kw=3, kw1=4)  # 正确
# complex_func(1, 2, 3, 4)  # 错误:kw1必须用关键字

3. 可变参数示例

# *args 接收任意数量的位置参数
def sum_all(*numbers):
    """计算所有数字的和"""
    return sum(numbers)

print(sum_all(1, 2, 3, 4, 5))  # 15
print(sum_all(10, 20))         # 30

# **kwargs 接收任意数量的关键字参数
def print_info(**info):
    """打印所有关键字参数"""
    for key, value in info.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="Beijing")

# 混合使用
def mixed_func(a, b, *args, option=True, **kwargs):
    """混合所有参数类型"""
    print(f"a={a}, b={b}, args={args}, option={option}, kwargs={kwargs}")

三、函数返回值

1. 返回多个值

def get_stats(numbers):
    """返回统计信息:最小值、最大值、平均值"""
    if not numbers:
        return None
    
    minimum = min(numbers)
    maximum = max(numbers)
    average = sum(numbers) / len(numbers)
    
    # 返回元组(多个值)
    return minimum, maximum, average

# 接收多个返回值
min_val, max_val, avg_val = get_stats([1, 2, 3, 4, 5])

# 返回字典
def get_person():
    """返回字典包含多个值"""
    return {
        "name": "Alice",
        "age": 25,
        "city": "Beijing"
    }

2. 返回函数

# 函数作为返回值
def make_multiplier(factor):
    """创建乘法函数"""
    def multiplier(x):
        return x * factor
    return multiplier

# 使用
double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))  # 10
print(triple(5))  # 15

四、变量作用域

1. 作用域层次

# 全局变量
global_var = "I'm global"

def outer_function():
    # 闭包作用域变量
    outer_var = "I'm in outer function"
    
    def inner_function():
        # 局部变量
        local_var = "I'm local"
        
        # 访问所有作用域
        print(local_var)      # 局部
        print(outer_var)      # 闭包
        print(global_var)     # 全局
        print(__name__)       # 内置
    
    inner_function()

# 全局作用域
print(global_var)
# print(outer_var)  # 错误:不可访问

2. global 和 nonlocal

# global 关键字
counter = 0

def increment():
    global counter  # 声明使用全局变量
    counter += 1
    return counter

# nonlocal 关键字
def outer():
    x = 10
    
    def inner():
        nonlocal x  # 声明使用外层函数的变量
        x += 5
        return x
    
    return inner()

五、函数作为对象

1. 函数是一等公民

# 1. 函数可以赋值给变量
def say_hello(name):
    return f"Hello, {name}!"

greeting = say_hello  # 函数赋值
print(greeting("Bob"))  # 通过变量调用

# 2. 函数可以作为参数传递
def apply_operation(func, value):
    """将函数应用于值"""
    return func(value)

def square(x):
    return x * x

result = apply_operation(square, 5)  # 25

# 3. 函数可以作为返回值
def get_operation(op_type):
    """根据操作类型返回函数"""
    if op_type == "add":
        return lambda x, y: x + y
    elif op_type == "multiply":
        return lambda x, y: x * y
    else:
        return None

2. 函数属性

def example_func(x, y=10):
    """示例函数,用于演示属性"""
    return x + y

# 查看函数属性
print(example_func.__name__)      # 函数名: 'example_func'
print(example_func.__doc__)       # 文档字符串
print(example_func.__module__)    # 模块名
print(example_func.__defaults__)  # 默认参数值: (10,)
print(example_func.__code__)      # 字节码对象

# 自定义函数属性
example_func.author = "Alice"
example_func.version = "1.0"

六、Lambda表达式

1. Lambda 基础

# Lambda 语法: lambda arguments: expression
square = lambda x: x * x
add = lambda x, y: x + y

# 立即调用
result = (lambda x: x + 1)(5)  # 6

# 在列表推导式中使用
numbers = [1, 2, 3, 4, 5]
squares = [(lambda x: x**2)(n) for n in numbers]

2. Lambda 与高阶函数

# 与 map 一起使用
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))  # [1, 4, 9, 16, 25]

# 与 filter 一起使用
evens = list(filter(lambda x: x % 2 == 0, numbers))  # [2, 4]

# 与 sorted 一起使用
pairs = [(1, 5), (3, 2), (2, 8)]
sorted_pairs = sorted(pairs, key=lambda x: x[1])  # 按第二个元素排序

七、装饰器

1. 装饰器基础

# 简单装饰器
def my_decorator(func):
    """装饰器:在函数调用前后添加打印"""
    def wrapper():
        print("Before function call")
        func()
        print("After function call")
    return wrapper

# 使用装饰器
@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# 输出:
# Before function call
# Hello!
# After function call

2. 带参数的装饰器

# 带参数的装饰器
def repeat(num_times):
    """重复执行函数指定次数"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")
# 输出三次: Hello, Alice!

3. 类装饰器

# 类装饰器
class Timer:
    """计时装饰器"""
    def __init__(self, func):
        self.func = func
    
    def __call__(self, *args, **kwargs):
        import time
        start = time.time()
        result = self.func(*args, **kwargs)
        end = time.time()
        print(f"{self.func.__name__} took {end-start:.4f} seconds")
        return result

@Timer
def slow_function():
    import time
    time.sleep(1)
    return "Done"

slow_function()  # 输出执行时间

八、生成器和迭代器

1. 生成器函数

# 使用 yield 创建生成器
def count_up_to(max_num):
    """生成从1到max_num的数字"""
    count = 1
    while count <= max_num:
        yield count
        count += 1

# 使用生成器
counter = count_up_to(5)
for num in counter:
    print(num)  # 1, 2, 3, 4, 5

# 生成器表达式
squares = (x**2 for x in range(5))
for square in squares:
    print(square)  # 0, 1, 4, 9, 16

2. 协程

# 使用 yield 接收值的生成器
def coroutine():
    """协程示例"""
    print("Starting coroutine")
    while True:
        value = yield
        print(f"Received: {value}")

# 使用协程
co = coroutine()
next(co)  # 启动协程
co.send(10)  # Received: 10
co.send(20)  # Received: 20

九、递归函数

1. 递归基础

# 阶乘函数
def factorial(n):
    """计算阶乘(递归实现)"""
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))  # 120

# 斐波那契数列
def fibonacci(n):
    """计算斐波那契数列(递归实现)"""
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))  # 55

2. 尾递归优化

# 尾递归优化版本
def factorial_tail(n, accumulator=1):
    """尾递归阶乘函数"""
    if n <= 1:
        return accumulator
    return factorial_tail(n-1, n * accumulator)

# 使用递归深度限制
import sys
sys.setrecursionlimit(10000)  # 设置递归深度限制

十、函数注解

1. 类型注解

# 函数注解
def add(x: int, y: int) -> int:
    """返回两个整数的和"""
    return x + y

# 带有复杂类型注解
from typing import List, Dict, Optional, Union

def process_data(
    items: List[str],
    config: Optional[Dict[str, Union[int, str]]] = None
) -> Dict[str, List[str]]:
    """处理数据函数"""
    if config is None:
        config = {}
    return {item: [item] for item in items}

# 变量类型注解
name: str = "Alice"
age: int = 25
scores: List[int] = [85, 90, 78]

2. 类型检查

# 使用 mypy 进行类型检查
# 在命令行运行: mypy your_script.py

from typing import TypeVar, Callable

T = TypeVar('T')

def apply_to_all(func: Callable[[T], T], items: List[T]) -> List[T]:
    """将函数应用于列表所有元素"""
    return [func(item) for item in items]

十一、内置高阶函数

函数 描述 示例
map(func, iterable) 对可迭代对象的每个元素应用函数 map(str.upper, ['a','b'])['A','B']
filter(func, iterable) 筛选满足条件的元素 filter(lambda x: x>0, [-1,0,1])[1]
reduce(func, iterable) 累积计算 reduce(lambda x,y: x+y, [1,2,3])6
sorted(iterable, key=func) 排序 sorted(['abc','a','ab'], key=len)['a','ab','abc']
min(iterable, key=func) 最小值 min(['abc','a','ab'], key=len)'a'
max(iterable, key=func) 最大值 max(['abc','a','ab'], key=len)'abc'

十二、偏函数

from functools import partial

# 创建偏函数
def power(base, exponent):
    return base ** exponent

# 平方函数
square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(5))  # 25
print(cube(3))    # 27

# 固定部分参数
def greet(greeting, name):
    return f"{greeting}, {name}!"

say_hello = partial(greet, "Hello")
say_hi = partial(greet, "Hi")

print(say_hello("Alice"))  # Hello, Alice!
print(say_hi("Bob"))       # Hi, Bob!

十三、函数式编程

1. 不可变性

# 使用不可变数据结构
from functools import reduce
from typing import List

# 纯函数示例
def pure_multiply(numbers: List[int], factor: int) -> List[int]:
    """纯函数:不修改输入,返回新列表"""
    return [n * factor for n in numbers]

# 函数组合
def compose(f, g):
    """函数组合:(f ∘ g)(x) = f(g(x))"""
    return lambda x: f(g(x))

# 使用
add_one = lambda x: x + 1
square = lambda x: x * x
add_one_then_square = compose(square, add_one)
print(add_one_then_square(5))  # 36

十四、异步函数

import asyncio

# 异步函数
async def fetch_data():
    """模拟异步获取数据"""
    print("开始获取数据...")
    await asyncio.sleep(2)  # 模拟IO操作
    print("数据获取完成")
    return {"data": "some data"}

async def process_data():
    """异步处理数据"""
    data = await fetch_data()
    print(f"处理数据: {data}")
    return data

# 运行异步函数
async def main():
    result = await process_data()
    print(f"结果: {result}")

# Python 3.7+
asyncio.run(main())

十五、最佳实践

1. 设计原则

  1. 单一职责:每个函数只做一件事
  2. 短小精悍:函数应该简短(通常不超过20行)
  3. 明确命名:函数名应清晰表达其功能
  4. 减少副作用:尽量使用纯函数
  5. 合理抽象:适当抽象重复代码

2. 性能优化

  1. 避免不必要的递归
  2. 使用生成器处理大数据流
  3. 缓存重复计算结果
  4. 使用局部变量加速访问
  5. 考虑使用内置函数

3. 可读性建议

  1. 编写清晰的文档字符串
  2. 使用类型注解
  3. 保持参数数量合理(一般不超过5个)
  4. 避免深层嵌套
  5. 适当使用装饰器

十六、常见模式

# 1. 单例模式
def singleton(cls):
    """单例装饰器"""
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

# 2. 策略模式
class Strategy:
    """策略模式示例"""
    def execute(self, data):
        pass

class AddStrategy(Strategy):
    def execute(self, a, b):
        return a + b

class MultiplyStrategy(Strategy):
    def execute(self, a, b):
        return a * b

# 3. 回调模式
def fetch_data(callback):
    """获取数据后调用回调函数"""
    data = {"result": "success"}
    callback(data)

def handle_data(data):
    print(f"处理数据: {data}")

fetch_data(handle_data)