python装饰器系列(二)

对python装饰器系列(一)的deco函数进行修改:

1 def deco(fn):
2     def wrap():
3         print('ha ha ha')
4         print('call {0} funtion'.format(fn.__name__))
5         fn()
6     return wrap
1 @deco
2 def myfun():
3     print('call myfun')
1 myfun()
2 
3 ha ha ha
4 call myfun funtion
5 call myfun

myfun()函数被deco(fn)函数进行修饰后,调用myfun()时就像被施加了魔法一样在执行此函数前附加的执行了一些操作

有参数的装饰器

1 def deco(fn):
# 考虑到被装饰的函数可以接收的参数类型的不确定性,可以用可变位置参数和可变关键字参数来捕捉,即(*args,**kwargs)
2 def wrap(*args,**kwargs): 3 print('ha ha ha') 4 print('call {0} funtion'.format(fn.__name__)) 5 return fn(*args,**kwargs) 6 return wrap
1 @deco
2 def myfun(x):
3     return x ** 2
1 myfun(5)
1 ha ha ha
2 call myfun funtion
3 
4 25
1 myfun.__name__
2 'wrap'

myfun(x)函数被deco(fn)函数装饰后,函数对象的__name__属性会发生改变,发上输出。因为@deco就相当于执行了myfun = deco(myfun),即变量myfun已经指向了wrap(*args,**kwargs)函数,这时myfun变量指向函数的__name__属性就是wrap,不再是原来的myfun()函数的__name__属性。

如果要修正这个问题,可以直接引用python内置的functools.wraps方法

1 import functools
2 def deco(fn):
3     @functools.wraps(fn)
4     def wrap(*args,**kwargs):
5         print('ha ha ha')
6         print('call {0} funtion'.format(fn.__name__))
7         return fn(*args,**kwargs)
8     return wrap
1 @deco
2 def myfun(x):
3     return x ** 2
1 @deco
2 def myfun(x):
3     return x ** 2
1 myfun(25)
2 
3 ha ha ha
4 call myfun funtion
5 625
myfun.__name__
'myfun'

总结:装饰器其实也是一个函数,此函数可以接收一个函数作为参数,并返回一个函数,即也是一个高阶函数。装饰器这个函数能让一个函数在调用时的前或后额外的执行一些操作来修改原调用的函数

原文地址:https://www.cnblogs.com/tianshug/p/10921788.html