python闭包和装饰器_python闭包与装饰器

有关闭包和装饰器的知识点的理解着实花了我不少时间,整理笔记更是无从下手,但还是将从网上搜索学习的点滴记录下来以便后期的一个补充学习。

闭包(wrapper)

闭包通俗地解释就是通过调用了函数A,函数A返回了函数B,返回的函数B就是所谓的闭包,在调用函数A的时候传递的参数就是自由变量,该自由变量是被函数A引用的,在函数A的生命周期结束后仍然存在,这句话是至今能让我比较能理解的解释。

例如:

>>>def func1(name): #定义一个函数func1

def func2(age): #函数func2()是在func1调用的时候产生的一个闭包,且引用了自由变量name

print name,age

return func2 #函数调用完毕返回函数func2

>>> a=func1('Lily') #调用函数func1,且传递参数‘Lily’,将结果赋给a

>>> a(24) #上一步的结果是返回函数func2,这时再将参数24赋给函数func1,调用函数func2

Lily 24

闭包不能修改外部作用域的局部变量:

>>> def a():

x=1 #局部变量x的值为1

def b():

x=0 #在闭包内对x的值进行重新赋值

return x

>>> a()

1 #结果是x的值没有改变

使用闭包的好处呢一个就是在闭包运行之后,保存当前的运行环境,另一个是通过外部作用域的变量可以返回不同的值。

装饰器

装饰器是闭包的使用场景之一,装饰器其实也就是闭包的应用,只是区别的是装饰器传递的参数是函数。装饰器是将函数作为参数传递给一个函数,并对其进行加工处理即装饰返回一个新的函数,装饰器能保证在不改变已有的函数的结构,调用该函数返回一个新的函数,极大地提高了效率。

使用标识符@将装饰器应用在函数上,只需要在函数的定义前加上@和装饰器的名称,即@decorator

@decorator #解释器将会解释成:func=decorator(func),即将函数func作为参数传递给函数decorator,然后再返回新的函数赋值给func

def func():

pass

多个decorator使用:

@decorator1 #func=decorator2(decorator1(func))

@decorator2 #func=decorator1(func)

def func():

pass

再来一个打印调用函数前log日志的无参数的装饰器例子:

>>> def log(f):

def wrapper(*args):

print 'call %s()' %(f.__name__)

return f(*args)

return wrapper

>>> @log

def func():

print 'hello,world'

>>> func()

call func()

hello,world

带参数的装饰器:

带参数的装饰器比不带参数的装饰器还要复杂一点,需要编写一个返回decorator的高阶函数

>>> def log(text): #3层嵌套的函数

def decorator(f): #返回decorator函数

def wrapper(*args):

print '%s %s()' %(text,f.__name__) #将log的参数excute传递过来赋给text

return f(*args)

return wrapper

return decorator #先执行log('excute')函数,返回decorator函数,再调用返回wrapper函数,最后返回一个新的func函数

>>> @log('excute')

def func():

print 'hello,world'

>>> func()

excute func()

hello,world

>>>

>>> now.__name__ #函数的name属性,通过decorator装饰器调用执行之后返回wrapper函数,所以函数名由func变成了wrapper

'wrapper'

所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写wrapper.__name__ = f.__name__这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

import functools

def log(text):

def decorator(f):

@functools.wraps(f)

def wrapper(*args, **kw):

print('%s %s():' % (text, f.__name__))

return f(*args, **kw)

return wrapper

return decorator

以上的例子都是从网上找的,比较容易理解的例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值