装饰器
java注解:
-
都是@开头,注解、
-
Java 注解也叫元数据,一种代码级别的说明。注解是给别人看的,功能不仅仅由注解决定
-
注解对
-
java注解可以写在类、方法、变量头上
-
使用注解(Annotation)的语言:AtScript、Java、C#(叫 Attribute)
python装饰器:
-
都是@开头,注解、
-
Python 装饰器是一种语法糖。装饰器直接拦截,直接改变被装饰对象的行为
-
装饰器可以对方法进行功能上的改变,可以对所修饰的代码产生直接的影响。
-
python装饰器可以写在类、方法头上。
-
使用装饰器(Decorator)的语言:Python、JavaScript/ECMAScript
在java中注解+反射能够实现和python里装饰器同样的效果。
装饰器基础概念
装饰器本质上是一个函数,它可以接收一个函数作为参数并返回一个新的函数。这个新函数是对原函数的一种包装或增强,可以在不改变原函数代码的前提下,增加额外的功能。
装饰器的返回值也是一个函数。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
Python
中的装饰器是一个语法糖,它本身就涉及到一个返回函数的概念,可以说返回函数是装饰器得以实现的基石。
由于
Python
有一个内建属性__call__
,这个是一个很神奇的特性,只要某个类型中有__call__
方法,我们可以把这个类型的对象当作函数来使用。这点是Java
跟C++
不一样的地方,Python 中的函数可以像普通变量一样当做参数传递给另外一个函数
装饰器实现
装饰器的实现程可以分为以下几个步骤:
-
定义装饰器:首先定义一个装饰器函数,该函数接收一个函数作为参数。
-
定义包装函数:在装饰器函数内部,定义一个包装函数(wrapper),这个包装函数会调用原函数,并可以在调用前后添加额外的逻辑。
-
返回包装函数:装饰器函数返回这个包装函数。
-
使用
@
语法:在需要被装饰的函数定义前使用@
符号加上装饰器名称,这样Python解释器会自动将这个函数作为参数传递给装饰器,并将返回的新函数(包装函数)赋值给原函数名。
说白了装饰器就是一个闭包函数。
def deco(func):
def _deco():
print("before myfunc() called.")
# 执行被装饰的函数
func()
print(" after myfunc() called.")
# 不需要返回func,实际上应返回原函数的返回值
return _deco
示例:
1、装饰器装饰的函数有多个参数
def deco(func):
# 内部参数需要定义 不定数量的位置参数和关键字参数,以接受和传递任意数量的参数
def _deco(*args, **kwargs):
print("before %s called." % func.__name__)
# 执行被装饰的函数,使用不定参数
ret = func(*args, **kwargs)
print(" after %s called. result: %s" % (func.__name__, ret))
return ret
return _deco
2、装饰器带参数:装饰器带参数,则装饰器函数则变成了三层,我们需要在最外层把装饰器的参数传递进去。
# 第一层传入装饰器参数
def deco(arg):
# 第二层传入被装饰函数
def _deco(func):
# 第三层进行逻辑处理
def __deco():
print("before %s called [%s]." % (func.__name__, arg))
func()
print(" after %s called [%s]." % (func.__name__, arg))
return __deco
return _deco