python--闭包

转载:Source

在 python 里万物皆对象,函数也不例外,于是乎我们可以在一个函数中定义另一个函数作为返回值。

def func():
    def wrapper():
        print('你好')

    return wrapper

result= func()
result()


你好

这就是一个闭包(closure)了吗?还少了点味。

因为根据维基百科上对闭包的定义:

在支持头等函数的语言中,如果函数f内定义了函数g,那么如果g存在自由变量,且这些自由变量没有在编译过程中被优化掉,那么将产生闭包。

人话: f 函数中定义了 g 函数, g 还引用了 f 定义的变量, 就是闭包。

代码:

def func(name):
    def wrapper():
        print(f'你好,{name}')

    return wrapper

result = func('小明')
result()

由作用域的查找规则可知,在这段代码中,func 函数内是局部作用域, wrapper 函数内是闭合作用域, wrapper 函数可以直接使用 func 函数内的变量。

那 python 是怎么实现闭包的呢?

在实现闭包时,返回的函数会带有 __closure __ 属性,在__closure __ 里可以找到函数所需要的变量。

print(result.__closure__) 
print(result.__closure__[0].cell_contents) 


(<cell at 0x000001DF6F6B86D0: str object at 0x000001DF6F6B5C30>,)
小明

一、闭包的应用场景


使用闭包主要有以下三个好处。

  • 关联数据与函数
  • 保存临时变量,减少全局变量
  • 保存私有变量,防止变量被修改

在 python 中闭包有个很经典的应用场景就是装饰器,放在下节讲。

二、关联数据与函数

关联数据与函数,这与面向对象中很类似,但有时只有一个方法时,使用闭包会简单很多。

class Timer:
    def __init__(self, base):
        self.base = base

    def time(self, x):
        return self.base * x

timer2 = Timer(2)
print('结果:', timer2.time(4))


def timer(base):
    def wrapper(x):
        return x * base

    return wrapper

timer2 = timer(2)
print('结果:', timer2(4))


结果: 8
结果: 8

以上两种方式,用闭包实现会简单很多。

三、保存临时变量

由于闭包是把变量保存在局部作用域中,所以可以减少使用全局变量。

count = 0

def func():
    global count
    count += 1
    print(f'执行了{count}次')

func()
func()


def counter():
    count = 0

    def wrapper():
        nonlocal count
        count += 1
        print(f'执行了{count}次')

    return wrapper

func = counter()
func()
func()


执行了1次
执行了2次
执行了1次
执行了2

四、保存私有变量

闭包中传入的变量只能被内部的函数修改,这使得我们可能通过这个特性创建一个防止被修改的字典。

def my_dict(**kwargs):
    def wrapper():
       return {**kwargs}
    return wrapper

xiaoming = my_dict(name='小明', age=18)

print('修改前:', xiaoming())
xiaoming()['name'] = '小红'
print('修改后:', xiaoming())


修改前: {'name': '小明', 'age': 18}
修改后: {'name': '小明', 'age': 18}

成功避免了被更名改姓。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值