python函数装饰器

有函数如下,如何在不破坏函数的情况下为函数增加输出日志功能?

def say_nihao():
	print('nihao')

很简单,我们只需要对函数进行封装即可

def log()
	print('我是日志')
	say_nihao()

现在我们只需要调用log()函数即可,相信很多人都是这样写的,但是这样写有很大的弊端。

  1. 我们需要找到程序中所有调用say_nihao()的地方改成log()
  2. 如果现在又有一个函数say_hello()也需要增加输出日志功能,我们岂不是要再来一遍?也就是说我们刚才的操作是不能复用的

下面我们来介绍python中的装饰器。
对于第一个问题,我们这样进行修改:

def log()
	print('我是日志')
	return say_hello
say_nihao=log()

要解决第二个问题,我们只要把函数当作参数传递进去就可以了

def log(func)
	print('我是日志')
	return func
say_nihao=log(say_nihao)

这样我们就不需要修改程序,并且代码可以复用,而log()我们称作装饰器
我们通常将装饰器中增加的功能使用wrapper()包装起来,此时我们执行say_nihao()就相当于执行wrapper()

def log(func)
	def wrapper():
		print('我是日志')
		return func
	return wrapper
say_nihao=log(say_nihao)

在面向切面编程(AOP)中,我们将log()称为切面。将切面和具体函数结合的地方,也就是say_nihao=log(say_nihao)称为切入点。
如果say_nihao()函数有参数 ,我们可以这样:

def log(func)
	def wrapper(*args, **kwargs):
		print('我是日志')
		return func(*args, **kwargs)
	return wrapper
say_nihao=log(say_nihao)

*args**kwargs作用不再说明。
因为实际上调用say_nihao()相当于调用wrapper(),所以需要按照wrapper()的参数表进行传递,然后在wrapper()的函数体中传给say_nihao()
在python中为say_nihao=log(say_nihao)提供了一种语法糖:@

def log(func)
	def wrapper(*args, **kwargs):
		print('我是日志')
		return func(*args, **kwargs)
	return wrapper
	
@log
def say_nihao():
	print('nihao')

这里说一下参数的问题,如果@log没有参数,那么传递到装饰器log()函数里的是say_nihao对象,如果@log(a)有参数,那么那么传递到装饰器log()函数里的是@log(a)里面的参数a,而say_nihao对象将被传递到wrapper()函数里。
基于此,如果装饰器本身需要参数,那么可以这么些:

def log(value):
	def decorator(func):
		def wrapper(*args, **kwargs)
			print(value)
			return func(*args, **kwargs)
		return wrapper
	return decorator

@log('我是日志')
def say_nihao():
	print('nihao')

调用被修饰函数,相当于调用修饰函数的返回值
如果@log没有参数,相当于使用log函数进行修饰,没有参数时不要携带括号
如果@log( )有参数,相当于使用log函数的返回值进行修饰

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值