python函数装饰器

python函数装饰器,第1张

python函数装饰器

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

def say_nihao():
	print('nihao')

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

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

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

    我们需要找到程序中所有调用say_nihao()的地方改成log()如果现在又有一个函数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作用不在说明。
在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')

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5701257.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存