mysql闭包的作用_闭包浅析

首先:

如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数。

然后:

我们来看看闭包的官方定义: 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

分析:

一般情况下,在我们认知当中,如果一个函数执行完毕,函数的内部(即名称空间)所有东西都会释放掉,被回收还给内存,局部变量也会消失。

但是闭包是一种特殊情况,如果外函数在结束的时候发现其名称空间(作用域)中的临时变量将来会在内部函数中使用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

举例说明:

#outer是外部函数 a和b都是外函数的临时变量

def outer( a ):

b = 8

#inner是内函数

definner():#在内函数中 用到了外函数的临时变量a和b

print(a+b)#外函数的返回值是对内函数的引用

returninnerif __name__ == '__main__':

demo= outer(6)#调用外函数传入参数6

#此时外函数两个临时变量 a是6 b是8 ,outer外函数调用执行,其返回值就是对内函数的引用,将引用的内函数inner的内存地址赋值存给demo

#外函数结束的时候发现内部函数将会用到(因为demo只是引用了inner的内存地址,只有它加括号才能执行内部代码,所以这里说是将会用到)自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数inner# 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量

demo() #14

#demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数

demo2= outer(9)

demo2()#17

如果要更全面的理解闭包就需要知道一些知识:

① 外函数的返回值是内函数的引用

python中一切都是对象,包括变量、函数,其实都是对象。

当我们进行a=1的时候,实际上是在内存当中开辟一片空间存放了值1,然后用a这个变量名存了1所在内存位置的引用(内存地址)。

a只不过是一个变量名字,a里面存的是1这个数值所在的内存地址,就是a里面存了数值1的引用。

相同的道理,在python中定义一个函数def demo(): 的时候,会在内存中开辟一块空间,用于存放该函数的代码、内部的局部变量等等。

这个demo只不过是一个变量名字,它里面存了这个函数所在位置的引用而已。

我们还可以进行x = demo, y = demo, 这样的操作就相当于,把demo里存的东西赋值给x和y,这样x 和y 都指向了demo函数所在的引用,在这之后我们可以用x() 或者 y() 来调用我们自己创建的demo() ,调用的实际上根本就是一个函数,x、y和demo三个变量名存了同一个函数的引用。

有了上面对引用的解释,就可以更深刻的理解“返回内函数的引用”这句话了。

对于闭包,在外函数outer中最后return了inner,我们在调用外函数 demo = outer() 的时候,outer返回了inner,inner是一个函数的引用,这个引用被存入了demo中。所以接下来我们再进行demo() 的时候,相当于运行了inner函数。

同时我们知道,函数名后+括号就相当于调用执行了这个函数,如果不+括号,相当于只是一个函数的名字,里面存了函数所在位置的引用。

② 闭包中内函数修改外函数局部变量:

在闭包内函数中,我们可以随意使用外函数绑定来的临时变量,但是正常事不能修改的,因为作用域不一样,无法修改

在基本的python语法当中,一个函数可以随意读取全局数据,但是要修改全局数据的时候有两种方法:1、global 声明全局变量 2、全局变量是可变类型数据的时候可以修改

在闭包内函数也是类似的情况,在内函数中想修改闭包变量(外函数绑定给内函数的局部变量)的时候:

1、在python3中,可以用nonlocal 关键字声明 一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。

2、在python2中,没有nonlocal这个关键字,我们可以把闭包变量改成可变类型数据进行修改,比如列表。

举个栗子:

#修改闭包变量的实例#outer是外部函数 a和b都是外函数的临时变量

defouter( a ):

b= 10 #a和b都是闭包变量

c = [a] #这里对应修改闭包变量的方法2

#inner是内函数

definner():#内函数中想修改闭包变量

#方法1 nonlocal关键字声明

nonlocal b

b+=1

#方法二,把闭包变量修改成可变数据类型 比如列表

c[0] += 1

print(c[0])print(b)#外函数的返回值是内函数的引用

returninnerif __name__ == '__main__':

demo= outer(5)

demo()#6 11

还有一点需要特别注意:

使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量

4e2ea6419a9327eb85bb7f2d76e0a561.png

defouter(x):definner(y):

nonlocal x

x+=yreturnxreturninner

a= outer(10)print(a(1)) #11

print(a(3)) #14(注意,这里不是13,因为第二次使用的依然是x这个变量,只不过他在第一次引用的是第一次的结果11了)

两次分别打印出11和14,由此可见,每次调用inner的时候,使用的闭包变量x实际上是同一个。

总结

闭包的作用:

1、装饰器

2、面向对象:经历了上面的分析,我们发现外函数的临时变量送给了内函数。这其实跟类对象的情况一样,对象有好多类似的属性和方法,所以我们创建类,用类创建出来的对象都具有相同的属性方法。闭包也是实现面向对象的方法之一。在python当中虽然我们不这样用,在其他编程语言入比如avaScript中,经常用闭包来实现面向对象编程

3、实现单例, 其实这也是装饰器的应用。

defsingleton(cls):

_instance= cls('127.0.0.1', 3306)def wrapper(*args, **kwargs):if len(args) != 0 or len(kwargs) !=0:

obj= cls(*args, **kwargs)returnobjreturn_instancereturnwrapper

@singleton#MySQL=singleton(MySQL) #MySQL=wrapper

classMySQL:def __init__(self, ip, port):

self.ip=ip

self.port= port

4、自己还没想到的其它...,欢迎补充^-^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值