函数是Python编程中最重要的构建块之一,它们允许我们将代码组织成可重用的模块化片段。本文将全面介绍Python函数的所有重要概念和用法。

目录

  1. 函数基础
  2. 参数传递
  3. 返回值
  4. 作用域
  5. 高级函数特性
  6. 装饰器
  7. 匿名函数
  8. 最佳实践

函数基础

定义函数

使用 def 关键字定义函数:

def greet():
    """简单的问候函数"""
    print("Hello, World!")

调用函数

greet()  # 输出: Hello, World!

文档字符串

函数的第一行字符串是文档字符串,用于说明函数功能:

def add(a, b):
    """
    返回两个数的和
    
    参数:
    a -- 第一个数字
    b -- 第二个数字
    
    返回:
    两个数字的和
    """
    return a + b

print(add.__doc__)  # 查看文档字符串

参数传递

位置参数

def power(base, exponent):
    return base ** exponent

result = power(2, 3)  # 8

默认参数

def greet(name, message="Hello"):
    return f"{message}, {name}!"

print(greet("Alice"))  # Hello, Alice!
print(greet("Bob", "Hi"))  # Hi, Bob!

关键字参数

def describe_person(name, age, city):
    return f"{name} is {age} years old and lives in {city}"

# 使用关键字参数,顺序不重要
describe_person(age=25, city="New York", name="Alice")

可变参数

*args - 可变位置参数
def sum_numbers(*args):
    return sum(args)

print(sum_numbers(1, 2, 3, 4))  # 10
**kwargs - 可变关键字参数
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

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

参数组合

参数定义的顺序必须是:位置参数、默认参数、*args、**kwargs

def complex_function(a, b, c=10, *args, **kwargs):
    print(f"a={a}, b={b}, c={c}")
    print(f"args: {args}")
    print(f"kwargs: {kwargs}")

complex_function(1, 2, 3, 4, 5, name="Alice", age=25)

返回值

返回单个值

def square(x):
    return x * x

返回多个值

实际上返回的是元组:

def calculate(x, y):
    return x + y, x - y, x * y, x / y

result = calculate(10, 5)  # (15, 5, 50, 2.0)
sum_result, diff_result, prod_result, quot_result = calculate(10, 5)

作用域

局部变量 vs 全局变量

x = 10  # 全局变量

def test_scope():
    x = 20  # 局部变量
    print("局部变量 x:", x)  # 20

test_scope()
print("全局变量 x:", x)  # 10

global 关键字

x = 10

def modify_global():
    global x
    x = 20  # 修改全局变量

modify_global()
print(x)  # 20

nonlocal 关键字

用于嵌套函数中修改外部函数的变量:

def outer():
    x = 10
    
    def inner():
        nonlocal x
        x = 20  # 修改外部函数的变量
    
    inner()
    print(x)  # 20

outer()

高级函数特性

函数作为一等公民

函数可以像其他对象一样被传递和使用:

def shout(text):
    return text.upper()

def whisper(text):
    return text.lower()

def greet(func, name):
    return func(f"Hello, {name}")

print(greet(shout, "Alice"))  # HELLO, ALICE!
print(greet(whisper, "Bob"))  # hello, bob!

闭包

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

生成器函数

使用 yield 关键字:

def fibonacci(limit):
    a, b = 0, 1
    while a < limit:
        yield a
        a, b = b, a + b

for num in fibonacci(100):
    print(num)

装饰器

装饰器是修改其他函数行为的函数:

简单装饰器

def my_decorator(func):
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

带参数的装饰器

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator_repeat

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

greet("Alice")

类装饰器

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0
    
    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print(f"调用第 {self.num_calls} 次")
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello!")

say_hello()  # 调用第 1 次
say_hello()  # 调用第 2 次

匿名函数

使用 lambda 关键字创建匿名函数:

# 简单lambda函数
square = lambda x: x * x
print(square(5))  # 25

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

# 排序时使用
students = [("Alice", 25), ("Bob", 20), ("Charlie", 23)]
students.sort(key=lambda x: x[1])
print(students)  # [('Bob', 20), ('Charlie', 23), ('Alice', 25)]

最佳实践

1. 保持函数简短且专注

每个函数应该只做一件事,并且做好。

2. 使用有意义的名称

# 不好
def proc_data(data):
    pass

# 好
def process_user_data(user_data):
    pass

3. 使用类型提示

from typing import List, Dict, Optional

def process_items(
    items: List[str], 
    counts: Dict[str, int]
) -> Optional[bool]:
    # 函数体
    pass

4. 避免修改可变参数

# 不好
def add_to_list(item, items=[]):
    items.append(item)
    return items

# 好
def add_to_list(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

5. 使用装饰器 wisely

不要过度使用装饰器,它们可能会使代码难以理解。

6. 适当的错误处理

def divide(a: float, b: float) -> float:
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

更多推荐