函数是可重复调用的代码块,能提升代码复用性和可读性。
8.1 定义与调用函数
1. 定义格式
用def关键字声明,包含4个核心部分:
def 函数名(参数): # def关键字+函数名+括号(必带)+参数(可选)
"""函数说明文档(可选,说明功能、参数、返回值)"""
函数体(具体逻辑)
return 返回值(可选,无则默认返回None)
2. 调用方式
直接写函数名(实参),有参数则传对应值:
# 示例:定义打招呼函数并调用
def greet_user(name):
"""向用户打招呼"""
print(f"Hello, {name.title()}.")
greet_user('lxf') # 调用,输出:Hello, Lxf.
8.2 函数的参数
参数分「形参」(定义时的“占位符”)和「实参」(调用时的“具体值”),传递实参有4种常用方式:
| 传递方式 | 特点 | 示例代码(以计算差值函数为例) |
|---|---|---|
| 位置实参 | 按形参顺序传值,一一对应 | def subtract(num1, num2): print(num1-num2)subtract(20,10) # 输出10 |
| 关键字实参 | 明确形参名,不用管顺序 | subtract(num2=10, num1=20) # 输出10 |
| 默认值 | 定义时给形参设默认值,调用时可省略 | def multiply(num1, num2=10): print(num1*num2)multiply(5) # 用默认值10,输出50 |
| 等效调用 | 位置+关键字+默认值组合,只要值对应即可 | multiply(8,12)/multiply(num1=8,num2=12) # 均输出96 |
8.3函数的返回值
用return语句把结果传给调用者,支持返回多种类型:
1. 返回简单值(字符串、数字等)
# 示例:返回完整姓名
def get_full_name(first, last):
full_name = f"{first} {last}".title()
return full_name # 返回拼接后的姓名
user_name = get_full_name("lisa", "wang") # 用变量接收返回值
print(user_name) # 输出:Lisa Wang
2. 返回字典(适合结构化数据)
# 示例:返回用户信息(姓名必传,年龄可选)
def build_user(first, last, age=None):
user = {"first": first.title(), "last": last.title()}
if age: # 有年龄则添加到字典
user["age"] = age
return user
print(build_user("bob", "zhao", 28)) # 输出:{'first': 'Bob', 'last': 'Zhao', 'age': 28}
8.4 传递列表
函数可处理列表,默认会修改原列表;若想保留原列表,传列表副本(列表名[:]):
1. 修改原列表
# 示例:标记已完成的任务
def mark_done(todos, done_task):
if done_task in todos:
todos.remove(done_task) # 从待办列表移除
completed.append(f"✅ {done_task}") # 加入已完成列表
to_do = ["写报告", "开会"]
completed = []
mark_done(to_do, "开会")
print(to_do) # 输出:['写报告'](原列表被修改)
2. 传递列表副本(不修改原列表)
def sort_copy(lst):
lst_copy = lst[:] # 创建副本
lst_copy.sort() # 只排序副本
return lst_copy
original = [3,1,4,2]
sorted_lst = sort_copy(original)
print(original) # 输出:[3,1,4,2](原列表不变)
8.5传递任意数量实参
不确定实参数量时,在形参前加*,将实参打包成元组:
# 示例:计算任意个数的总和
def calculate_sum(*numbers): # *numbers接收任意个实参,存为元组
total = 0
for num in numbers:
total += num
return total
print(calculate_sum(1,2,3)) # 输出6
print(calculate_sum(10,20,30,40)) # 输出100
也可结合固定参数(固定参数放前面):
# 示例:统计某类别的物品
def count_items(category, *items):
print(f"类别:{category},物品:{list(items)},数量:{len(items)}")
count_items("水果", "苹果", "香蕉") # 输出:类别:水果,物品:['苹果','香蕉'],数量:2
8.6 函数存到模块(复用代码)
模块是.py文件,可封装函数,在其他文件中导入使用,3种常用导入方式:
1. 导入整个模块
模块文件(function_tools.py):
def add(a,b): return a+b
def subtract(a,b): return a-b
主文件调用:
import function_tools # 导入整个模块
print(function_tools.add(10,20)) # 输出30
2. 模块设别名(简化调用)
import function_tools as ft # 别名ft
print(ft.subtract(50,15)) # 输出35
3. 导入指定函数(直接用函数名调用)
from function_tools import add, subtract # 只导入add和subtract
print(add(5,8)) # 输出13(不用加模块名)
8.7 函数编写规范
编写函数时遵循以下规范,可提升代码质量和协作效率:
1 函数名要"见名知意"
用小写字母+下划线(如calculate_average),直接体现功能,避免func1这类模糊命名或驼峰式命名。
2 必须写文档字符串
用"""在函数定义后说明:功能、参数含义、返回值类型,必要时加异常说明,方便他人理解。
示例:
def calculate_area(radius):
"""
计算圆形面积
:param radius: float,半径(>0)
:return: float,面积(π×radius²)
:raises ValueError: 半径≤0时抛出
"""
3 单一职责原则
一个函数只做一件事,避免"大而全"。例如拆分"读数据→算平均→存结果"为3个独立函数。
4 参数设计要合理
- 数量不宜过多(建议≤5个),多参数可封装为字典
- 可选参数用默认值,优先用不可变对象(如
None),避免列表等可变对象
错误:def add(items=[]):(多次调用会累积数据)
正确:def add(items=None): items = items or []
5 返回值要明确统一
- 类型保持一致(避免有时返回数字,有时返回字符串)
- 多值返回用元组,固定顺序并在文档说明含义
6 避免硬编码固定值
-
灵活值(如阈值、路径)通过参数传递,方便调整。
-
例:
def check_score(score, pass_line=60):(及格线可灵活修改)
7 处理异常增强健壮性
- 对可能出错的操作(如除零、文件读取)用
try-except捕获异常,或提前判断参数合法性。
8 减少副作用
尽量不修改外部变量或传入的可变对象(如列表),必要时创建副本操作并返回新结果,避免意外修改原数据。
评论区