王亟亟的Python学习之路(10)-函数对象的作用域,函数作为返回值,闭包

转载请注明出处:王亟亟的大牛之路

本来打算把工作的事周末做掉点,但是发现在外面浪并不能迅速集中投入,为了避免不必要的BUG 还是明天在家做吧,那么久写一篇Python的文章吧,毕竟背着Mac出门不做些太对不起自己的肩膀了



废话不多,直接说内容,这篇文章的内容大致是围绕“闭包”走的,介绍下相关理论知识

作用域:对象有其存活的范围
闭包:内部函数可以引用外部函数的参数和局部变量(是不是听得云里雾里的,没事 看例子就明白了)

就像循环内声明的对象,除了循环也就无法获取他的值一样。就像在java中声明的静态变量它的作用域就在整个类都有效一样。

那如果在非对象可存活的范围内操作了某个对象编译器也不会让我们通过的,像这样(拿一个错误的闭包函数来演示下)

那再上一个对的实现

也就引出了“高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回”。

我们来解释下这2个例子,首先外层有一个wdd函数,它里面有一个line函数因为我们图1他超出了合理的作用域所以编译器就报错了。

那我们再来分析下第二个例子,我们也是外面有一个wdd()函数,里面有一个line函数 函数返回值为 传入的参数x*2+50 然后line()函数的计算结果作为wdd()函数的返回值

这也就是我们所说的 函数作为返回值,实质上其实就是类似于 我们声明了一个 k 然后wdd()这个函数赋值给了k 然后line(x) 这个函数引用了外部函数的参数 5 然后计算出结果后的结果返回给了外部函数wdd。

那有些人问了 直接

print(wdd(5))

不行吗?

我们再贴个例子来看一下

def sumLogic2(*args):
    def addAll():
        sumValue2 = 0
        for k in args:
            sumValue2 = sumValue2 + k
        return sumValue2

    return addAll

这个例子跟wdd区别只是计算的算法不同,结果完全相同,主要看下不同的调用的结果

result = sumLogic2(1, 2, 3, 4, 5)
print(result())
print(sumLogic2(1, 2, 3, 4, 5))

结果:
15
<function sumLogic2.<locals>.addAll at 0x101b7b840>

这也就验证了我们刚才说的 我们 sumLogic2(1, 2, 3, 4, 5) 其实返回的是addAll()方法,调用函数result时,才真正计算结果。

再顺道上一下证明 内部函数可以引用外部函数的参数和局部变量 的例子

def wjj(z, x, c):
    a = 20

    def wjj2():
        return a*(z * x * c)

    return wjj2

k = wjj(2, 3, 4)
print(k())

结果:
480

这个例子不仅引用了局部变量,也使用了外部传入wjj方法的参数。

那我们每次调用同一个外部函数返回的是同一个对象吗?

拿刚才的result验证下

def sumLogic2(*args):
    def addAll():
        sumValue2 = 0
        for k in args:
            sumValue2 = sumValue2 + k
        return sumValue2

    return addAll

result = sumLogic2(1, 2, 3, 4, 5)
print(result())
print(sumLogic2(1, 2, 3, 4, 5))

result2 = sumLogic2(1, 2, 3, 4, 5)

print(result == result2)

结果:
15
<function sumLogic2.<locals>.addAll at 0x101b7b840>
False

那也就说明调用结果互不影响。

是不是对大致的使用 有了点概念?

什么? 还不清楚,还是觉得闭包没用? 那么看以下例子

def line_conf(a, b):
    def line(x):
        return a*x + b
    return line

line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5), line2(5))

结果:

6 25

这个例子中,函数line与环境变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个环境变量的取值,这样,我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,我们可以看到,闭包也具有提高代码可复用性的作用。

如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。这样,我们就需要更多的参数传递,也减少了代码的可移植性。利用闭包,我们实际上创建了泛函。line函数定义一种广泛意义的函数。这个函数的一些方面已经确定(必须是直线),但另一些方面(比如a和b参数待定)。随后,我们根据line_conf传递来的参数,通过闭包的形式,将最终函数确定下来。

是不是发现瞬间觉得有那么点用了?



现在手头运作一些公司的职位,有兴趣的小伙伴可以U 简历到452270579@qq.com

公司:Pactera 地点:上海 职位: Java PHP Android UI设计 .Net 服务于平安好车项目(大企业,大项目)

公司:阿里巴巴 地点 :上海,杭州,北京 职位: Android/iOS 淘宝/蚂蚁/其他子公司(有一定能力,学历要求)

公司:暴走漫画 地点:上海 职位:Android/iOS 暴走大事件配套App产品(大用户量产品)



源码:https://github.com/ddwhan0123/PythonExample/blob/master/示例/l8Demo.py

最后一个例子来源于:http://www.cnblogs.com/vamei/archive/2012/12/15/2772451.html

时间: 2024-08-24 08:20:03

王亟亟的Python学习之路(10)-函数对象的作用域,函数作为返回值,闭包的相关文章

王亟亟的Python学习之路(六)-递归,迭代,列表生成式

转载请注明出处:王亟亟的大牛之路 最近事情比较多,也没什么时间学习.(借口,明明在偷懒) 难得空下来,就继续把文章写下去.(玩手游时间更多) 在贴今天要写的内容之前还是先说一下某些概念!(概念还是很重要的,虽然更重要的是理解) 什么是递归?(维基来的) 白话的理解就是某函数自己调用自己 大牛的分析: 递归的基本思想是把规模大的问题转化为规模小的相似的子问题来解决.在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况.另外这个解决问题的函数必须有明

王亟亟的Python学习之路(四)-循环,条件,Range,list和tuple

转载请注明出处:王亟亟的大牛之路 这是本次Python学习历程的第4篇,之前的文章:传送门 这篇主要讲以下几个知识点 - 循环 - 条件语句 - range函数 - list - tuple 循环 Python中的循环语句有 for 和 while.同样需要注意冒号和缩进.另外,在Python中没有do..while循环. 需要注意冒号和缩进,因为没有{}来帮助我们把循环里面的内容封起来 while循环 while 判断逻辑: 业务内容 或者for-in循环 names = ['12',12,

王亟亟的Python学习之路(五)-dictionary,set,函数,函数参数

转载请注明出处王亟亟的大牛之路 上一篇说的是循环,条件,Range,list和tuple,今天将从函数(方法)开始进一步的学习 -dictionary -set -函数 -函数参数 dictionary 键-值(key-value)存储,具有极快的查找速度.为什么反复提起查询速度,因为如果你一个用list只是为了获取里面X元素内容的话性能是相对比较查的,极力推荐"字典",字典也在第三片文章中有列出,但是这里还是再丰富下他的一些常用方法. 如何获检索dic内的值 dic={'wjj':1

王亟亟的Python学习之路(一)-环境搭建

轉載請注明出處王亟亟的大牛之路 楼主因为正好对Python这门高级语言感兴趣,然后经过一定的学习,总结下一些经验和知识点,分享给大家,这一系列会由浅至深,因为本身就不是从业余Python相关开发纯粹兴趣,如有不对请提出,谢谢哈! 言归正传,这篇讲下简单的环境搭建,百度其实也有,但是还要自己找资源,楼主在这边给各位客官都整理好了,您只需要下载一下就好了,哈哈 现在主流的有Python2.x系列和3.x系列.我的一系列文章将从3.X的版本展开,请大家理解,这其中还是会有很大区别的! 首先 贴下载地址

王亟亟的Python学习之路(10)-匿名函数

转载请注明出处:王亟亟的大牛之路 又有好多天没有碰Python的东西了,下午抽出点时间就补一篇介绍匿名函数 匿名函数在很多语言里都有,它可以使代码更加简洁.紧凑,模块化程度更高. 在jdk8里发现了lambda表达式的影子 以前我们要循环一个集合需要这样 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); for (int number : numbers) { System.out.println(number); } 现在可以这

王亟亟的Python学习之路(九)-sorted()排序以及简单字符串处理

转载请注明出处:王亟亟的大牛之路 这一片就讲2个知识点,1排序,2字符串处理 Python在排序操作的这一部分做了很好的封装,我们不需要写太多代码就可以实现排序的效果,先贴下Java的实现.(这里不是黑Java!!!!) public class 直接插入排序 { public static void main(String[] args) { int[] a={49,38,65,97,76,13,27,49,78,34,12,64,1}; System.out.println("排序之前:&q

王亟亟的Python学习之路(二)-项目创建以及要点提及

转载请注明出处王亟亟的大牛之路 首先,说一下上一篇为什么虽说我们是从3.X开始说起,那就要说明下2个版本的区别(上下版本几乎没关系) Python的3​​.0版本,常被称为Python 3000,或简称Py3k.相对于Python的早期版本,这是一个较大的升级. 为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下相容.不兼容哦!! 许多针对早期Python版本设计的程式都无法在Python 3.0上正常执行. 为了照顾现有程式,Python 2.6作为一个过渡版本,基本使用了Py

王亟亟的Python学习之路(三)-基础语法以及基本数据类型

转载请注明出处:王亟亟的大牛之路 理论知识虽然很枯燥,但是你以后的高度取决于你基础的厚度 每种语言多多少少都有它的保留关键字 JAVA的: Python的: 那关键字是什么? 电脑语言里事先定义的,有特别意义的标识符,有时又叫保留字,还有特别意义的变量. 注释 java: -单行 // -多行/** **/ Python: 单行# 多行''' 数据类型 整数:诸如 1 2 3 -1 -2 10 0 这种都算,当然计算机是 2进制干活的,所以 2进制 10进制 16进制的整形数据都算....你懂的

王亟亟的Python学习之路(八)-函数式编程,map(),reduce(),filter()

转载请注明出处:王亟亟的大牛之路 首先在这里祝愿大家,新年快乐,工作顺利,BUG少少!!! 本来说是在春节假期内继续维持着写文章的进度,但是还是偷懒了几天(打了4天SC2哈哈哈) 今天上的是关于Python的文章,毕竟在亲戚家拜年,懒得插各类手机调试什么的,况且确实好久没有弄Python了,就写了,废话不多,开始正题!! 函数式编程 函数是什么? 把复杂的操作化为简单的函数分解成简单的操作,这种操作就是面向过程,也就是C这类的实现的大体概念. 函数式是什么? 函数没有变量,任意一个函数,只要输入