**函数作为返回值**
在高阶函数那一讲,我们已经知道了,高阶函数可以接受函数作为参数,其实函数也可以作为结果值返回。
在函数嵌套那一讲我们讲了这么一个例子
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myAdd(a,b):
'''两数求和悄悄加一'''
sum = a + b
def innerAdd(num):
return num + 1
sum = innerAdd(sum)
return sum
print(myAdd(1,2))
~~~
我们直接把两数求和再加一的结果返回了,如果不需要立刻知道结果,而是在后面的代码中,根据需要再计算怎么办?所以就不能直接返回结果了,而是返回计算的函数。
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def myAdd(a,b):
'''两数求和悄悄加一'''
sum = a + b
def innerAdd():
return sum + 1
return innerAdd
f = myAdd(1,2)
#第一次打印
print(f)
#第二次打印
print(f())
#第三次打印
print(myAdd(1,2) == myAdd(1,2))
~~~
运行结果
~~~
airvip@airvip$ ./test.py
#第一次打印结果
<function myAdd.<locals>.innerAdd at 0x7f5b2a1ac6a8>
#第二次打印结果
4
#第三次打印结果
False
~~~
当我们调用 myAdd() 时,返回的并不是最终的结果,而是一个函数,再调用函数 f 时,才真正计算得到结果。
需要特别注意第三次打印的结果为 False 假。
在这个例子中,我们在函数 myAdd 中又定义了函数 innerAdd,内部函数 innerAdd 可以使用用外部函数 myAdd 的参数和局部变量,当 myAdd 返回 innerAdd 函数时,其调用的参数和变量都已经保存在返回的函数中,这种方式称为“闭包(Closure)”。
另外当一个函数返回了一个函数后,其内部的局部变量还被新函数使用中,返回的函数并没有立刻执行,只有调用了之后才执行,我们来看下面这个例子。
~~~
>>> def myAdd(a,b):
... Fl = []
... sum = a+b
... for i in range(2):
... def innerAdd():
... return sum + i
... Fl.append(innerAdd)
... return Fl
~~~
在程序中每次循环都创建了一个新的函数,最后一起把创建的函数都返回了
调用,我们想要的结果是 3,4 ,然而真实结果却是:
~~~
>>> f1,f2 = myAdd(1,2)
>>> f1()
4
>>> f2()
4
~~~
结果全为 4 ,这是为什么呢?因为返回的函数引用了变量 i,它并没有立刻执行。等到所有函数都返回时,它们使用的变量 i 已经都变成了 1,所以结果就都是 4 了。
那如何解决呢?想办法将传入函数的参数绑定在函数上无法修改,这就需要再创建一个函数。
~~~
>>> def myAdd(a,b):
... Fl = [];
... sum = a+b
... def center(i):
... def innerAdd():
... return sum + i
... return innerAdd
... for i in range(2):
... Fl.append(center(i))
... return Fl
...
~~~
再次调用
~~~
>>> f1,f2 = myAdd(1,2)
>>> f1()
3
>>> f2()
4
~~~
总结:
每次调用以函数作为返回值的函数时,即便传递的参数一模一样,返回的结果也不同。
在编写返回函数时,一定不要使用任何后续操作会发生变化的变量。
- 跟老司机学Python
- 了解Python
- 1、python简介
- 2、Python发展史
- 3、Python特点
- 4、Python解释器
- 入坑Python
- 1、Python环境搭建
- 2、设置环境变量
- 3、开始使用Python
- 4、运行Python程序
- 掌握Python基础
- Python基础知识
- Python运算符
- 算术运算符
- 比较运算符
- 赋值运算符
- 逻辑运算符
- 位运算符
- 成员运算符
- 身份运算符
- 运算符优先级
- Python的变量与常量
- Python数据类型
- Number数值
- String字符串
- List列表
- Tuple元组
- Dictionary字典
- Set集合
- Python流程控制语句
- 条件判断
- 循环控制
- Python函数
- 1、函数是什么
- 2、函数的定义
- 3、函数的参数
- 4、函数的调用
- 5、嵌套函数
- 6、递归函数
- 7、匿名函数
- 8、函数式编程
- 9、高阶函数
- 1、map
- 2、reduce
- 3、filter
- 4、sorted
- 10、返回函数
- 11、偏函数
- Python文件IO操作
- 标准输入输出
- 读写文件
- with读写文件
- Python高级特性
- 1、列表生成式
- 2、迭代器
- 3、生成器
- 4、装饰器
- Python模块初探
- 1、模块与包
- 2、创建模块
- 3、模块中的作用域
- 4、模块的导入
- Python面向对象编程
- 类与对象
- 类的定义及使用
- 面向对象特性
- 类中的访问域
- 查看对象详情
- Python面向对象进阶
- 类中的方法
- 类中的特殊成员
- 限制对象的属性
- 再聊多继承
- 装x式创建类
- 创建元类
- Python内置模块
- os模块
- sys模块
- random模块
- time模块
- datetime模块
- shutil模块
- collections模块
- base64模块
- json模块
- hashlib模块
- xml模块
- 1. SAX解析XML
- 2. DOM解析XML
- 3. ElementTree解析XML
- urllib模块
- logging模块
- re模块
- Python第三方模块
- Pillow与PIL
- Requests
- Tablib
- Xpinyin
- Chardet
- Pycurl
- Virtualenv
- Python操作数据库
- Mysql操作
- Sqllite操作
- Mongodb操作
- Redis操作
- Python的GUI编程
- Python中GUI的选择
- Tkinter
- wxPython
- Socket网络编程
- Socket网络编程简聊
- Socket内建方法
- TCP协议编程
- UDP协议编程
- TCP与UDP
- Python电子邮件
- SMTP发邮件
- POP3收邮件
- IMAP收邮件
- 进程线程
- 进程与线程
- 进程编程
- 使用进程池
- 进程间的通信
- 线程编程
- 使用线程锁
- Python的GIL
- Web编程
- WSGI介绍
- Web框架
- Flask使用
- 模板jinjia2使用
- 项目结构规划
- 异步与协程
- 概念扫盲
- 异步IO进化之路
- 协程是什么
- yield协程编程
- yield from
- asyncio
- async与await
- aiohttp之client
- aiphttp之server
- 网络爬虫
- 网络爬虫简聊
- Beautiful Soup模块的使用
- pyquery 模块的使用
- selenium模块的使用
- 爬取段子实例
- 错误与调试
- 错误
- 错误处理
- 抛出错误
- 高效的调试
- Python重要语句
- pass语句
- return语句
- Python开发必知
- pip使用详解
- 如何对列表进行迭代
- 如何对字典进行迭代
- 字符串格式化
- 知识扩展
- 网络模型
- GUI是什么