Python装饰器与Java注释、Spring AOP或Aspect J是否相同、相似或根本不同?
Python装饰器与Java注释、Spring AOP或Aspect J是否相同、相似或根本不同?
Python的装饰器只是一种语法糖,可以将一个函数作为参数传递给另一个函数,并用返回值替换第一个函数:
@decorator
def function():
pass
是语法糖,用于
def function():
pass
function = decorator(function)
Java注释本身只是存储元数据,需要有东西来检查它们以添加行为。
Java AOP系统是基于Java构建的庞大系统,而装饰器只是带有很少或没有语义附加的语言语法,你不能真正比较它们。
这是一个非常合理的问题,任何同时涉足这两种语言的人都可能会遇到。我自己花了一些时间学习Python,并最近在加快掌握Java,以下是我的比较看法。
Java注释只是注释。它们是标记;包含关于它们所标记/注释的基础对象的额外元数据的容器。它们的存在本身不会改变基础对象的执行流程,也不会在其上添加封装/包装。那么它们有什么用处?它们由注释处理器读取和处理。它们包含的元数据可以被自定义的注释处理器使用,以添加一些辅助功能,使生活更轻松;但是,它们既不改变底层的执行流程,也不包裹在其上。
对于使用Python装饰器的人而言,“不改变执行流”这个重点将是清晰明确的。 Python装饰器虽然在外观上与Java注释相似,但在内部却非常不同。它们采取底层并以任何方式将自己包裹起来,如用户所需,甚至完全避免运行底层,如果选择这样做的话。它们采取底层,将自己包裹起来,并用包裹后的方法替换底层。它们有效地'代理'了底层!
现在,这与Java中Aspect的工作方式非常相似!就本质而言,方面在其机制和灵活性方面都得到了很大发展。但是它们所做的只是 - 获取“建议”的方法(我正在谈论Spring AOP术语,不确定是否也适用于AspectJ),在其周围包装功能,以及谓词和类似的东西,并使用包装的方法“代理”“建议”方法。
请注意,这些思考是在非常抽象和概念性的水平上,以帮助把握全局。当您开始深入研究时,所有这些概念 - 装饰器、注释、方面 - 都具有相当广泛的范围。但在抽象层面上,它们是可以相互比较的。
简短总结:
就外观和感觉而言,Python 装饰器可以被视为类似于 Java 注解的东西,但在内部实现上,它们的工作方式非常类似于 Java 中的 Aspects 机制。
我会用类似的方式来使用它们:打开/关闭调试或测试选项。
例如(Python装饰器):
def measure_time(func):
def _measure_time(*args, **kwargs):
t0 = time.time()
ret = func(*args, **kwargs)
print "time=%lf" % (time.time()-t0)
...
return ret
return _measure_time
@measure_time
def train_model(self):
...
对于Java注解,可以使用getAnnotation等方法来完成类似或更复杂的工作。
Python装饰器和Java注解在语法上相同,但用途完全不同!它们不兼容,不能互换使用!
最近我在一个项目中需要在Python脚本中使用Java注解语义,于是我寻找一种模拟方法,并找到了这个:
在Python中有一种称为“文档字符串”的功能!
它只是一个特殊的注释行,必须是模块、类或函数的第一行!
与注释行类似,您可以使用任何形式的文本。但在我这种情况下,它之所以特别,是因为它可以被Python内省读取!
因此,它可以像Java注解一样工作,后者也需要Java反射来解释并响应从中传递的元数据!!
以下是一个简短的示例:
源文件 a.py
```
def some_function():
'''@myJavaLikeAnnotation()'''
... (my function code) ...
```
源代码 b.py(在其中我必须处理 @myJavaLikeAnnotacion()):
import a
for element_name in dir(a):
element = getattr(a, element_name)
if hasattr(element, '__call__'):
if not inspect.isbuiltin(element):
try:
doc = str(element.__doc__)
if not doc == '@myJavaLikeAnnotation()':
# It don't have the 'java like annotation'!
break
... It have! Do what you have to do...
except:
pass
显然,缺点在于您必须自己解析在“Python Java类注释”中使用的所有元数据!