一、@函数装饰器

装饰器可用于修饰其他函数,例如@classmethod、@staticmethod都是函数装饰器,他们都是Python内置的函数。

我们可以自己开发自定义函数装饰器,例:

def a(f):
	print ('0')
	f()
	print ('2')
	return 666
'''
@a 函数装饰器相当于a(b),
把b()函数作为参数传给a(),
b()函数返回a()的返回值
'''
@a
def b():
	print ('1')
'''
打印
0
1
2
'''

print (b)   # 返回a()的返回值,打印 666
print (type(b)) # b不再是函数,而是被替换成666,所以类型为int,打印 <class 'int'>

上面的例子可以看出,当程序使用“@函数”装饰另一个函数时,相当于将被修饰的函数作为参数传给@符号引用的函数,被装饰的函数被替换成@符号引用的函数的返回值。

 

因为被装饰函数总是被替换成@符号引用的函数的返回值,那么我们想把被装饰函数在替换之后还是函数,就可以把@符号引用的函数返回值变成函数,另外如果被装饰函数有参数,可以使用*args和**kwargs。(*args:把参数打包成元组给函数体调用,**kwargs:把关键字参数打包成字典给函数体调用)

例:

def d(f):
    # 定义a()嵌套函数
    def a(*args,**kwargs):
            print ('取元组第一个元素:',args[0])
            return f(args,kwargs)
    return a

@d
def b(k1,k2):
	print ('元组:',k1)
	print ('字典:',k2)

	
print (b)
b('1','2',k2 = '777')
'''
最终还是会被替换成a()函数,
调用b()实际上是在调用a()函数,
打印
<function d.<locals>.a at 0x0000000003169268>
取元组第一个元素: 1
元组: ('1', '2')
字典: {'k2': '777'}
'''