[Python之路] 闭包
一、思考一个问题
我们要给定一个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之路] 闭包的更多相关文章
- 百万年薪python之路 -- 闭包
2.闭包 闭包的定义: 闭包是嵌套在函数中的函数. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用. 一句话定义就是:在嵌套函数内,对非全局变量 (且不是本层的变量)的引用 如何判断判断闭包? ...
- Python之路【第一篇】python基础
一.python开发 1.开发: 1)高级语言:python .Java .PHP. C# Go ruby c++ ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...
- Python之路
Python学习之路 第一天 Python之路,Day1 - Python基础1介绍.基本语法.流程控制 第一天作业第二天 Python之路,Day2 - Pytho ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
- 说说Python中的闭包 - Closure
转载自https://segmentfault.com/a/1190000007321972 Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西 ...
- Python之路【第十九篇】:爬虫
Python之路[第十九篇]:爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
随机推荐
- PDO原生分页
** PDO分页** 1.PDO连接数据库 $dbh=new PDO('mysql:host=127.0.0.1;dbname=03a','root','root');//使用pdo 2.接收页码 $ ...
- laravel框架之自帶登錄&註冊
//控制器層 <?php namespace App\Http\Controllers\admin; use App\Models\admin\Users; use Illuminate\Htt ...
- 关于Python中的lambda
lambda是Python编程语言中使用频率较高的一个关键字.那么,什么是lambda?它有哪些用法?网上的文章汗牛充栋,可是把这个讲透的文章却不多.这里,我们通过阅读各方资料,总结了关于Python ...
- X86逆向12:内存补丁的制作
本章我们将学习各种打补丁的方式,补丁在软件的破解过程中非常的重要,比如软件无法脱壳我们就只能通过打补丁的方式来破解程序,补丁原理就是当程序运行起来会被释放到内存并解码,然后补丁就通过地址或特征码定位到 ...
- Codeforces 1228E. Another Filling the Grid
传送门 看到 $n=250$ 显然考虑 $n^3$ 的 $dp$ 设 $f[i][j]$ 表示填完前 $i$ 行,目前有 $j$ 列的最小值是 $1$ 的合法方案数 那么对于 $f[i][j]$ ,枚 ...
- Java反射的理解(六)-- 通过反射了解集合泛型的本质
Java反射的理解(六)-- 通过反射了解集合泛型的本质 上述写了那么多,我们可能会有个疑问,为什么要用反射,步骤比我们常规的加载类操作复杂多了,别急,这个问题我最后才解答,我们先来了解集合泛型的本质 ...
- tomcat日志报Invalid message received with signature的解决办法
这位大神说的是正解,大家可以参考一下这个链接:https://blog.csdn.net/bugdongwenlong/article/details/84261424
- 连接云服务器中MySql数据库遇到的问题
使用的免费的云服务器,上面只能下载MySql数据库,不过当云数据库使用绰绰有余了,也就放一些测试数据而已 而且上面只可以部署php项目,.netcore项目部署实现比较麻烦 问题如下: 下载了navi ...
- C# WPF集中引用图片等资源的路劲方式
第一内部资源: pack://application:,,,/images/my.jpg 第二 外部程序资源: pack://SiteOfOrigin:,,,/images/my.jpg 需要将资源放 ...
- opencv ORB各参数的含义
ORB中有很多参数可以设置,在OpenCV中它可以通过ORB来创建一个ORB检测器. ORB::ORB(int nfeatures=500, float scaleFactor=1.2f, int n ...