一、思考一个问题

我们要给定一个x,要求一条直线上x对应的y的值。公式是y = kx+b。

我们需要用k,b来确定这条直线,则我们实现的函数应该有3个参数:

def line(k, b, x):
print(k * x + b) line(1, 3, 4)
line(1, 3, 5)
line(1, 3, 6)

可以看到,我们每次修改x都要重新传入k和b。

我们也可以用全局变量来实现:

k = 1
b = 3 def line(x):
print(k * x + b) line(4)
line(5)
line(6)

k和b为全局变量,但如果我们想要另外一条不同的直线时,则还需要重新定义k和b的值,同样不合理。而且全局变量会暴露给其他不相关的函数,容易造成冲突,或代码混乱。

用面向对象来实现:

class Line(object):
def __init__(self, k, b):
self.k = k
self.b = b def create_y(self, x):
print(self.k * x + self.b) l1 = Line(1, 3)
l1.create_y(4)
l1.create_y(5)
l1.create_y(6)

用类和对象来实现肯定是可以的,但是这么一个简单的功能使用面向对象比较浪费资源。

二、使用闭包

def line(k, b):
def create_y(x):
print(k * x + b) return create_y l1 = line(1, 3)
l1(4)
l1(5)
l1(6)

从以上代码可以直观的看到,闭包有以下几个条件:

1.在一个外函数中定义了一个内函数。

2.内函数里运用了外函数的临时变量。

3.并且外函数的返回值是内函数的引用。

一个函数结束的时候,会把自己的临时变量都释放给内存,之后变量都不存在了。一般情况下,确实是这样的。但是闭包是一个特别的情况。外部函数发现,自己的临时变量会在将来的内部函数中用到,自己在结束的时候,返回内函数的同时,会把外函数的临时变量和内函数绑定在一起。所以外函数已经结束了,调用内函数的时候仍然能够使用外函数的临时变量。

三、内层函数修改外层函数临时变量

def line(k, b):
multi = 10; def create_y(x):
print((k * x + b) * multi) return create_y l1 = line(1, 3)
l1(4)
l1(5)
l1(6)

假设外层函数中有一个multi变量,这个变量可以提供给内层函数访问,但是如果内层函数想修改这个multi变量怎么办呢?

在python3.x中,我们可以使用nonlocal关键字来实现:

def line(k, b):
multi = 10; def create_y(x):
nonlocal multi
multi = 5
print((k * x + b) * multi) return create_y l1 = line(1, 3)
l1(4)
l1(5)
l1(6)

这个nonlocal类似与global的作用,但是global是用于修改全局变量,而nonlocal是用于修改闭包中的外层临时变量。

如果在python2.x中,则不存在nonlocal关键字,我们可以通过将multi变为可变类型数据来实现:

def line(k, b):
# python2.x中将multi变为列表
multi = [10] def create_y(x):
# 可以对外层函数的列表进行修改
multi[0] = 5
print((k * x + b) * multi[0]) return create_y l1 = line(1, 3)
l1(4)
l1(5)
l1(6)

四、闭包和函数、对象等的区别

函数(包含匿名函数):只是功能代码,不包含数据。

对象:包含数据和功能实现。

闭包:包含数据和功能实现。数据指外层函数接收到的参数以及他的局部变量,功能指内层函数的功能。

当函数、匿名函数、对象和闭包做为实参传递时,他们有什么区别????

1.函数和匿名函数被当做实参传递时,传递的是功能的引用,可以通过该引用调用他们实现的功能。但数据需要另外提供。

2.闭包被当做实参传递时,其实传递了数据+功能。例如:

def line(k, b):
# python2.x中将multi变为列表
multi = [10] def create_y(x):
# 可以对外层函数的列表进行修改
multi[0] = 5
print((k * x + b) * multi[0]) return create_y def function(func):
func(5) function(line(1, 3))

我们可以看到,闭包line被传入function,实际上带着数据k=1,b=3。

而如果是普通函数:

def line_norm(k, b, x):
print(k * x + b) def function(func):
func(1, 3, 5) function(line_norm)

这里的k=1,b=3是function函数自己提供的。

3.对象被当做实参传递时,该对象中的成员属性作为数据,成员方法作为方法,都被传递给function函数。

class Line(object):
def __init__(self, k, b):
self.k = k
self.b = b def create_y(self, x):
print(self.k * x + self.b) line1 = Line(1, 3) def function(inst):
inst.create_y(5) function(line1)

[Python之路] 闭包的更多相关文章

  1. 百万年薪python之路 -- 闭包

    2.闭包 闭包的定义: 闭包是嵌套在函数中的函数. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用. 一句话定义就是:在嵌套函数内,对非全局变量 (且不是本层的变量)的引用 如何判断判断闭包? ...

  2. Python之路【第一篇】python基础

    一.python开发 1.开发: 1)高级语言:python .Java .PHP. C#  Go ruby  c++  ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...

  3. Python之路

    Python学习之路 第一天   Python之路,Day1 - Python基础1介绍.基本语法.流程控制              第一天作业第二天   Python之路,Day2 - Pytho ...

  4. python之路 目录

    目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...

  5. 说说Python中的闭包 - Closure

    转载自https://segmentfault.com/a/1190000007321972 Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西 ...

  6. Python之路【第十九篇】:爬虫

    Python之路[第十九篇]:爬虫   网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...

  7. Python之路【第十八篇】:Web框架们

    Python之路[第十八篇]:Web框架们   Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...

  8. Python之路【第十七篇】:Django【进阶篇 】

    Python之路[第十七篇]:Django[进阶篇 ]   Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...

  9. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

随机推荐

  1. java注解类型的aop

    import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import org.aspectj.la ...

  2. HDU1285(拓扑排序裸题

    ..被多组测试坑了一波 #include<iostream> #include<vector> #include<queue> using namespace st ...

  3. 【NOIP2015普及组】 推销员(纪中数据-标准)

    题目 [题目描述] 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有 N 家住户,第 i 家住户到入口的距离为 ...

  4. 对CSRF(跨站请求伪造)的理解

    一.什么是CSRF? CSRF是Cross Site Request Forgery的缩写,翻译过来就是跨站请求伪造.那么什么是跨站请求伪造呢?让我一个词一个词的解释: 1.跨站:顾名思义,就是从一个 ...

  5. MySql常用字符集

    常用字符集 位(bit):是计算机 内部数据 储存的最小单位,11001100是一个八位二进制数. 字节(byte):是计算机中 数据处理 的基本单位,习惯上用大写 B 来表示,1B(byte,字节) ...

  6. 牛客 109B 好位置 (字符串水题)

    大意: 给定字符串$s1,s2$, 对于$s1$中所有与$s2$相等的子序列$t$, $t$在$s1$中的下标定义为好位置. 求$s1$是否所有位置都是好位置. 显然$s1$的前缀要与$s2$相等, ...

  7. JavaScript设计模式(单例模式)

    单例模式是一种简单但非常实用的模式,特别是惰性单例技术,在合适的时候才创建对象,并且只创建唯一的一个.下面我们来逐步了解单例模式的用法. 一.简版单例模式: var Singleton = funct ...

  8. Struts2 流程原理

    一.流程图 (转) 二.流程详解 1.服务器传递来的请求,通过ActionContextClearUp.other filters.最后到达StrutsPrepareAndExecuteFilter ...

  9. 随便----js参考书

    一.Javascript方面的书籍: 1 JavaScript权威指南(第6版):号称javascript圣经,前端必备:前端程序员学习核心JavaScript语言和由Web浏览器定义的JavaScr ...

  10. Atcoder-SoundHound Inc.Contest 2018 -Masters Tournament-比赛报告

    A C++ Example #include <iostream> #include <cstdio> #include <cstdlib> #include &l ...