python闭包

原创
2017/02/17 16:47
阅读数 130

一.定义,什么样的叫闭包?

在Python语言中,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。你在调用函数A的时候传递的参数就是自由变量。简单的说,内部函数可以使用外部函数变量的行为,就叫闭包。

二. 为什么使用闭包?

因为在工作中,闭包可以缩减我们的代码量,可以偷懒,在一些场合还可以降低资源的消耗。闭包的几个特点:

1.与父函数中的变量建立关联,减少文件中全局变量的使用。有利于后面发展的并行运算。

2.即便生成闭包的环境-父函数已经释放,闭包还是会存在即内部变量的值还是存在于内存中。

三.实例说明

1.平常中,有些类的功能可以通过闭包的方式来实现,以达到缩减代码量的目的。

## 类
class Food(object):
    def __init__(self,food):
        self.food=food
        #self.name=name
    def eat_food(self,name):
        print "{}偷吃了{}".format(name,self.food)

apple=Food('apple')
apple.eat_food('小明')

## 闭包方式
def Fruit(fruit):
    def eat(name):
        print '{}偷吃了{}'.format(name,fruit)
    return eat

man=Fruit('milk')
man('小强')

2.装饰器在很多时候就是闭包的一种应用,不过装饰器传递的是函数体。比如下面带参的装饰器Auth():

def Auth(auth_type):
    def wrap(func):
        def inner(*args,**kwargs):
            if auth_type=='local':
                name=raw_input('输入用户名:')
                passwd=raw_input('输入密码:')
                if auth_type=='local':
                    if name=='admin' and passwd=='admin':
                        print('登陆成功!')
                        func(*args,**kwargs)
                    else:
                        print('登录失败')
            if auth_type=='ldap':
                print '喔,你改用ldap方式认证啦'
                func(*args,**kwargs)
        return inner
    return wrap

@Auth('local')
def Tv(price):
    print('电视售价:{}'.format(price))

@Auth('ldap')
def Index():
    print('欢迎来到XXX')

Tv(3500)
Index()

不带参的装饰器f():

def wrap(fun):
    def inner(*args,**kwargs):
        print 'call function {}():'.format(fun.__name__)
        return fun(*args,**kwargs)
    return inner
@wrap
def tv():
    print 'Welcome'

tv()

##输出
call function tv():
Welcome

可以看到带有参数的装饰器比没带参数的装饰器多了一层包裹。

3. 在闭包中使用循环变量有个陷阱

可以看见,结果并未如一些人预料到的1,4,9  。   原因就是闭包内部的inner()是在for循环结束的时候才开始执行的。由此,为了避免一些预料外的错误,应尽量不在闭包中使用循环变量。

当然在特殊情况下的补救措施也是有的-对内部函数再包一层,借用函数的参数来保存每次循环后的变量值:

参考资料:

1.http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0014186131194415d50558b7a1c424f9fb52b84dc9c965c000

2.http://funhacks.net/2016/11/17/closure/

3.https://segmentfault.com/a/1190000004461404

4.http://blog.csdn.net/ithomer/article/details/17252651

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部