第五阶段:函数基础,解锁模块化编程新技能
😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🌝分享学习心得,欢迎指正,大家一起学习成长!
转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人
前言
恭喜大家顺利通关Python3基础学习第四阶段!在第四阶段,我们吃透了列表、元组、字典、集合四大容器,还掌握了字符串高级操作,能够高效存储和处理各类数据。但在实际编程中,我们常会遇到重复使用的代码------比如多次筛选列表中的有效数据、反复计算不同数值的求和/平均值、批量格式化输出内容,逐行编写不仅繁琐,还容易出错、难以修改。
而第五阶段我们要重点攻克的「函数基础」,就是解决这一问题的"神器"。函数的核心作用是代码复用与模块化:将重复逻辑封装成一个"代码模块",一次定义、多次调用,既能减少重复代码量,还能让代码结构更清晰、更易维护。这也是Python编程从"零散代码"走向"规范编程"的关键一步,为后续学习函数进阶、面向对象、模块与包打下坚实基础。
本次第五阶段,我们将严格按照「函数定义与调用→函数参数→函数返回值→局部变量与全局变量→匿名函数→函数嵌套与递归(基础版)」的节奏,每个知识点都搭配可直接复制运行的代码示例、通俗解析和新手避坑技巧,全程贴合新手学习节奏,跟着敲代码、练案例,就能轻松吃透函数基础~
1、函数的定义与调用:从"零散代码"到"模块化封装"
简单来说,函数就是"提前写好的、可重复调用的代码块"------就像工厂里的"标准化生产线",提前设定好流程(代码逻辑),每次投入原材料(参数),就能产出对应产品(结果)。Python中定义函数必须使用 def 关键字,语法固定,新手只需牢记模板即可。
1.1 函数的定义(固定模板)
定义函数的核心语法(新手必背):
python
# 函数定义模板
def 函数名(参数列表):
"""函数文档字符串(可选,用于说明函数功能、参数、返回值)"""
# 函数体(要执行的代码逻辑)
代码块
# 返回值(可选,用return语句,后续详解)
解析每个部分的作用,新手一看就懂:
def:定义函数的关键字,必须放在最前面(相当于"声明这是一个函数");- 函数名:遵循变量命名规范(字母、数字、下划线组成,不能以数字开头,不能用Python关键字,如def、if),建议见名知意(比如计算求和的函数叫sum_nums,一目了然);
- 参数列表:括号内的内容,可选(无参数则括号为空),用于接收外部传入的"原材料",后续详细讲解;
- 文档字符串:用三引号包裹,可选,用于说明函数功能,方便自己和他人查看(调用时用help(函数名)可查看);
- 函数体:缩进的代码块(推荐4个空格,和if、for循环缩进一致),是函数的核心逻辑,调用函数时会执行这里的代码;
- 返回值:用return语句,可选,用于将函数的执行结果返回给调用者,没有return则默认返回None。
新手入门示例(两个基础函数,可直接复制运行):
python
# 示例1:无参数、无返回值的函数(仅执行简单操作)
def greet():
"""无参数函数,用于输出问候语"""
print("Hello, Python! 欢迎学习第五阶段函数基础~")
# 示例2:有参数、无返回值的函数(接收参数,执行操作)
def print_name(name):
"""有参数函数,用于输出传入的姓名
参数:name -- 要输出的姓名(字符串类型)
"""
print(f"我的名字是:{name}")
# 示例3:有参数、有简单逻辑的函数(计算两个数的和,暂时不返回结果)
def add(a, b):
"""计算两个数的和,并打印结果
参数:a -- 第一个数字,b -- 第二个数字
"""
result = a + b
print(f"{a} + {b} = {result}")
1.2 函数的调用(核心:定义后必须调用才会执行)
函数定义后,只是"写好了生产线",不会自动执行,必须通过「函数名(参数)」的方式调用,才能触发函数体的执行------这是新手最容易忽略的点!调用语法和参数传递,要和函数定义时的参数列表对应。
python
# 调用示例1:调用无参数函数(括号为空,无需传参)
greet() # 输出:Hello, Python! 欢迎学习第五阶段函数基础~
# 调用示例2:调用有一个参数的函数(必须传入1个参数,与定义时的name对应)
print_name("张三") # 输出:我的名字是:张三
print_name("李四") # 输出:我的名字是:李四
# 调用示例3:调用有两个参数的函数(必须传入2个参数,与定义时的a、b对应)
add(3, 5) # 输出:3 + 5 = 8
add(10, 20) # 输出:10 + 20 = 30
# 查看函数文档字符串(新手必备,忘记函数功能时使用)
help(print_name) # 输出函数的文档说明,包含参数解释
3. 新手避坑指南(必看)
- 避坑1:函数名不能用Python关键字(如def、if、for、list),否则会报错;
python
>>> def if():
File "<stdin>", line 1
def if():
^^
SyntaxError: invalid synta
- 避坑2:函数体必须缩进(4个空格),不缩进会被视为普通代码,且报错;
- 避坑3:定义函数后,必须调用才会执行,只定义不调用,函数体的代码永远不会运行;
- 避坑4:调用函数时,传入的参数个数、类型,要和函数定义时的参数列表对应(比如add(a,b)必须传2个参数,不能多也不能少)。
2 函数参数:灵活传递"原材料",适配不同场景
函数的参数,就是函数与外部交互的"接口"------通过参数,我们可以向函数传递不同的数据,让同一个函数实现不同的功能(比如add(a,b),传入3和5得到8,传入10和20得到30)。
按照使用场景,我们重点掌握4种核心参数类型,按"基础→进阶"的顺序讲解,每个类型配代码、解析区别,新手可逐步掌握:位置参数、关键字参数、默认参数、可变参数,结合参考资料中的参数用法,简化适配新手学习。
2.1 位置参数(最基础、最常用)
位置参数,也叫"必选参数",是最基础的参数类型,特点是:调用时必须按函数定义的参数顺序传参,参数个数必须一致,缺一不可、多一不可,就像"按顺序排队"一样。
python
# 定义一个计算两个数差值的函数(位置参数示例)
def subtract(a, b):
"""计算a - b的差值,a和b都是位置参数"""
result = a - b
print(f"{a} - {b} = {result}")
# 正确调用:按参数顺序传参(a=10,b=5)
subtract(10, 5) # 输出:10 - 5 = 5
# 正确调用:按参数顺序传参(a=20,b=8)
subtract(20, 8) # 输出:20 - 8 = 12
# 错误调用1:参数个数不足(少传1个参数)
# subtract(10) # 报错:missing 1 required positional argument: 'b'
# 错误调用2:参数个数过多(多传1个参数)
# subtract(10, 5, 3) # 报错:takes 2 positional arguments but 3 were given
# 错误调用3:参数顺序颠倒(得到错误结果,不报错但逻辑错误)
subtract(5, 10) # 输出:5 - 10 = -5(顺序错,结果错)
核心总结:位置参数"按顺序、定个数",调用时必须严格匹配函数定义的参数顺序和个数,新手优先掌握这种参数用法。
2.2 关键字参数(更灵活,无需记顺序)
关键字参数,是在调用函数时,通过「参数名=参数值」的方式传参,特点是:无需按参数顺序传参,只要参数名正确,就能匹配到对应的参数,适合参数较多的场景,避免记混顺序。
python
# 复用上面的subtract函数(a和b是位置参数,调用时可改用关键字参数)
def subtract(a, b):
result = a - b
print(f"{a} - {b} = {result}")
# 正确调用1:全部用关键字参数(顺序可颠倒)
subtract(a=10, b=5) # 输出:10 - 5 = 5
subtract(b=5, a=10) # 输出:10 - 5 = 5(顺序颠倒,结果正确)
# 正确调用2:位置参数和关键字参数混合使用(重点:位置参数必须在关键字参数前面)
subtract(10, b=5) # 输出:10 - 5 = 5(a用位置参数,b用关键字参数)
# 错误调用:关键字参数在位置参数前面(顺序错误)
# subtract(a=10, 5) # 报错:positional argument follows keyword argument
核心总结:关键字参数"按名字、不按顺序",混合使用时,位置参数必须在关键字参数前面,新手可在参数较多时优先使用,减少出错。
2.3 默认参数(可选传参,简化调用)
默认参数,是在函数定义时,给参数指定一个"默认值",特点是:调用函数时,可传参(覆盖默认值),也可不传参(使用默认值),适合参数值经常重复的场景,能简化函数调用。
重点规则:默认参数必须放在位置参数的后面(否则报错),参考资料中默认参数的用法,适配新手编写简单案例。
python
# 定义一个计算折扣价的函数(默认参数示例)
# price:位置参数(必传),discount:默认参数(默认0.9,即9折)
def calculate_discount(price, discount=0.9):
"""计算商品折扣价
参数:price -- 商品原价(必传,位置参数)
discount -- 折扣率(可选,默认0.9,即9折)
"""
final_price = price * discount
print(f"商品原价:{price}元,折扣率:{discount},折后价:{final_price}元")
# 调用1:不传默认参数(使用默认折扣0.9)
calculate_discount(100) # 输出:商品原价:100元,折扣率:0.9,折后价:90.0元
# 调用2:传默认参数(覆盖默认值,比如8折)
calculate_discount(100, 0.8) # 输出:折后价:80.0元
# 调用3:用关键字参数传默认参数(更清晰)
calculate_discount(100, discount=0.7) # 输出:折后价:70.0元
# 错误定义:默认参数放在位置参数前面(顺序错误)
# def calculate_discount(discount=0.9, price): # 报错:non-default argument follows default argument
新手避坑:默认参数的默认值,最好是不可变类型(如数字、字符串、元组),不要用列表、字典等可变类型(会出现意想不到的错误,后续进阶再详细讲解)。
2.4 可变参数(不定个数,灵活适配)
可变参数,是指函数调用时,传入的参数个数可以任意(0个、1个、多个),适合参数个数不确定的场景(比如计算多个数的总和、打印多个信息)。Python中常用两种可变参数:
*args:接收任意个数的位置参数 ,传入后会自动打包成一个元组;**kwargs:接收任意个数的关键字参数 ,传入后会自动打包成一个字典。
重点:*args 和 **kwargs 只是约定俗成的名字,args和kwargs可以换成其他名字,但星号*和**不能少,参考资料中可变参数的案例,简化后适配新手。
python
# 示例1:*args 接收任意个数的位置参数(计算多个数的总和)
def sum_nums(*args):
"""计算任意个数的总和,*args接收位置参数,打包成元组"""
print("传入的参数打包成元组:", args) # 查看args的类型(元组)
total = sum(args)
print(f"所有数的总和:{total}")
# 调用:可传0个、1个、多个参数
sum_nums() # 输出:总和:0(args为空元组)
sum_nums(1, 2, 3) # 输出:总和:6(args=(1,2,3))
sum_nums(10, 20, 30, 40) # 输出:总和:100(args=(10,20,30,40))
# 示例2:**kwargs 接收任意个数的关键字参数(打印用户信息)
def print_user_info(**kwargs):
"""打印用户信息,**kwargs接收关键字参数,打包成字典"""
print("传入的参数打包成字典:", kwargs) # 查看kwargs的类型(字典)
for key, value in kwargs.items():
print(f"{key}:{value}")
# 调用:可传0个、1个、多个关键字参数
print_user_info(name="张三", age=18, gender="男", score=95)
# 输出:name:张三,age:18,gender:男,score:95(kwargs是对应的字典)
print_user_info() # 输出:无信息(kwargs为空字典)
# 示例3:*args 和 **kwargs 混合使用(接收任意位置参数和关键字参数)
def mix_params(a, b, *args, **kwargs):
"""混合使用多种参数,顺序:位置参数 → *args → **kwargs(必记)"""
print(f"位置参数a:{a},b:{b}")
print(f"可变位置参数args:{args}")
print(f"可变关键字参数kwargs:{kwargs}")
# 调用:按顺序传参
mix_params(1, 2, 3, 4, 5, name="张三", age=18)
# 输出:a=1, b=2;args=(3,4,5);kwargs={'name':'张三','age':18}
核心总结:可变参数适合"参数个数不确定"的场景,*args 对应元组,**kwargs 对应字典,混合使用时,参数顺序必须是:**位置参数 → 默认参数 → *args → kwargs(新手记牢这个顺序,避免报错)。
3 函数返回值:用return语句,获取函数的"执行结果"
前面我们写的函数,大多是"执行操作并打印结果",但在实际编程中,我们常常需要将函数的执行结果保存起来,用于后续的计算、判断等操作------这就需要用到函数的返回值,return语句就是函数的"输出口",负责将函数内部的结果传递给调用者,参考资料4中return的用法,拆解成新手易懂的知识点。
3.1 return语句的基础用法(核心)
语法:return 结果,作用有两个:① 将"结果"返回给函数调用者;② 终止函数执行(return后面的代码,永远不会运行)。
重点:如果函数没有return语句,默认返回 None(Python中的空值,相当于"无结果")。
python
# 示例1:有return语句的函数(返回两个数的和,用于后续计算)
def add(a, b):
"""计算a + b的和,并用return返回结果"""
result = a + b
return result # 返回计算结果
# return后面的代码不会执行
print("这句话永远不会被执行!")
# 调用函数,接收返回值(将return的结果赋值给变量total)
total1 = add(3, 5)
print(f"3+5的和:{total1}") # 输出:8
# 用返回值进行后续计算
total2 = add(10, 20)
print(f"10+20的和乘以2:{total2 * 2}") # 输出:60
# 示例2:无return语句的函数(默认返回None)
def print_hello():
print("Hello, Python!")
# 接收返回值(默认是None)
res = print_hello()
print(f"函数的返回值:{res}") # 输出:None
# 示例3:return终止函数执行
def judge_num(num):
if num > 0:
return "正数" # 满足条件,返回结果,终止函数
print("这句话在num>0时,不会执行!")
if num == 0:
return "零"
return "负数"
print(judge_num(5)) # 输出:正数(return后面的代码未执行)
3.2 return返回多个值(实用技巧)
Python中,return可以返回多个值,用逗号分隔即可------本质上,return返回的是一个元组,调用时可以用多个变量"解包"接收,非常实用。
python
# 示例:一个函数返回多个结果(计算两个数的加、减、乘、除)
def calc(a, b):
add_res = a + b
sub_res = a - b
mul_res = a * b
div_res = a / b if b != 0 else "除数不能为0"
# 返回多个值,用逗号分隔
return add_res, sub_res, mul_res, div_res
# 方式1:用多个变量解包接收(推荐,清晰直观)
add_r, sub_r, mul_r, div_r = calc(10, 5)
print(f"加法:{add_r},减法:{sub_r},乘法:{mul_r},除法:{div_r}")
# 输出:加法:15,减法:5,乘法:50,除法:2.0
# 方式2:用一个变量接收(得到的是元组)
all_res = calc(10, 5)
print(f"所有结果(元组):{all_res}") # 输出:(15, 5, 50, 2.0)
print(f"乘法结果:{all_res[2]}") # 输出:50(通过索引获取元组中的值)
# 处理除数为0的情况
add_r2, sub_r2, mul_r2, div_r2 = calc(10, 0)
print(div_r2) # 输出:除数不能为0
3.3 新手避坑指南
- 避坑1:return和print的区别(新手最易混淆)------print只是"打印结果到屏幕",不会返回任何值;return是"将结果返回给调用者",可以用于后续计算;
- 避坑2:return后面的代码不会执行,不要在return后面写逻辑代码;
- 避坑3:return返回多个值时,调用者可以用任意个数的变量接收(少接收会报错,多接收可用*args接收剩余值);
- 避坑4:函数中可以有多个return语句,但只有第一个被执行的return会生效(因为return会终止函数)。
4 局部变量与全局变量:搞懂"变量的作用范围",避免报错
在函数学习中,新手很容易遇到"变量找不到""变量修改无效"的问题,核心原因是没搞懂「变量的作用范围」------变量分为局部变量和全局变量,各自有不同的作用域(即"能被访问的范围"),结合参考资料1和3中局部与全局变量的案例,简化讲解,重点突破新手痛点。
4.1 局部变量(函数内部的"临时变量")
局部变量:在函数内部定义的变量,作用域仅限于函数内部(只能在函数内部访问、修改,函数执行结束后,局部变量会被销毁,外部无法访问)。
python
# 局部变量示例
def add(a, b):
# result是在函数内部定义的,属于局部变量
result = a + b
print(f"函数内部访问局部变量result:{result}") # 正确:函数内部可访问
# 调用函数
add(3, 5) # 输出:函数内部访问局部变量result:8
# 错误:函数外部访问局部变量(超出作用域)
# print(f"函数外部访问局部变量result:{result}") # 报错:name 'result' is not defined
核心:局部变量是函数内部的"临时变量",仅供函数内部使用,外部无法访问,函数执行完就消失。
4.2 全局变量(函数外部的"公共变量")
全局变量:在函数外部定义的变量,作用域是整个程序(既能在函数外部访问、修改,也能在函数内部访问,但不能直接修改,需要用关键字声明)。
python
# 全局变量示例(在函数外部定义)
global_num = 100 # global_num是全局变量
# 函数内部访问全局变量(无需声明,直接访问)
def print_global():
print(f"函数内部访问全局变量global_num:{global_num}") # 正确:可直接访问
# 函数外部访问全局变量(直接访问)
print(f"函数外部访问全局变量global_num:{global_num}") # 输出:100
# 调用函数
print_global() # 输出:函数内部访问全局变量global_num:100
4.3 重点:函数内部修改全局变量(必须用global关键字)
新手最易踩坑:函数内部不能直接修改全局变量------如果在函数内部直接给全局变量赋值,Python会认为你是在定义一个"新的局部变量",而不是修改全局变量,此时会报错或出现逻辑错误。
解决方法:在函数内部,用 global 全局变量名 声明该变量是全局变量,然后再修改。
python
# 示例1:错误修改全局变量(未用global声明)
global_num = 100
def wrong_modify():
# 错误:未声明global,Python认为是定义局部变量
global_num = 200 # 这里的global_num是新的局部变量,不是全局变量
print(f"函数内部(错误修改):{global_num}") # 输出:200
wrong_modify()
# 函数外部查看全局变量(未被修改,还是原来的值)
print(f"函数外部查看全局变量:{global_num}") # 输出:100(未修改成功)
# 示例2:正确修改全局变量(用global声明)
global_num2 = 100
def correct_modify():
global global_num2 # 声明:global_num2是全局变量,后续修改的是全局变量
global_num2 = 200 # 正确修改全局变量
print(f"函数内部(正确修改):{global_num2}") # 输出:200
correct_modify()
# 函数外部查看全局变量(已被修改)
print(f"函数外部查看全局变量:{global_num2}") # 输出:200(修改成功)
4.4 新手避坑指南
- 避坑1:局部变量和全局变量同名时,函数内部优先使用局部变量(全局变量被"屏蔽");
- 避坑2:函数内部访问全局变量,无需声明;修改全局变量,必须用global关键字声明;
- 避坑3:尽量不要让局部变量和全局变量同名,容易混淆,导致逻辑错误;
- 避坑4:全局变量适合存储"整个程序都需要使用的公共数据",不要滥用(否则会让代码逻辑混乱)。
5 匿名函数(lambda表达式):简洁的"一次性小函数"
在实际编程中,我们常会遇到"只需要使用一次的简单函数"(比如简单的计算、排序时的key函数),此时用def定义函数会显得繁琐------而匿名函数(lambda表达式),就是为这种场景设计的:一行代码定义简单函数,无需函数名,用完即丢,结合参考资料2中lambda的用法,简化适配新手。
5.1 lambda表达式的基础语法(一行搞定)
语法(新手必记):lambda 参数列表: 表达式
解析:
lambda:定义匿名函数的关键字(相当于def);- 参数列表:和普通函数的参数一致(可接收位置参数、默认参数、*args等,通常参数较少);
- 表达式:函数的核心逻辑,只能有一个表达式(不能有循环、多行条件语句),表达式的结果会自动作为返回值(无需写return);
- 匿名函数没有函数名,通常赋值给一个变量,通过变量调用,或直接作为参数传递(比如配合sorted、map等函数)。
python
# 示例1:用lambda定义简单的加法函数(对比def定义)
# 用def定义(繁琐,适合复杂函数)
def add_def(a, b):
return a + b
# 用lambda定义(简洁,适合简单函数)
add_lambda = lambda a, b: a + b # 赋值给变量add_lambda,通过变量调用
# 两种函数的调用方式一致
print(add_def(3, 5)) # 输出:8
print(add_lambda(3, 5)) # 输出:8
# 示例2:lambda表达式的核心特点(一个表达式、自动返回结果)
# 计算两个数的最大值(用lambda,一行搞定)
max_lambda = lambda a, b: a if a > b else b # 单行条件表达式(允许)
print(max_lambda(5, 8)) # 输出:8
# 示例3:无参数的lambda表达式
hello_lambda = lambda: "Hello, lambda!"
print(hello_lambda()) # 输出:Hello, lambda!
# 示例4:带默认参数的lambda表达式
power_lambda = lambda x, n=2: x **n # n默认值为2(平方)
print(power_lambda(3)) # 输出:9(3的平方)
print(power_lambda(3, 3)) # 输出:27(3的立方)
5.2 lambda表达式的常用场景(新手必学)
lambda的核心价值是"简洁",最常用的场景是:作为"临时函数"传递给其他函数(比如配合sorted排序、map映射),结合第四阶段的容器类型,实现高效编程。
python
# 场景1:配合sorted()排序(按列表中元组的第二个元素排序)
# 定义一个包含元组的列表(存储姓名和年龄)
students = [("张三", 19), ("李四", 17), ("王五", 18)]
# 用lambda作为key函数,按年龄排序(升序)
sorted_students = sorted(students, key=lambda x: x[1])
print("按年龄升序排序:", sorted_students)
# 输出:[('李四', 17), ('王五', 18), ('张三', 19)]
# 场景2:配合map()映射(将列表中所有元素乘以2)
nums = [1, 2, 3, 4, 5]
# 用lambda定义映射逻辑,map()批量处理元素
new_nums = list(map(lambda x: x * 2, nums))
print("所有元素乘以2:", new_nums) # 输出:[2, 4, 6, 8, 10]
# 场景3:配合filter()过滤(筛选列表中的偶数)
nums = [1, 2, 3, 4, 5, 6]
# 用lambda定义过滤条件,filter()筛选符合条件的元素
even_nums = list(filter(lambda x: x % 2 == 0, nums))
print("筛选列表中的偶数:", even_nums) # 输出:[2, 4, 6]
5.3 新手避坑指南
- 避坑1:lambda表达式只能有一个表达式,不能有循环、多行条件语句(if...elif...else),复杂逻辑请用def定义普通函数;
- 避坑2:lambda表达式没有函数名,不能直接调用,必须赋值给变量,或作为参数传递给其他函数;
- 避坑3:lambda适合"简单、一次性"的函数场景,不要用lambda写复杂逻辑(否则会让代码可读性变差);
- 避坑4:lambda表达式的参数列表,和普通函数的参数规则一致,传参时要匹配参数个数和类型。
6 函数嵌套与递归(基础版):解锁更复杂的函数逻辑
掌握了前面的基础后,我们来学习函数的进阶用法------函数嵌套与递归(基础版)。函数嵌套是"函数内部定义函数",实现逻辑封装;递归是"函数调用自身",解决可拆分的简单问题,结合参考资料1和3中的案例,简化成新手能理解的基础版本,不深入复杂逻辑。
6.1 函数嵌套(函数内部定义函数)
函数嵌套:在一个函数(外部函数)的内部,再定义另一个函数(内部函数),核心特点:
- 内部函数只能在外部函数内部访问和调用,外部无法直接访问;
- 内部函数可以访问外部函数的参数和局部变量(实现逻辑封装,隐藏内部细节);
- 外部函数可以返回内部函数,让内部函数在外部被调用(后续进阶讲解,基础版暂不深入)。
python
# 函数嵌套示例(外部函数+内部函数)
def outer_func():
"""外部函数"""
print("进入外部函数")
# 内部函数(在外部函数内部定义)
def inner_func():
"""内部函数,只能在外部函数内部访问"""
print("进入内部函数,访问外部函数的局部变量:", outer_num)
# 外部函数的局部变量
outer_num = 100
# 外部函数内部调用内部函数(正确)
inner_func()
print("退出外部函数")
# 调用外部函数(会触发内部函数的调用)
outer_func()
# 输出顺序:进入外部函数 → 进入内部函数,访问外部函数的局部变量:100 → 退出外部函数
# 错误:外部直接调用内部函数(超出作用域)
# inner_func() # 报错:name 'inner_func' is not defined
# 示例2:内部函数访问外部函数的参数
def calculate(a, b):
"""外部函数,接收两个参数"""
def add():
# 内部函数访问外部函数的参数a和b
return a + b
def subtract():
return a - b
# 外部函数返回内部函数的执行结果
return add(), subtract()
# 调用外部函数,获取内部函数的结果
add_res, sub_res = calculate(10, 5)
print(f"加法结果:{add_res},减法结果:{sub_res}") # 输出:15,5
核心总结:函数嵌套的核心是"封装内部逻辑",将复杂逻辑拆分成多个小函数,隐藏内部细节,让外部函数的调用更简洁。
6.2 递归(基础版):函数调用自身,解决简单问题
递归的核心:函数自己调用自己,就像"套娃"一样,适合解决"可以拆分成多个相同小问题"的场景(比如计算阶乘、斐波那契数列)。
新手必记:递归必须满足两个条件(否则会陷入无限递归,导致程序崩溃):
-
- 终止条件:存在一个明确的终止递归的条件(当满足条件时,不再调用自身);
-
- 递推关系:每次递归调用,都要让问题的规模"缩小"(比如计算n!,递推关系是n! = n * (n-1)!,规模从n缩小到n-1)。
基础示例1:计算n的阶乘(n! = 1×2×3×...×n,终止条件:n=1时,1! = 1),参考资料1中的阶乘案例,简化适配新手:
python
# 递归计算n的阶乘(基础版)
def factorial(n):
"""递归计算n的阶乘
参数:n -- 非负整数
终止条件:n == 1 或 n == 0 时,返回1
递推关系:n! = n * (n-1)!
"""
# 终止条件(必须有,否则无限递归)
if n == 0 or n == 1:
return 1
# 递推关系:函数调用自身,问题规模缩小(n → n-1)
return n * factorial(n - 1)
# 调用函数,测试结果
print(factorial(5)) # 输出:120(5! = 5×4×3×2×1 = 120)
print(factorial(3)) # 输出:6(3! = 3×2×1 = 6)
print(factorial(0)) # 输出:1(0! 规定为1)
基础示例2:递归计算斐波那契数列(前两项为1,从第三项开始,每一项等于前两项之和):
python
# 递归计算斐波那契数列的第n项(基础版)
def fibonacci(n):
"""递归计算斐波那契数列第n项
终止条件:n == 1 或 n == 2 时,返回1
递推关系:fib(n) = fib(n-1) + fib(n-2)
"""
if n == 1 or n == 2:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
# 调用函数,输出前10项斐波那契数列
for i in range(1, 11):
print(fibonacci(i), end=" ") # 输出:1 1 2 3 5 8 13 21 34 55
6.3 新手避坑指南(递归重点!)
- 避坑1:递归必须有明确的终止条件,否则会陷入无限递归(程序会报错"RecursionError",栈溢出);
- 避坑2:递归的递推关系必须让"问题规模缩小",否则即使有终止条件,也无法触发;
- 避坑3:Python的递归深度有限(默认约1000层),递归次数过多会报错,基础阶段不要用递归解决大规模问题;
- 避坑4:递归适合"简单、可拆分"的问题,复杂问题用循环(for/while)实现更高效(后续会对比)。
7 总结
到这里,Python3基础学习第五阶段「函数基础」的核心内容就全部梳理完毕了!这一阶段,我们从"函数的定义与调用"入手,逐步掌握了参数、返回值、局部与全局变量、匿名函数、函数嵌套与递归(基础版),每一个知识点都是Python模块化编程的基础,也是后续学习更高级内容(函数进阶、面向对象、模块与包)的关键。
对于新手来说,这一阶段的重点不是死记硬背语法,而是理解函数的核心价值(代码复用、模块化),并多动手练习,重点注意以下几点:
- 函数的定义与调用是基础,牢记def关键字的模板,注意缩进和调用方式,避免"只定义不调用";
- 函数参数是重点,分清4种参数类型的用法和顺序,尤其是可变参数
*args和**kwargs,多练习混合传参; - 分清return和print的区别,掌握return返回多个值的技巧,这是后续数据处理的常用方法;
- 搞懂局部变量与全局变量的作用域,记住"修改全局变量必须用global声明",避免变量报错;
- 匿名函数适合简单、一次性场景,复杂逻辑用普通函数,不要滥用lambda;
- 递归基础重点记"终止条件+递推关系",新手先练习简单案例(阶乘、斐波那契数列),不要追求复杂递归。
第五阶段的学习,难度比前四阶段略有提升,尤其是参数、局部全局变量、递归这三个知识点,新手容易踩坑。建议大家每天花30分钟,亲手敲写每个知识点的代码示例,修改参数、调试报错,感受函数的用法------只有多动手,才能真正吃透函数,让代码变得更简洁、更高效。
下一个阶段,我们将进入「函数进阶」的学习,重点攻克递归进阶、高阶函数、装饰器等内容,进一步提升代码的复用性和可读性。继续加油,稳步解锁Python编程的更多技能,离"合格的Python初学者"又近了一步~