网站首页 > 技术文章 正文
点赞、收藏、加关注,下次找我不迷路
一、啥是返回函数?先从生活里找灵感
先不聊代码,想想生活中的场景。比如你让朋友帮你带杯奶茶,朋友买完奶茶后把奶茶递给你,这就相当于函数返回了一个具体的 "值",也就是这杯奶茶。那如果朋友说:"我给你一个制作奶茶的秘方,你自己随时都能做",这秘方就好比是一个 "函数",朋友返回给你的不是具体的奶茶,而是一个能制作奶茶的方法。这就是返回函数最核心的概念 —— 函数的返回值是一个函数本身。
在 Python 里,函数和普通的变量、数字、字符串一样,都是一种数据类型,所以函数完全可以作为另一个函数的返回值。比如下面这个简单的例子:
def get_greeting():
def say_hello():
print("Hello!")
return say_hello
这里的get_greeting函数里面定义了一个say_hello函数,然后把say_hello作为返回值返回。这时候,当我们调用get_greeting时,得到的不是一个具体的结果,而是say_hello这个函数本身。
greeting = get_greeting()
greeting() # 输出 Hello!
就像拿到了朋友给的奶茶秘方,你随时可以用这个秘方去制作奶茶(调用返回的函数)。
二、返回函数的常见玩法
(一)返回普通函数:最基础的操作
先来看一个超级简单的例子,我们定义一个函数make_add_function,它接受一个数字n作为参数,然后返回一个新的函数add_n,这个add_n函数可以把传入的数字加上n。
def make_add_function(n):
def add_n(x):
return x + n
return add_n
add_5 = make_add_function(5)
print(add_5(3)) # 输出 8
这里就好像是一个工厂,make_add_function根据不同的n(比如 5),生产出不同的加法函数add_5,当我们用这个函数去计算3+5时,就得到了 8。
(二)返回闭包:记住外部函数的变量
这里有个重要的概念叫 "闭包"(Closure)。简单来说,就是内部函数引用了外部函数的变量,并且外部函数返回这个内部函数后,外部函数的变量依然会被保留在内存中,供内部函数使用。
比如我们想创建一系列函数,每个函数都能计算从 1 累加到某个数的和。用返回闭包的方式可以这样做:
def make_accumulator(start):
count = start
def accumulate(n):
nonlocal count # 声明count不是当前函数的局部变量
count += n
return count
return accumulate
acc = make_accumulator(0)
print(acc(10)) # 输出 10
print(acc(20)) # 输出 30
print(acc(30)) # 输出 60
这里的count是make_accumulator函数中的变量,当acc函数被调用时,它会记住count的值,每次调用都会在之前的基础上累加。就像一个记账本,每次记录一笔账,余额都会更新并保存下来。
为了让大家更好地理解返回普通函数和返回闭包的区别,咱们用个表格来对比一下:
特点 | 返回普通函数 | 返回闭包 |
对外部变量的引用 | 不引用外部函数的变量 | 引用外部函数的变量 |
变量保存 | 外部函数执行完,变量被释放 | 外部函数执行完,变量依然保留在内存中 |
典型场景 | 简单的函数工厂,如根据参数生成不同功能的函数 | 需要保留状态,如累加器、计数器等 |
(三)返回匿名函数:简洁至上
在 Python 中,我们可以用lambda表达式来创建匿名函数,也就是没有名字的函数。当我们需要返回一个简单的函数时,用lambda会让代码更简洁。
比如前面的make_add_function函数,我们可以用lambda来改写:
def make_add_function(n):
return lambda x: x + n
add_3 = make_add_function(3)
print(add_3(5)) # 输出 8
这样写是不是更简洁了?lambda表达式直接定义了一个匿名的加法函数并返回。
三、返回函数的注意事项
(一)变量作用域:别让变量 "失踪" 了
在闭包中,一定要注意变量的作用域问题。如果内部函数修改了外部函数的变量,在 Python 3 中需要用nonlocal关键字声明,否则会报错。比如下面这个例子:
def outer():
x = 10
def inner():
x = 20 # 这里会报错,因为默认认为x是inner函数的局部变量,而在赋值前被引用
print(x)
inner()
outer()
正确的做法是使用nonlocal声明:
def outer():
x = 10
def inner():
nonlocal x
x = 20
print(x)
inner()
print(x) # 输出 20
outer()
(二)避免内存泄漏:适时释放不再需要的函数
虽然闭包很方便,但如果大量使用闭包,并且长时间保留对闭包的引用,可能会导致内存泄漏。所以,当我们不再需要某个闭包函数时,应该及时将其赋值为None,让垃圾回收机制回收内存。
(三)调试技巧:打印函数对象和调用过程
当我们拿到一个返回的函数时,可以先打印一下这个函数对象,看看它是不是我们期望的函数。比如:
def get_function():
def func():
print("This is a function.")
return func
f = get_function()
print(f) # 输出 <function get_function.<locals>.func at 0x...>
这样可以确认我们确实得到了正确的函数。在调用过程中,如果出现问题,可以在函数内部添加打印语句,跟踪变量的值,帮助我们定位问题。
四、轻松记住返回函数的核心要点
为了让大家更容易记住返回函数的知识点,咱们来总结几个记忆诀窍:
(一)"返回函数像传球,传来传去是方法"
返回函数就像是在传球,这个球不是具体的数值,而是一个可以执行的方法(函数)。我们可以把这个 "球"(函数)保存起来,随时调用它。
(二)"闭包就像小仓库,记住变量不遗忘"
闭包就像是一个小仓库,内部函数把外部函数的变量 "存" 在里面,即使外部函数执行完了,这些变量依然在仓库里,不会被遗忘,内部函数随时可以拿出来用。
(三)"nonlocal 关键字要牢记,修改变量别忘记"
如果在闭包的内部函数中要修改外部函数的变量,一定要记得用nonlocal关键字声明,就像在仓库里拿东西出来修改,得先告诉大家你要修改的是仓库里的东西,而不是自己新弄的东西。
五、返回函数在实际开发中的场景
(一)装饰器:Python 编程中的 "魔法披风"
装饰器是返回函数的一个非常重要的应用场景。装饰器可以在不修改原函数代码的情况下,为函数添加新的功能,比如日志记录、性能统计、权限验证等。
装饰器的内容可以看看我的另一篇文章:
比如我们定义一个日志装饰器:
def log_decorator(func):
def wrapper():
print(f"开始调用函数 {func.__name__}")
func()
print(f"函数 {func.__name__} 调用结束")
return wrapper
@log_decorator
def say_hi():
print("Hi!")
say_hi()
这里的log_decorator函数接受一个函数func作为参数,返回一个wrapper函数,wrapper函数在调用原函数前后添加了日志打印功能。@log_decorator语法糖就是对say_hi函数应用了这个装饰器。
(二)函数工厂:批量生成相似功能的函数
当我们需要创建多个功能相似但参数不同的函数时,函数工厂(返回函数的函数)就派上用场了。比如前面提到的make_add_function,可以根据不同的n生成不同的加法函数。
(三)状态保持:让函数记住 "过去"
闭包的特性使得返回的函数可以保持外部函数的变量状态,这在需要记录状态的场景中非常有用,比如计数器、游戏中的角色状态管理等。
我们知道了返回函数就是函数返回一个函数本身,它有返回普通函数、返回闭包、返回匿名函数等玩法,还了解了使用返回函数时的注意事项和实战应用场景。记住那几个记忆诀窍,多动手写例子练习,相信你很快就能熟练掌握返回函数啦!
如果大家还有什么疑问,欢迎在评论区留言,咱们一起讨论交流。觉得这篇文章有用的话,别忘了点赞、收藏和分享哦!
猜你喜欢
- 2025-06-10 想要提升Python代码效率?这五个高级方法是必须要会的
- 2025-06-10 新手学Python避坑,学习效率狂飙! 二十一、print()函数
- 2025-06-10 新手学Python避坑,学习效率狂飙!十九、break 与 continue
- 2025-06-10 新手学Python避坑,学习效率狂飙!十三、if语句和while语句
- 2025-06-10 Python自动化办公:打工人常用的10个效率工具,告别加班!
- 2025-06-10 Python的10个神级冷门技巧,让代码效率翻倍!
- 2025-06-10 提升Python编程效率的10点建议(python小技巧及速度提高)
- 2025-06-10 90%的Python程序员都不知道的(效率密码 )函数让代码直接封神!
- 265℃Python短文,Python中的嵌套条件语句(六)
- 264℃python笔记:for循环嵌套。end=""的作用,图形打印
- 263℃PythonNet:实现Python与.Net代码相互调用!
- 259℃Python实现字符串小写转大写并写入文件
- 257℃Python操作Sqlserver数据库(多库同时异步执行:增删改查)
- 117℃原来2025是完美的平方年,一起探索六种平方的算吧
- 98℃Python 和 JavaScript 终于联姻了!PythonMonkey 要火?
- 90℃Ollama v0.4.5-v0.4.7 更新集合:Ollama Python 库改进、新模型支持
- 最近发表
-
- 想要提升Python代码效率?这五个高级方法是必须要会的
- 函数还能返回函数?Python 这个神操作让代码效率翻倍
- 新手学Python避坑,学习效率狂飙! 二十一、print()函数
- 新手学Python避坑,学习效率狂飙!十九、break 与 continue
- 新手学Python避坑,学习效率狂飙!十三、if语句和while语句
- Python自动化办公:打工人常用的10个效率工具,告别加班!
- Python的10个神级冷门技巧,让代码效率翻倍!
- 提升Python编程效率的10点建议(python小技巧及速度提高)
- 90%的Python程序员都不知道的(效率密码 )函数让代码直接封神!
- 【Python】性能加速之解析器加速Pypy 库使用说明
- 标签列表
-
- python中类 (31)
- python 迭代 (34)
- python 小写 (35)
- python怎么输出 (33)
- python 日志 (35)
- python语音 (31)
- python 工程师 (34)
- python3 安装 (31)
- python音乐 (31)
- 安卓 python (32)
- python 小游戏 (32)
- python 安卓 (31)
- python聚类 (34)
- python向量 (31)
- python大全 (31)
- python次方 (33)
- python桌面 (32)
- python总结 (34)
- python浏览器 (32)
- python 请求 (32)
- python 前端 (32)
- python验证码 (33)
- python 题目 (32)
- python 文件写 (33)
- python中的用法 (32)