
大家好,我是煜道。
今天我们一起来学习 函数定义与使用。
引言
函数是组织代码的基本单元,它将复杂的逻辑封装为可重用的代码块。良好的函数设计遵循"单一职责原则"——每个函数只做一件事。在Python中,函数是一等公民,这意味着函数可以作为参数传递、作为返回值、从另一个函数返回,甚至可以赋值给变量。
本文将深入探讨Python函数的各个方面,包括函数定义、参数传递、返回值、作用域、闭包。通过系统学习,我们将能够编写出模块化、可维护的Python代码。

01 函数的基本概念
1.1 函数的定义
# 基本函数定义defgreet(name):"""向用户打招呼的函数"""returnf"Hello, {name}!"# 函数调用message = greet("Python")print(message) # Hello, Python!# 查看函数文档print(greet.__doc__)
1.2 函数的特性
# 函数是对象defadd(a, b):return a + bprint(type(add)) # <class 'function'>print(add.__name__) # 'add'print(add(2, 3)) # 5# 函数可以赋值给变量func = addprint(func(2, 3)) # 5# 函数可以作为参数传递defapply_operation(a, b, op):return op(a, b)result = apply_operation(5, 3, add)print(result) # 8# 函数可以作为返回值defget_operation(op_name): operations = {'add': lambda a, b: a + b,'sub': lambda a, b: a - b,'mul': lambda a, b: a * b }return operations.get(op_name, None)add_func = get_operation('add')print(add_func(2, 3)) # 5


02 函数参数详解
2.1 位置参数
defdescribe_pet(name, age):"""描述宠物信息"""returnf"{name} is {age} years old"# 位置参数调用print(describe_pet("Dog", 3)) # Dog is 3 years oldprint(describe_pet("Cat", 2)) # Cat is 2 years old
2.2 关键字参数
# 关键字参数调用print(describe_pet(age=3, name="Dog")) # 顺序可不同# 位置参数和关键字参数混合print(describe_pet("Dog", age=3)) # 位置在前,关键字在后
2.3 默认参数
defgreet(name, greeting="Hello"):"""带默认参数值的函数"""returnf"{greeting}, {name}!"print(greet("Python")) # Hello, Python!print(greet("Python", "Hi")) # Hi, Python!# 默认参数的注意事项defappend_to_list(item, lst=[]):# 危险!默认参数是可变对象 lst.append(item)return lst# 正确做法defappend_to_list_fixed(item, lst=None):if lst isNone: lst = [] lst.append(item)return lst
2.4 可变参数
# *args - 收集位置参数为元组defsum_numbers(*args): total = 0for num in args: total += numreturn totalprint(sum_numbers(1, 2, 3, 4, 5)) # 15# **kwargs - 收集关键字参数为字典defprint_info(**kwargs):for key, value in kwargs.items(): print(f"{key}: {value}")print_info(name="Python", version=3.12, type="language")# name: Python# version: 3.12# type: language
2.5 参数组合使用
deffunc(pos1, pos2, *args, kw1="default", **kwargs): print(f"pos1: {pos1}, pos2: {pos2}") print(f"args: {args}") print(f"kw1: {kw1}") print(f"kwargs: {kwargs}")func(1, 2, 3, 4, 5, kw1="custom", extra="value")# pos1: 1, pos2: 2# args: (3, 4, 5)# kw1: custom# kwargs: {'extra': 'value'}

2.6 Python 3.12的参数语法改进
Python 3.12引入了PEP 695的语法改进:
# Python 3.12之前defgreet(name: str, greeting: str = "Hello") -> str:returnf"{greeting}, {name}!"# Python 3.12(简化泛型语法)defgreet[T](name: T, greeting: str = "Hello") -> str:returnf"{greeting}, {name}!"

03 返回值
3.1 返回单个值
defadd(a, b):return a + bresult = add(3, 4)print(result) # 7
3.2 返回多个值
defget_min_max(numbers):return min(numbers), max(numbers)# 返回的是元组result = get_min_max([3, 1, 4, 1, 5, 9, 2, 6])print(result) # (1, 9)min_val, max_val = result # 解包
3.3 隐式返回None
defno_return(): print("This function doesn't return anything")result = no_return() # This function doesn't return anythingprint(result) # None

04 作用域与命名空间
4.1 LEGB规则
Python按照LEGB规则查找变量:
# 内置作用域print(len([1, 2, 3])) # len是内置函数# 全局作用域x = "global"defouter():# 闭包作用域 x = "enclosing"definner():# 局部作用域 x = "local" print(x) # local inner() print(x) # enclosingouter()print(x) # global

4.2 global关键字
counter = 0defincrement():global counter counter += 1 print(f"Counter: {counter}")increment() # Counter: 1increment() # Counter: 2print(counter) # 2
4.3 nonlocal关键字
defouter(): count = 0definner():nonlocal count count += 1return countreturn innerf = outer()print(f()) # 1print(f()) # 2print(f()) # 3

05 闭包
5.1 闭包的定义
闭包是由函数及其相关的引用环境组合而成的实体。 当一个函数引用了外部作用域的变量时,就形成了闭包。
defmake_counter(): count = 0defcounter():nonlocal count count += 1return countreturn counter# 创建计数器counter1 = make_counter()counter2 = make_counter()print(counter1()) # 1print(counter1()) # 2print(counter2()) # 1(独立的闭包环境)

5.2 闭包的应用
# 工厂函数defmake_power(exponent):defpower(base):return base ** exponentreturn powersquare = make_power(2)cube = make_power(3)print(square(5)) # 25print(cube(5)) # 125# 带状态的函数defmake_average(): total = 0 count = 0defaverage(new_value):nonlocal total, count total += new_value count += 1return total / count if count > 0else0return averageavg = make_average()print(avg(10)) # 10.0print(avg(20)) # 15.0print(avg(30)) # 20.0

06 特殊函数类型
6.1 匿名函数(lambda)
# lambda表达式add = lambda a, b: a + bprint(add(2, 3)) # 5# 与高阶函数配合numbers = [1, 2, 3, 4, 5]squares = list(map(lambda x: x**2, numbers))print(squares) # [1, 4, 9, 16, 25]# 排序keypoints = [(1, 2), (3, 1), (5, 0)]points.sort(key=lambda p: p[1])print(points) # [(5, 0), (3, 1), (1, 2)]
6.2 高阶函数
# 接受函数作为参数defapply_twice(func, value):return func(func(value))defadd_five(x):return x + 5print(apply_twice(add_five, 10)) # 20# 返回函数defmake_multiplier(factor):defmultiplier(x):return x * factorreturn multiplierdouble = make_multiplier(2)triple = make_multiplier(3)print(double(7)) # 14print(triple(7)) # 21
6.3 内置高阶函数
numbers = [1, 2, 3, 4, 5]squared = list(map(lambda x: x**2, numbers))print(squared)# filtereven = list(filter(lambda x: x % 2 == 0, numbers))print(even)# reducefrom functools import reducetotal = reduce(lambda x, y: x + y, numbers)print(total)# sorted(返回新列表)sorted_list = sorted(numbers, reverse=True)sorted_by_abs = sorted([-1, 2, -3, 4], key=abs)print(sorted_list)print(sorted_by_abs)


07 函数装饰器
7.1 基本装饰器
装饰器是修改函数行为的语法糖:
defmy_decorator(func):defwrapper(*args, **kwargs): print("调用前处理") result = func(*args, **kwargs) print("调用后处理")return resultreturn wrapper@my_decoratordefsay_hello(): print("Hello!")say_hello()# 调用前处理# Hello!# 调用后处理

7.2 带参数的装饰器
defrepeat(times):defdecorator(func):defwrapper(*args, **kwargs):for _ in range(times): result = func(*args, **kwargs)return resultreturn wrapperreturn decorator@repeat(3)defgreet(name): print(f"Hello, {name}!")greet("Python")# Hello, Python!# Hello, Python!# Hello, Python!
7.3 使用functools.wraps
import functoolsdefmy_decorator(func): @functools.wraps(func)defwrapper(*args, **kwargs):"""包装后函数的注释文档"""return func(*args, **kwargs)return wrapper@my_decoratordeforiginal():"""原始的函数注释文档"""passprint(original.__name__) # 'original'(而非'wrapper')print(original.__doc__) # 'Original function docstring'
7.4 常见装饰器示例
import functoolsimport time# 计时装饰器deftimer(func): @functools.wraps(func)defwrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"{func.__name__} 花费 {end - start:.4f} 秒")return resultreturn wrapper# 缓存装饰器defcache(func): cache_dict = {} @functools.wraps(func)defwrapper(*args):if args in cache_dict:return cache_dict[args] result = func(*args) cache_dict[args] = resultreturn resultreturn wrapper# 验证装饰器defvalidate_args(func): @functools.wraps(func)defwrapper(*args, **kwargs):# 示例:验证所有参数为数字for arg in args:ifnot isinstance(arg, (int, float)):raise TypeError("参数必须是数字")return func(*args, **kwargs)return wrapper

08 小结
本文系统介绍了Python函数的各个方面:
- 函数定义与调用:函数作为对象,函数名、参数、返回值。
- 参数类型:位置参数、关键字参数、默认参数、可变参数。
- 作用域规则:LEGB规则,global和nonlocal关键字。
- 特殊函数:lambda表达式、高阶函数、内置函数。
函数是Python编程的核心概念之一。掌握函数的定义、参数传递、作用域等知识,对于编写清晰、可维护的代码至关重要。
