前面我们学了数据结构(列表、字典等)和流程控制,能写出实现具体功能的代码了。但如果遇到“重复的逻辑”——比如多次计算两个数的和、反复验证用户输入是否合法,总不能每次都写一遍相同的代码吧?这篇要学的“函数”,就是解决“代码重复”的核心工具——把重复的逻辑封装成一个“工具”,要用的时候直接调用,既省时间又能减少错误。
一、先搞懂:什么是函数?为什么要用?
简单说,函数就是“一段提前定义好、可重复调用的代码块”,就像生活里的“计算器”——你不用知道它内部怎么算的,只要输入数字(参数),它就会返回结果(返回值)。
举个例子:如果要多次计算“两个数的平均值”,没函数时要反复写“(a+b)/2”,有函数后只需定义一次,后续直接调用:
# 没函数:重复写相同逻辑
print((10+20)/2) # 计算10和20的平均
print((30+40)/2) # 计算30和40的平均
print((50+60)/2) # 计算50和60的平均
# 有函数:定义一次,多次调用
def calculate_average(a, b): # 定义函数
return (a + b) / 2
# 调用函数,直接用结果
print(calculate_average(10, 20)) # 输出15.0
print(calculate_average(30, 40)) # 输出35.0
print(calculate_average(50, 60)) # 输出55.0
很明显,用函数后代码更简洁——如果要修改逻辑(比如改成“(a+b+c)/3”),只需改函数内部,不用改每一处调用。
二、函数的基础:定义与调用
这是函数最核心的两步:先“定义”(写好工具),再“调用”(用工具)。
1. 定义函数:用def关键字
语法结构:
def 函数名(参数1, 参数2, ...): # def开头,函数名自定义,参数可选(无参数就空括号)
"""函数文档字符串(可选,说明函数功能、参数、返回值)"""
函数体代码(要缩进,实现具体逻辑)
return 返回值(可选,没return就返回None)
注意:
- 函数名命名规则和变量一样:字母、数字、下划线,不数字开头,小写+下划线(如
calculate_average
); - 文档字符串(三引号包裹)不是必须的,但建议写——用
help(函数名)
能查看,方便自己和别人理解。
示例:定义一个“判断数字是否为偶数”的函数:
def is_even(num):
"""判断一个数字是否为偶数
参数:
num:要判断的整数
返回值:
True:是偶数;False:不是偶数
"""
if num % 2 == 0:
return True
else:
return False
2. 调用函数:用函数名+括号
定义好后,用“函数名(实际参数)”就能调用,括号里的“实际参数”要和定义时的“参数”对应(数量、类型尽量一致):
# 调用is_even函数,传入实际参数10
result1 = is_even(10)
print(result1) # 输出True(10是偶数)
# 传入实际参数15
result2 = is_even(15)
print(result2) # 输出False(15不是偶数)
# 查看函数文档
help(is_even) # 会显示我们写的文档字符串
3. 无参数、无返回值的函数
不是所有函数都要有参数和返回值——比如“打印欢迎语”的函数,既不用输入,也不用返回结果:
# 无参数:括号里空着
def print_welcome():
print("="*20)
print("欢迎使用Python工具!")
print("="*20)
# 调用:括号里也空着,不用接收返回值
print_welcome()
运行后会直接打印欢迎语,函数没return
,所以调用时不用赋值给变量。
三、函数的核心:参数传递
参数是“函数的输入”,灵活处理参数能让函数更通用。新手先掌握3种常用参数类型:位置参数、默认参数、关键字参数。
1. 位置参数:按顺序传参(最常用)
定义时的参数叫“形参”,调用时的参数叫“实参”,位置参数要求“实参顺序和形参一致,数量相同”:
# 定义一个“计算a乘以b加c”的函数(形参a、b、c)
def calculate(a, b, c):
return a * b + c
# 调用:实参10(对应a)、2(对应b)、5(对应c),按顺序传
result = calculate(10, 2, 5)
print(result) # 10*2+5=25,输出25
如果顺序错了,结果会错——比如calculate(2, 10, 5)
,会变成210+5=25(碰巧对),但calculate(10, 5, 2)
会变成105+2=52(错了)。
2. 默认参数:给参数设默认值(可选传参)
定义函数时,给形参加“=默认值”,调用时可以不传这个参数(用默认值),也可以传(覆盖默认值):
# 定义:给c设默认值0(默认计算a*b+0)
def calculate(a, b, c=0):
return a * b + c
# 调用1:不传c,用默认值0 → 10*2+0=20
result1 = calculate(10, 2)
print(result1) # 输出20
# 调用2:传c=5,覆盖默认值 →10*2+5=25
result2 = calculate(10, 2, 5)
print(result2) # 输出25
注意:默认参数要放在“非默认参数后面”——比如def calculate(a, c=0, b)
是错的,必须把c=0
放最后。
3. 关键字参数:按参数名传参(不用记顺序)
调用函数时,用“形参名=实参”的方式传参,不用管顺序,适合参数多的场景:
# 定义一个“打印用户信息”的函数,参数多
def print_user_info(name, age, city):
print(f"姓名:{name},年龄:{age},城市:{city}")
# 调用:按关键字传参,顺序打乱也没关系
print_user_info(age=18, name="小明", city="北京")
# 输出:姓名:小明,年龄:18,城市:北京
也可以“位置参数+关键字参数”混合用,但位置参数必须在前面:
# 正确:name是位置参数(第一个),age和city是关键字参数
print_user_info("小红", city="上海", age=17)
# 错误:关键字参数不能在位置参数前面
# print_user_info(city="广州", "小刚", age=19)
四、函数的进阶:返回值与作用域
1. 返回值:用return给函数“输出结果”
return
的作用有两个:1. 返回结果;2. 终止函数(return
后面的代码不会执行)。
(1)返回单个值
前面的例子都是返回单个值,直接return 结果
即可:
def add(a, b):
return a + b # 返回a+b的结果
sum_result = add(3, 5)
print(sum_result) # 输出8
(2)返回多个值
Python支持一次返回多个值,用逗号分隔,接收时用多个变量对应:
# 定义一个“返回两个数的和与差”的函数
def add_and_sub(a, b):
sum_ab = a + b
sub_ab = a - b
return sum_ab, sub_ab # 返回两个值
# 接收:两个变量对应两个返回值
sum_result, sub_result = add_and_sub(10, 3)
print(sum_result) # 输出13(和)
print(sub_result) # 输出7(差)
本质是返回一个“元组”,只是省略了括号——return (sum_ab, sub_ab)
和上面一样。
2. 作用域:变量的“有效范围”
函数里定义的变量(局部变量),只能在函数内部用;函数外定义的变量(全局变量),能在函数外和函数内用(但修改全局变量需要用global
关键字)。
示例:
# 全局变量:在函数外定义
global_num = 100
def test_scope():
# 局部变量:在函数内定义,只能在函数里用
local_num = 200
print("函数内访问全局变量:", global_num) # 可以访问,输出100
print("函数内访问局部变量:", local_num) # 可以访问,输出200
# 修改全局变量:必须用global声明
global global_num
global_num = 150 # 现在修改的是全局变量
test_scope()
# 函数外访问全局变量:输出修改后的值150
print("函数外访问全局变量:", global_num)
# 函数外访问局部变量:报错(局部变量只在函数内有效)
# print("函数外访问局部变量:", local_num)
建议:尽量少用全局变量——函数依赖全局变量会降低复用性,优先用“参数传递”和“返回值”传递数据。
五、实战小案例:用函数封装“学生成绩分析工具”
需求:写一个工具,能实现3个功能:1. 计算成绩列表的平均分;2. 找出成绩列表中的最高分;3. 统计及格人数(≥60)。用函数封装每个功能,最后调用测试。
# 1. 定义“计算平均分”的函数
def calculate_avg(scores):
"""计算成绩列表的平均分
参数:
scores:成绩列表(元素是整数/浮点数)
返回值:
平均分(浮点数),若列表为空返回0
"""
if not scores: # 判断列表是否为空
return 0.0
return sum(scores) / len(scores)
# 2. 定义“找最高分”的函数
def find_max(scores):
"""找成绩列表的最高分
参数:
scores:成绩列表
返回值:
最高分,若列表为空返回None
"""
if not scores:
return None
return max(scores)
# 3. 定义“统计及格人数”的函数
def count_pass(scores):
"""统计成绩≥60的人数
参数:
scores:成绩列表
返回值:
及格人数(整数)
"""
count = 0
for score in scores:
if score >= 60:
count += 1
return count
# 4. 调用函数测试
student_scores = [85, 92, 58, 76, 98, 60, 45]
print("成绩列表:", student_scores)
print("平均分:", round(calculate_avg(student_scores), 1)) # 保留1位小数,输出76.3
print("最高分:", find_max(student_scores)) # 输出98
print("及格人数:", count_pass(student_scores)) # 输出5(85、92、76、98、60)
总结
这篇我们掌握了函数的核心:
- 定义与调用:用
def
定义,用“函数名()”调用,解决代码重复问题; - 参数传递:位置参数(按顺序)、默认参数(设默认值)、关键字参数(按名传);
- 返回值:
return
返回结果,支持返回多个值; - 作用域:局部变量(函数内有效)、全局变量(慎用,优先用参数和返回值)。
有了函数,我们就能把复杂问题拆成多个小功能(每个功能一个函数),代码会更清晰、更好维护。下一篇我们会学“模块与包”——如何把函数/代码拆到不同文件里,实现更大规模的代码组织~