返回函数和闭包

一、返回函数:

一个函数可以返回一个计算结果,也可以返回一个函数

def lazy_sum(*args):def sum():           # 通常情况下,无需这一列,但如果不需要立刻求和,可以不返回求和的结果,而是返回求和的函数for n in args:ax=ax+0return axreturn sum   # 内部函数sum直接作为返回值返回了。为什么不带括号呢,当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它

当我们调用lazy_sum()时,返回的并不是求和结果ax,而是求和函数sum

>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f       # f现在指向到lazy_sum()函数中的sum()函数,但并未执行它,sum()函数未被调用
<function lazy_sum.<locals>.sum at 0x101c6ed90>

调用函数f时,才真正计算求和的结果:

>>> f()      # # f现在指向到lazy_sum()函数中的sum()函数,把一对小括号放在后面,这个函数就会执行
25

“闭包(Closure)”程序结构:
在函数lazy_sum中又定义了函数sum
内部函数sum可以引用外部函数lazy_sum的参数和局部变量args
lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中


二、闭包

一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)

(一)注意:

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。例如:

def count():   # 第一层函数fs = []    # 定义一个空列表for i in range(1, 4):     # 循环变量idef f():    # 第二层函数return i*i       # 第二层函数返回引用了循环变量!!!fs.append(f)return fsf1, f2, f3 = count()

实际结果是:全都是9! **
原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。**

>>> f1()  # 不加括号返回的是函数,加了才是调用函数的结果
9
>>> f2()
9
>>> f3()
9

不得已的情况下:

返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量
如果一定要引用循环变量:
再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

def count():def f(j):     # 第二层函数用它的参数绑定循环变量的值i!def g():  # 第三层函数引用了循环变量return j*j   # 第三层函数返回中引用了循环变量的值return g  # 第二层函数返回第三层函数吗,无需带括号fs = []       # 定义一个空列表for i in range(1, 4):    # 和第二层函数平级fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()return fs     # 第一层函数返回结果

以下为结果:

再看看结果:

>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

(二)注意:

闭包无法直接访问外部函数的局部变量

def outer():x = 5 def inner(): #上面一行的x相对inner函数来说是函数外的局部变量(非全局变量)x *= xreturn xreturn inner
outer()()       # 会报错

解决方法:

**如果想在函数体内对全局变量赋值,需要使用关键字global; **
而嵌套函数中通过nonlocal关键字来解决:

def outer():x = 5 def inner(): nonlocal x #把x声明为非局部变量x *= xreturn xreturn inner print(outer()())

(三)Task:

利用闭包返回一个计数器函数,每次调用它返回递增整数:

1.方法一

def createCounter():num=[0]def counter():num[0]+=1return num[0]return counter  # 内部函数counter直接作为返回值返回了。为什么不带括号呢,因为函数名其实就是指向函数的变量.# 测试:
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = createCounter()
if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:print('测试通过!')
else:print('测试失败!')

2.方法二

def createCounter():res = {'sum': 0}def counter():res['sum'] += 1return res['sum']return counter

参考网站(菜鸟教程)

参考网站(廖雪峰官方网站)

对Python【返回函数与闭包】的一点思考相关推荐

  1. python学习-高阶函数(函数传参、返回函数(闭包)、匿名函数lambda)

    文章目录 高阶函数 函数传参 返回函数(闭包) 匿名函数lambda 高阶函数 定义: 至少满足下列一个条件: 接受一个或多个函数作为输入 输出一个函数 python里的高阶函数有 filter.ma ...

  2. python 返回函数 闭包_python中闭包Closure函数作为返回值的方法示例

    前言 首先看看闭包的概念:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外 ...

  3. python 返回函数对象_Python—函数对象与闭包

    一 函数对象 函数对象指的是函数可以被当做"数据"来处理,具体可以分为四个方面的使用. 1.1 函数可以被引用 def index(): print('from index') a ...

  4. 一篇文章带你搞定Python返回函数

    一.什么是返回函数? 返回函数,简单的说就是返回值是一个函数. 返回的是函数,调用返回的函数的时候才会返回结果. 二.闭包 (以返回函数的形式实现) 相关参数和变量都保存在返回的函数中,这种称为&qu ...

  5. python 返回函数对象_返回函数

    函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_sum(*args): ax = ...

  6. python 返回函数

    返回函数 Python的函数不但可以返回int.str.list.dict等数据类型,还可以返回函数!例如,定义一个函数 f(),我们让它返回一个函数 g,可以这样写:def f():print 'c ...

  7. Python——返回函数

    一. 返回函数 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. >>> def lazy_sum(*args): ... def sum(): ... z = 0 ...

  8. Python将函数作为闭包

    在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包.闭包可以用来在一个函数与一组"私有"变量之间创建关联关系.在给定函数被多次 ...

  9. python 返回函数 变量_你如何设置一个变量等于由python函数返回的值

    我试图设计一个系统,允许我在点击时将精灵移动到光标位置,类似于RuneScape,玩家将移动到鼠标在屏幕上单击的位置.以下是我的代码如下: for event in pygame.event.get ...

  10. 关于机器学习 Machine Learning中loss函数参数正则化的一点思考

    1 致谢 感谢 Andrew Ng教授的讲述! 2 前言 今天在学习机器学习中对loss函数中的参数进行正则化~ 3 关于机器学习中loss函数参数正则化 在机器学习中,有一项防止过拟合的技巧就是(参 ...

最新文章

  1. svn 常见问题记录
  2. smarty半小时快速上手入门教程
  3. 荣耀 6 安装 SD 卡,提示:SD卡已安全移除
  4. ubuntu 16.04 安装MySQL Workbench
  5. STS安装 activiti-designer-5.18.0插件
  6. Jeecg-P3 1.0版本发布,JAVA插件开发框架
  7. 『中级篇』手动建立一个base Image(14)
  8. UVA11760 Brother Arif, Please feed us!【bitset】
  9. java文件虚拟路径_java虚拟路径的总结
  10. Redisson 3.13.6 发布,官方推荐的 Redis 客户端
  11. 社交APP软件开发流程解析
  12. java一般安装在哪_安装Java时不知道安在哪?
  13. 在RecyclerView里使用图片轮播
  14. webrtc视频卡顿分析一本地视频卡顿
  15. ThinkPHP3.0主入口配置,注册、登录案例
  16. 【Numpy】选择特定行列
  17. 整数大小比较(YZOJ-1034)
  18. 实验内容:实验六 数组冒泡排序
  19. 机器学习 深度学习 神经网络 图像处理优质博客整理
  20. python 凯撒加密

热门文章

  1. 【毕业设计】深度学习人脸性别年龄识别系统 - python
  2. 图片转Word文档怎么转?这两种转换方法学起来
  3. 音色、音高、音强、音长
  4. pose_subscriber.cpp
  5. R语言常见报错及解决方法
  6. 这五个方法能提高程序员工作效率
  7. 1317: PIPI的生日礼物
  8. 小学计算机课打字游戏,小学信息技术打字游戏教案
  9. 关于app申请软件著作权登记时软件名称命名的问题
  10. 面试珠玑 嵌入式C程序员经典笔试题一