
1. Python函数基础概念函数是Python编程中最重要的构建块之一它允许我们将代码组织成可重用的逻辑单元。想象一下函数就像厨房里的多功能料理机 - 你只需要把食材放进去输入参数按下按钮调用函数就能得到处理好的食物返回值而不需要每次都重新发明轮子。在Python中函数通过def关键字定义基本语法结构如下def 函数名(参数1, 参数2, ...): 函数文档字符串 函数体 return 返回值这个简单的结构却蕴含着强大的能力。让我们看一个实际例子def greet(name): 向指定的人问好 return fHello, {name}! print(greet(Alice)) # 输出: Hello, Alice!注意函数名应该使用小写字母单词间用下划线连接这是PEP 8风格指南的建议。好的函数名应该清楚地表达函数的功能。2. 函数参数详解2.1 位置参数与关键字参数Python函数的参数传递非常灵活。最基本的两种方式是位置参数和关键字参数def describe_pet(animal_type, pet_name): print(fI have a {animal_type} named {pet_name}.) # 位置参数调用 describe_pet(hamster, Harry) # 关键字参数调用 describe_pet(pet_nameHarry, animal_typehamster)位置参数必须按照定义时的顺序传递而关键字参数则通过参数名指定顺序不重要。关键字参数能大大提高代码可读性特别是在处理多个参数时。2.2 默认参数值我们可以为参数指定默认值这使得某些参数变为可选的def describe_pet(pet_name, animal_typedog): print(fI have a {animal_type} named {pet_name}.) describe_pet(Willie) # 使用默认的animal_type describe_pet(Harry, hamster) # 覆盖默认值重要提示默认参数在函数定义时计算一次而不是每次调用时计算。这意味着如果默认值是可变对象如列表、字典所有调用将共享同一个对象这可能导致意外行为。2.3 可变参数Python支持两种可变参数*args接收任意数量的位置参数打包成元组**kwargs接收任意数量的关键字参数打包成字典def make_pizza(*toppings): print(Making pizza with:) for topping in toppings: print(f- {topping}) make_pizza(pepperoni) make_pizza(mushrooms, green peppers, extra cheese) def build_profile(**user_info): profile {} for key, value in user_info.items(): profile[key] value return profile user build_profile(nameAlice, age25, occupationEngineer) print(user)3. 返回值与作用域3.1 返回多个值Python函数可以返回多个值实际上是返回一个元组def get_user_stats(user_id): # 模拟从数据库获取数据 posts 42 followers 1024 following 256 return posts, followers, following stats get_user_stats(123) print(stats) # 输出: (42, 1024, 256)我们可以使用元组解包来接收这些值posts, followers, following get_user_stats(123)3.2 变量作用域理解变量作用域对编写可靠的函数至关重要局部变量函数内部定义的变量只能在函数内部访问全局变量函数外部定义的变量可以在整个程序中使用nonlocal变量在嵌套函数中用于声明变量来自外层(非全局)作用域x global # 全局变量 def outer(): x outer # 外层函数的局部变量 def inner(): nonlocal x # 声明使用外层函数的x x inner # 修改外层函数的x print(inner:, x) inner() print(outer:, x) outer() print(global:, x)输出将是inner: inner outer: inner global: global4. 高阶函数与lambda表达式4.1 函数作为对象在Python中函数是一等公民可以像其他对象一样被传递和使用def apply_operation(func, x, y): return func(x, y) def add(a, b): return a b def multiply(a, b): return a * b print(apply_operation(add, 3, 4)) # 输出: 7 print(apply_operation(multiply, 3, 4)) # 输出: 124.2 lambda表达式lambda用于创建小型匿名函数适合简单的操作square lambda x: x ** 2 print(square(5)) # 输出: 25 # 常用于排序等需要函数作为参数的场景 names [Alice, Bob, Charlie, David] names.sort(keylambda name: len(name)) print(names) # 输出: [Bob, Alice, David, Charlie]虽然lambda很方便但PEP 8建议对于复杂逻辑还是使用常规def函数。5. 装饰器基础装饰器是修改或增强函数行为的强大工具def timer(func): 测量函数执行时间的装饰器 import time def wrapper(*args, **kwargs): start time.time() result func(*args, **kwargs) end time.time() print(f{func.__name__} executed in {end - start:.4f} seconds) return result return wrapper timer def long_running_function(n): 模拟耗时操作 sum 0 for i in range(n): sum i return sum result long_running_function(1000000) print(result)装饰器本质上是一个接受函数作为参数并返回新函数的高阶函数。timer语法糖等同于long_running_function timer(long_running_function)。6. 常见问题与调试技巧6.1 参数传递问题新手常犯的错误是混淆可变和不可变对象的参数传递def modify_list(lst): lst.append(4) # 修改会影响原始列表 lst [1, 2, 3] # 重新赋值不会影响原始列表 my_list [1, 2, 3] modify_list(my_list) print(my_list) # 输出: [1, 2, 3, 4]6.2 递归深度限制Python默认递归深度限制为1000超过会引发RecursionError。对于深度递归问题通常可以改写为迭代形式# 不推荐的递归实现 def factorial(n): if n 1: return 1 return n * factorial(n - 1) # 更好的迭代实现 def factorial(n): result 1 for i in range(1, n 1): result * i return result6.3 调试技巧使用print调试虽然简单但更专业的做法是使用logging模块或调试器import logging logging.basicConfig(levellogging.DEBUG) def complex_function(x): logging.debug(fEntering complex_function with x{x}) try: result x ** 2 / (x - 1) except ZeroDivisionError: logging.error(Division by zero occurred) return None logging.debug(fExiting complex_function with result{result}) return result对于更复杂的调试可以使用Python内置的pdb模块或IDE的调试功能。7. 函数最佳实践单一职责原则每个函数应该只做一件事并且做好合理命名函数名应该清晰表达其功能使用动词或动词短语适当长度函数体不宜过长一般不超过20-30行文档字符串使用docstring说明函数用途、参数和返回值类型提示Python 3.5支持类型提示可以提高代码可读性from typing import List, Optional def process_items(items: List[str], limit: Optional[int] None) - int: 处理项目列表并返回处理的数量 Args: items: 要处理的字符串列表 limit: 可选的处理数量限制 Returns: 实际处理的项目数量 count 0 for item in items: if limit is not None and count limit: break # 处理逻辑 count 1 return count在实际项目中我经常发现遵循这些原则的函数更容易维护和测试。特别是当几个月后回头看代码时良好的函数设计和文档能大大减少理解成本。