[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 ...
随机推荐
- 深拷贝 & 浅拷贝
浅拷贝: class Professor { String name; int age; public Professor(String name, int age) { this.name = na ...
- 【Havel 定理】Degree Sequence of Graph G
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2454 [别人博客粘贴过来的] 博客地址:https://www.cnblogs.com/debug ...
- nginx + uwsgi 部署django项目
因项目需求,需要部署django项目,这里是基础的nginx配合uwsgi部署django,后续会采用docker部署的方式 环境: centos7 python3.5.4 django2.1.4 u ...
- Java 中使用serversocket通信
1. 创建一个Java项目 TestMyServerSocket. 2. 创建一个包 com.weloglog.main 3. 创建一些使用到的类 程序启动类 MyServerSccket : 用来启 ...
- # 风险定性(Qualitative)分析
1. 从一个给教师打分的设计表说起 我们参加一个培训课程,一般在培训结束之后,培训机构一般都会分发一份培训师培训效果反馈表,用于评价其讲师的培训能力的强弱. 如果是一家没有什么经验的培训机构设计的反馈 ...
- 客户端相关知识学习(六)之deeplink技术
Deeplink应用描述 Deeplink,简单讲,就是你在手机上点击一个链接之后,可以直接链接到app内部的某个页面,而不是app正常打开时显示的首页.不似web,一个链接就可以直接打开web的内页 ...
- JS基础_一元运算符
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 使用svn遇到的问题---(在编辑器没有配置svn的前提下)
日常写代码的过程中新增了文件,一般都是继续文件的书写,写完一部分后提交 新增文件后面经常忘记了add后commit 原来是可以在commit时勾选左下角的 [show unversioned file ...
- css中animation和@keyframes 动画
Animation 使用简写属性,将动画与 div 元素绑定: div { animation:mymove 5s infinite; -webkit-animation:mymove 5s infi ...
- python中进制转换
使用Python内置函数:bin().oct().int().hex()可实现进制转换. 先看Python官方文档中对这几个内置函数的描述: bin(x)Convert an integer numb ...