函数的定义
函数的语法
基本格式如下:
def 函数名(参数1, 参数2, ...):
"""文档字符串(可选)"""
函数体(一组语句) # 缩进
return[返回值1, 返回值2, ...] # 可选
说明及注意事项:
- def:定义函数的关键字。
- 函数名:遵循变量命名规则(字母、数字、下划线,不能以数字开头),建议函数名第一个字母小写,要用有意义的函数名称,如 calculate_area() 而不是 func1()。
- 参数:传递给函数的数据,可以有多个,每个参数值之间逗号隔开,也可以没有(空括号)。
- :****冒号表示函数体开始,英文输入格式。
- 文档字符串(docstring):用三双引号 """ """ 或三单引号包裹,描述函数功能,推荐编写。
- return:返回结果。return和返回值都是可有可无,若有多个返回值彼此之间逗号隔开,若无 return,默认返回 None。
- 函数必须先定义后调用
应用举例
python
# 无参数无返回值的函数
def say_hello():
"""打印问候语"""
print("Hello, Python!")
print("欢迎学习函数!")
# 调用函数
say_hello()
# 有参数有返回值的函数
def add_numbers(a, b):
"""计算两个数的和"""
result = a + b
return result
# 调用函数并接收返回值
sum_result = add_numbers(10, 20)
print(f"10 + 20 = {sum_result}")
# 返回多个值的函数
def calculate_rectangle(length, width):
"""计算矩形的面积和周长"""
area = length * width
perimeter = 2 * (length + width)
return area, perimeter
# 调用函数并解包多个返回值
rect_area, rect_perimeter = calculate_rectangle(5, 3)
print(f"矩形面积:{rect_area}, 周长:{rect_perimeter}")
# 数据处理与统计
def analyze_student_scores(scores):
"""
分析学生成绩数据
参数:
scores: 成绩列表
返回:
dict: 包含最高分、最低分、平均分等信息的字典
"""
if not scores: # 空列表检查
return {"error": "成绩数据为空"}
max_score = max(scores)
min_score = min(scores)
avg_score = sum(scores) / len(scores)
pass_count = sum(1 for score in scores if score >= 60)
return {
"最高分": max_score,
"最低分": min_score,
"平均分": round(avg_score, 2),
"及格人数": pass_count,
"总人数": len(scores)
}
# 测试成绩分析
student_scores = [85, 92, 78, 65, 90, 55, 88, 72, 95, 68]
analysis_result = analyze_student_scores(student_scores)
print("学生成绩分析报告:")
for key, value in analysis_result.items():
print(f"{key}: {value}")
函数的参数设计
参数类型及顺序汇总
|----------------------------------------|------------------------------------------------------------------|----------------------------|---------------------|
| 参数类型 | 语法格式 | 作用 | 顺序要求 |
| 位置参数(Positional Arguments) | def func(param1, param2, param3): # 函数体 | 按位置传递值,第一个值给第一个参数 | 第 1 位(最优先) |
| 默认参数 (Default Arguments) | def funct(param1, param2="默认值"): # 函数体 | 提供默认值,调用时可省略,默认值是不可变对象 | 第 2 位(位置参数后) |
| 可变位置参数 (Variable Positional Arguments) | def func(*args): | 接收任意数量的位置参数,打包为元组 | 第 3 位(默认参数后,关键字参数前) |
| 关键字仅参数 (Keyword-Only Arguments) | def func(*, a, b): 或 def func(*args, a, b): | 强制使用关键字传递 | 第 4 位(*args 后) |
| 默认关键字仅参数 (Default Keyword-Only) | def func(*, a=5, b=10): | 结合默认值和关键字强制 | 第 4 位(可与关键字仅参数混用) |
| 可变关键字参数 (Variable Keyword Arguments) | def func(**kwargs): | 接收任意数量的关键字参数,打包为字典 | 第 5 位(最后) |
| 关键字参数(Keyword Arguments) | def func(param1, param2): ... func(param2=value2, param1=value1) | 通过关键字传参,顺序无关 | 位置参数之后 |
完整参数顺序示例:
deffunc(pos1, pos2, default1=1, default2=2, *args, kw_only1, kw_only2=10, **kwargs):
pass
参数顺序规则:
-
pos1,pos2:位置参数(必填)
-
default1, default2: 默认参数(可选)
-
*args(可变位置参数)
-
kw_only1: 关键字专用参数(必需)
-
kw_only2: 关键字专用参数(可选,有默认值)
-
**kwargs: 任意数量关键字参数
应用举例
python
# 一、位置参数--必须按顺序传递
# 示例 1:传递一个参数
def calculate_square(number):
"""计算一个数的平方"""
return number ** 2
result = calculate_square(5)
print(f"5 的平方是:{result}")
# 示例 2:传递多个参数
def calculate_area(length, width):
"""计算矩形面积"""
area = length * width
return area
area_result = calculate_area(10, 5)
print(f"长 10 宽 5 的矩形面积:{area_result}")
# 二、关键字传参
def create_profile(name, age, city):
"""创建个人信息档案"""
print(f"姓名:{name}, 年龄:{age}, 城市:{city}")
create_profile(name="张三", age=25, city="北京")
create_profile(city="上海", name="李四", age=30)
# 三、默认值参数--提供默认值,可选择性覆盖
def greet(name, age=18):
print(f"你好,{name},你今年{age}岁。")
greet("王五") # 使用默认值 你好,王五,你今年18岁。
greet("赵六", 22) # 覆盖默认值 你好,赵六,你今年22岁。
# 四、可变位置参数 (*args)--接收任意数量的位置参数
def variable_positional_example(*args):
"""可变位置参数:接收任意数量的位置参数"""
print(f"args 类型:{type(args)}") # tuple
for i, arg in enumerate(args):
print(f"参数{i}: {arg}")
# 调用
variable_positional_example(1, 2, 3)
variable_positional_example("a", "b", "c", "d")
# 五、关键字仅参数--强制使用关键字传递
def keyword_only_example(*, name, age):
"""关键字仅参数:强制使用关键字传递"""
print(f"姓名:{name}, 年龄:{age}")
# 调用
keyword_only_example(name="小明", age=20) # 正确
# keyword_only_example("小明", 20) # 错误:必须使用关键字
# 六、可变关键字参数 (**kwargs)--接收任意数量的关键字参数
def variable_keyword_example(**kwargs):
"""可变关键字参数:接收任意数量的关键字参数"""
print(f"kwargs 类型:{type(kwargs)}") # dict
for key, value in kwargs.items():
print(f"{key}: {value}")
# 调用
variable_keyword_example(name="小红", age=22, city="深圳")
# 七、完整示例(所有参数类型)
def complete_example(pos1, pos2,
default1=10, default2=20,
*args,
kw_only_req,
kw_only_opt=999,
**kwargs):
"""
完整参数顺序演示
参数顺序:
1. pos1, pos2 - 位置参数(必填)
2. default1, default2 - 默认参数(选填)
3. *args - 可变位置参数
4. kw_only_req - 关键字仅参数(必填)
5. kw_only_opt - 关键字仅参数(选填,带默认值)
6. **kwargs - 可变关键字参数
"""
print("=" * 50)
print(f"位置参数:pos1={pos1}, pos2={pos2}")
print(f"默认参数:default1={default1}, default2={default2}")
print(f"可变位置参数:args={args}")
print(f"必需关键字参数:kw_only_req={kw_only_req}")
print(f"可选关键字参数:kw_only_opt={kw_only_opt}")
print(f"可变关键字参数:kwargs={kwargs}")
print("=" * 50)
# 调用示例
complete_example(
1, 2, # 位置参数
3, 4, # 覆盖默认参数
5, 6, 7, # *args 可变位置参数
kw_only_req="必须指定", # 关键字仅参数(必填)
kw_only_opt=888, # 关键字仅参数(选填)
extra1="额外 1", # **kwargs
extra2="额外 2"
)
函数的回传值
函数返回值汇总
| 类型 | 语法格式 | 作用 | 特点 | 适用场景 |
|---|---|---|---|---|
回传 None |
return 或 return None |
表示函数无返回值,仅执行副作用(如打印、修改全局变量、写文件) | 无值返回 默认行为(无 return 时自动返回 None) 不适合用于判断或交互 |
日志记录、配置初始化、副作用操作 |
| 回传数值数据 (int, float, complex) | return 42 return 3.14 |
返回数字结果,用于计算、比较、状态码等 | 适合数学运算;可参与表达式; | 数学计算、评分系统、接口状态码 |
| 回传多个数据 (元组 / 解包) | return a, b, c (自动打包为 tuple) |
一次返回多个结果,避免多个函数调用 | 支持解包赋值(x, y = func()) 保持顺序关联 不能命名字段,可读性较差 |
分割结果(商/余)、统计分析、坐标点 |
| 回传字符串 (str) | return "Hello" |
返回文本信息,常用于提示、日志、格式化输出 | 可读性强;易于拼接、格式化;无法直接表示结构化数据 | 用户提示、API 返回文本、HTML 内容生成 |
| 回传字典 (dict) | return {"name": "Alice", "age": 25} |
返回结构化、命名的数据集合,语义清晰 | 支持字段命名;易扩展 适合 JSON、配置、对象模型;不能保证顺序(Python 3.7+ 有序) | API 响应、用户信息、配置解析、对象封装 |
| 回传列表 (list) | return [1, 2, 3] 或 return [x for x in ...] |
返回有序、可重复的数据组,适合批量处理 | 支持索引、遍历、切片 可变,适合动态更新 无命名字段,不具语义 | 数据集合、搜索结果、文件行读取、循环输出 |
| 推荐使用顺序(从高到低): 🔹 字典 > 🔹 列表 > 🔹 多个数据(元组) > 🔹 字符串 > 🔹 数值 > 🔹 None |
返回值综合应用
python
# return 返回值综合应用
import random
from datetime import datetime
# 模拟:假设用户是否联网
has_network = True # 可切换为 False 模拟断网
def get_weather_data(city="Beijing"):
"""
模拟从天气 API 获取数据,根据条件返回不同类型的值。
用于演示 Python 中函数 return 的六种常见类型。
"""
# 模拟网络延迟或断网(真实项目中可用 requests 和 try/except)
if not has_network:
print("📡 无法连接网络,返回 None")
return None # 类型1:返回 None(未联网)
# 模拟真实天气数据
temp = round(random.uniform(10, 35), 1) # 温度:10~35℃
humidity = random.randint(30, 90) # 湿度:30%~90%
wind_speed = round(random.uniform(0, 15), 1) # 风速:0~15 m/s
condition = random.choice(["Sunny", "Partly Cloudy", "Overcast", "Rainy", "Snowy"])
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 类型2:返回数值(当前温度)
if city == "temperature_only":
print(f"🌡️ 返回数值:当前温度 {temp}℃")
return temp
# 类型3:返回元组(气温, 湿度, 风速)
if city == "tuple":
print(f"🌡️ · 气温: {temp}℃, 湿度: {humidity}%, 风速: {wind_speed} m/s")
return temp, humidity, wind_speed
# 类型4:返回字符串(天气描述)
if city == "description":
desc = f"今天 {condition.lower()},气温 {temp}℃,湿度 {humidity}%,风速 {wind_speed} m/s"
print("📝 返回字符串:", desc)
return desc
# 类型5:返回字典(结构化数据)
if city == "dict":
data = {
"temp": temp,
"humidity": humidity,
"condition": condition,
"timestamp": timestamp
}
print("📦 返回字典:", data)
return data
# 类型6:返回列表(多个城市预报)
if city == "multiple_cities":
cities = ["Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Hangzhou"]
weather_list = []
for c in cities:
t = round(random.uniform(15, 38), 1)
h = random.randint(40, 95)
w = round(random.uniform(0, 20), 1)
cond = random.choice(["Sunny", "Cloudy", "Rain"])
weather_list.append({
"city": c,
"temp": t,
"humidity": h,
"wind_speed": w,
"condition": cond,
"timestamp": timestamp
})
print(f"🏙️ 返回列表 ------ {len(weather_list)} 个城市预报")
return weather_list
# 默认:返回北京的字典数据(实际项目中用于正常调用)
print(f"🌤️ 正常返回:北京天气(字典)")
return {
"city": city,
"temp": temp,
"humidity": humidity,
"condition": condition,
"timestamp": timestamp
}
if __name__ == "__main__":
print("=" * 50)
print("🌦️ 测试 get_weather_data() 函数:六种 return 类型")
print("=" * 50)
# 1. ✅ return None(未联网)
print("\n[1] 测试:断网时返回 None")
has_network = False
result_none = get_weather_data("Beijing")
print(f"返回值:{result_none}")
# 2. ✅ return 数值(温度)
print("\n[2] 测试:仅返回数值(温度)")
has_network = True
temp = get_weather_data("temperature_only")
print(f"当前温度:{temp}℃")
# 3. ✅ return 元组(气温, 湿度, 风速)
print("\n[3] 测试:返回元组")
weather_tuple = get_weather_data("tuple")
t, h, w = weather_tuple
print(f"气温: {t}℃, 湿度: {h}%, 风速: {w} m/s")
# 4. ✅ return 字符串(描述)
print("\n[4] 测试:返回字符串")
desc = get_weather_data("description")
print(desc)
# 5. ✅ return 字典(结构化数据)
print("\n[5] 测试:返回字典")
data_dict = get_weather_data()
print(f"城市:{data_dict['city']}, 温度:{data_dict['temp']}℃, 情况:{data_dict['condition']}")
# 6. ✅ return 列表(多个城市)
print("\n[6] 测试:返回列表(多个城市预报)")
cities_data = get_weather_data("multiple_cities")
for item in cities_data[:3]: # 只打印前3个
print(f" {item['city']}:{item['temp']}℃ ({item['condition']})")
调用函数时参数
调用函数时参数汇总
| 类型 | 是否可变 | 函数内能修改? | 是否影响原始数据? | 传递建议 |
|---|---|---|---|---|
list |
✅ 是 | ✅ 用 append 等 |
✅ 会变 | 传 lst.copy()/list(lst) 安全 |
dict |
✅ 是 | ✅ 修改键值 | ✅ 会变 | 传 copy.deepcopy() 安全 |
set |
✅ 是 | ✅ 使用 add, remove |
✅ 会变 | 传 s.copy() 安全 |
tuple |
❌ 否 | ❌ 不能改 | ❌ 不会变 | 无需副本,只读安全 |
int / float |
❌ 否 | ❌ 不能改 | ❌ 不会变 | 完全安全(值传递) |
str |
❌ 否 | ❌ 不能改 | ❌ 不会变 | 完全安全 |
综合应用
python
import copy
from datetime import datetime
# ============================
# 1. 定义学生管理函数(综合调用)
# ============================
def manage_student(
student_id: int, # 数值参数
name: str, # 字符串参数
grades: list, # 列表参数(可变)
courses: tuple, # 元组参数(不可变)
scores: dict, # 字典参数(可变)
tags: set, # 集合参数(可变)
active: bool = True # 布尔参数(可选)
):
"""
管理学生信息,演示各类参数的传递行为。
:param student_id: 学号(int)
:param name: 姓名(str)
:param grades: 成绩列表(list,函数内会被修改)
:param courses: 课程元组(tuple,只读)
:param scores: 各科分数(dict,会更新)
:param tags: 标签集合(set,可修改)
:param active: 是否活跃(bool,默认 True)
:return: 更新后的状态字典
"""
print(f"📋 正在处理学生:{name} (ID: {student_id})")
print(f" 课程:{courses}")
print(f" 初始成绩:{grades}")
print(f" 初始标签:{sorted(tags)}")
print(f" 是否活跃:{active}")
# ✅ 修改可变参数:列表、字典、集合
# 1. 给成绩列表追加"优秀"评价(函数内修改原列表)
grades.append("优秀")
# 2. 更新各科成绩(字典修改)
scores["数学"] = scores.get("数学", 95) + 1 # 累加1分
scores["英语"] = 88
# 3. 添加新标签(集合修改)
tags.add("进步中")
tags.add("擅长编程")
# 4. 演示数值变化
if active:
print(f" 👍 学生{student_id}当前活跃,状态更新成功。")
else:
print(f" 🛑 学生{student_id}为非活跃状态。")
# 返回合并信息
return {
"id": student_id,
"name": name,
"avg_grade": round(sum(grade for grade in grades[:-1] if isinstance(grade, (int, float))) / len(grades[:-1]),
2) if grades[:-1] else 0,
"final_scores": scores,
"tags": tags,
"updated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
# ============================
# 2. 使用示例(调用函数 + 传入各类型参数)
# ============================
# 原始数据(外部变量)
student_id = 2025001
student_name = "张三"
student_grades = [85, 90, 78] # 列表
student_courses = ("数学", "英语", "物理") # 元组
student_scores = {"语文": 80, "数学": 88} # 字典
student_tags = {"勤奋", "学习认真"} # 集合
is_active = True
# ❗️重要提醒:如果你想保留原始数据!必须传副本!
# ✅ 方式一:传原始数据(会修改原值 ------ 正常业务逻辑)
print("=" * 60)
print("🟢 方式一:直接传入原始数据(**会修改**)")
print("=" * 60)
result1 = manage_student(
student_id,
student_name,
student_grades,
student_courses,
student_scores,
student_tags,
is_active
)
print("\n✅ 处理完成,返回结果:")
print(result1)
print("\n🔥 处理后原始数据已变化!")
print(f"🔹 成绩列表(原):{student_grades}") # → [85, 90, 78, '优秀']
print(f"🔹 分数字典(原):{student_scores}") # → {'语文': 80, '数学': 89, '英语': 88}
print(f"🔹 标签集合(原):{student_tags}") # → {'进步中', '学习认真', '擅长编程'}
# ✅ 方式二:传副本(不修改原始数据 ------ 安全模式)
print("\n" + "=" * 60)
print("🟡 方式二:传副本(**不修改**原始数据)")
print("=" * 60)
# 使用 copy 保证数据安全
safe_grades = student_grades.copy()
safe_scores = copy.deepcopy(student_scores) # 字典嵌套,需深拷贝
safe_tags = student_tags.copy()
result2 = manage_student(
student_id,
student_name,
safe_grades,
student_courses, # 元组无需复制
safe_scores,
safe_tags,
is_active
)
print("\n✅ 处理完成,返回结果:")
print(result2)
print("\n📦 处理后原始数据未变!")
print(f"🔹 成绩列表(原):{student_grades}") # → [85, 90, 78](不变)
print(f"🔹 分数字典(原):{student_scores}") # → {'语文': 80, '数学': 88}(不变)
print(f"🔹 标签集合(原):{student_tags}") # → {'勤奋', '学习认真'}(不变)
# ✅ 方式三:数值 & 字符串传参(值传递,完全安全)
print("\n" + "=" * 60)
print("🔵 方式三:数值和字符串参数(完全安全,无法被修改)")
print("=" * 60)
def test_value_params(num, text):
num = 999 # ❌ 仅修改局部变量,不影响外部
text = "changed" # ❌ 不影响原值
print(f"内部 num: {num}, text: {text}")
original_num = 100
original_text = "Hello"
test_value_params(original_num, original_text)
print(f"外部 num: {original_num}, text: {original_text}")
进一步认识函数
函数文档字符串
函数名称下的"""函数说明文档...."""称为文档字符串 Docstring(document string)缩写,用于解释说明该函数的用途、参数含义、返回值、示例;可以用print(函数名.doc)进行查看函数文档
python
# 语法格式
def 函数名(参数):
"""
函数说明文档(docstring)
- 用途
- 参数说明
- 返回值说明
- 示例:
>>> func(3)
5
"""
# 函数体
return 返回值
# 实例说明
def count_even(numbers):
"""
计算列表中偶数的个数。
参数:
numbers (list): 整数列表
返回:
int: 偶数的个数
示例:
>>> count_even([1, 2, 3, 4, 5, 6])
3
"""
return len([x for x in numbers if x % 2 == 0])
# 查看文档
print(count_even.__doc__)
函数是一个对象
在 Python 中,函数是第一类对象(First-class object),可以像变量一样赋值、传递、存储。
python
# 将函数赋值给变量
def greet(name):
return f"Hello, {name}!"
# 函数赋值
greet_func = greet
print(greet_func("Alice")) # Hello, Alice!
函数是数据结构成员
函数可以作为列表、字典、集合等数据结构的元素。
python
# 定义几个运算函数
def add(a, b):
return a + b
def multiply(a, b):
return a * b
def subtract(a, b):
return a - b
# 将函数放入字典
operations = {
'+': add,
'*': multiply,
'-': subtract
}
# 动态调用
result = operations['+'](5, 3)
print(result) # 8
函数作为参数传递给其他函数
将函数作为参数传入另一个函数(高阶函数)。
python
def apply_operation(func, a, b):
"""接收一个函数和两个参数,执行函数"""
return func(a, b)
# 使用
print(apply_operation(add, 10, 5)) # 15
print(apply_operation(multiply, 4, 6)) # 24
函数当参数与 *args 不定量参数
*args:接收任意数量位置参数,打包为元组- 结合函数参数传递,传递函数和可变参数
python
# 计算多个数的平均值(用函数处理)
def calculate_average(func, *args):
"""使用函数对可变参数进行处理并返回结果"""
return func(args) # 如 sum(args)/len(args)
def sum_list(nums):
return sum(nums)
# 调用
result = calculate_average(sum_list, 1, 2, 3, 4, 5)
print(result) # 15(在函数内部处理)
# 用函数筛选并操作不定参数
def process_numbers(func, *args):
filtered = [x for x in args if x > 0]
return func(filtered)
def max_value(nums):
return max(nums)
print(process_numbers(max_value, -1, 2, -3, 5, 1)) # 5
嵌套函数(Nested Function)
函数中定义另一个函数,内部函数可访问外部函数的变量。
python
# 身份证号校验的嵌套函数
def validate_id_card(id_card):
"""验证身份证号(简略版)"""
def is_valid_length():
return len(id_card) == 18
def ends_with_check():
last_char = id_card[-1]
return last_char.isdigit() or last_char.lower() == 'x'
if is_valid_length() and ends_with_check():
return "有效"
else:
return "无效"
print(validate_id_card("11010119900307123X")) # 有效
函数作为返回值
函数可以返回另一个函数。
python
# 返回不同计算函数
def make_multiplier(factor):
"""根据 factor 返回乘法函数"""
def multiply(x):
return x * factor
return multiply # 返回函数对象
# 创建特定乘法函数
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(4)) # 12
闭包(Closure)
内部函数是一个 动态产的程序,当它可以记住函数以外的程序所建立的环境变量值时,我们称这个内部函数是闭包。
python
def outer():
b = 10 # inner所使用的变量值
def inner(x):
return 5 * x + b # 引用第2行的变量b
return inner
b = 2
f = outer()
print(f(b)) # 20
print(f) # <function outer.<locals>.inner at 0x0000020EA0E0EA60>
print(f.__closure__) # (<cell at 0x0000020EA0E0EA60: int object at 0x0000020EA0E0EA60>,)
print(f.__closure__[0].cell_contents) # 10
上述第2行b是一个环境变量,这也是定义在inner()以外的变量,由于第7行inner当作回传值,inner()内的b其实就是第2行所定义的b;其实变量b和inner就构成了一个closure。
第12行的f(b),其实这个b将是inner(x)的x参数,所以最后得到5 * 2 + 10,结果是20
其实**closure内是一个元组**,环境变量b就是存在cell_contents内。
python
# 计数器(带状态的函数)
def make_counter():
count = 0 # 外部变量(被闭包捕获)
def increment():
nonlocal count # 声明要修改外部变量
count += 1
return count
return increment # 返回函数对象
# 创建两个独立计数器
counter1 = make_counter()
counter2 = make_counter()
print(counter1()) # 1
print(counter1()) # 2
print(counter2()) # 1(独立状态)
print(counter1()) # 3
递归函数的设计
递归函数是指在函数执行过程中直接或间接调用自身的函数。递归通常用于解决可以分解为相似子问题的问题。
语法格式
python
def recursive_function(参数):
# 1. 基线条件(终止条件)
if 条件:
return 值
# 2. 递归条件
else:
return recursive_function(缩小的参数)
适用场景
-
数学计算(阶乘、斐波那契数列)
-
树形结构遍历(文件系统、DOM 树)
-
分治算法(快速排序、归并排序)
-
回溯算法(迷宫问题、八皇后)
应用举例
python
# 案例1:斐波那契数列(经典递归)
def fibonacci(n):
"""
计算斐波那契数列第 n 项
参数:n - 正整数
返回:第 n 个斐波那契数
"""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(6)) # 输出: 8
# 注意:此版本效率极低(指数级时间复杂度),建议用记忆化递归优化:
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(6))
# 案例2:二 叉树前序遍历(深度优先搜索)
# 递归自然表达树结构的遍历逻辑。
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def preorder(root):
if root is None:
return []
return [root.val] + preorder(root.left) + preorder(root.right)
# 示例:构建树 [1,2,3] → 1 -> 2 -> 3
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
print(preorder(root)) # 输出: [1, 2, 3]
# 案例3:目录遍历(递归搜索文件夹)
import os
def list_files(directory, indent=0):
"""
递归列出目录下所有文件和子目录
参数:directory - 目录路径,indent - 缩进级别
"""
files = os.listdir(directory)
for file in sorted(files):
file_path = os.path.join(directory, file)
# 打印当前文件/目录,带缩进显示层级
print(" " * indent + "├── " + file)
# 如果是目录,递归调用
if os.path.isdir(file_path):
list_files(file_path, indent + 4)
list_files(r"D:\pythonProject\python_王者归来", 0) # 替换为你要遍历的目录路径
# 案例4:汉诺塔问题(经典递归问题)
def hanoi(n, source, auxiliary, target):
"""
汉诺塔问题求解
参数:
n - 盘子数量
source - 源柱子
auxiliary - 辅助柱子
target - 目标柱子
"""
if n == 1:
print(f"将盘子 1 从 {source} 移动到 {target}")
else:
# 将 n-1 个盘子从 source 移到 auxiliary
hanoi(n - 1, source, target, auxiliary)
# 将第 n 个盘子从 source 移到 target
print(f"将盘子 {n} 从 {source} 移动到 {target}")
# 将 n-1 个盘子从 auxiliary 移到 target
hanoi(n - 1, auxiliary, source, target)
hanoi(3, 'A', 'B', 'C')
print(f"\n总共需要 {2 ** 3 - 1} 步")
# 案例5:快速排序
def quick_sort(arr):
"""
使用递归实现快速排序
参数:arr - 待排序列表
返回:排序后的列表
"""
# 基线条件:空列表或只有一个元素
if len(arr) <= 1:
return arr
else:
# 选择基准值
pivot = arr[len(arr) // 2]
# 小于基准值的元素
left = [x for x in arr if x < pivot]
# 等于基准值的元素
middle = [x for x in arr if x == pivot]
# 大于基准值的元素
right = [x for x in arr if x > pivot]
# 递归排序左右两部分
return quick_sort(left) + middle + quick_sort(right)
data = [33, 10, 59, 27, 41, 45, 89, 78, 56, 23]
print(f"原始数据:{data}")
sorted_data = quick_sort(data)
print(f"排序结果:{sorted_data}")