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 注释相似,但在底层却有很大不同。他们根据用户的需要,采用底层技术并以任何方式将其自身包裹起来,甚至可能完全避免运行底层技术本身(如果有人选择这样做的话)。他们拿起底层,将自己包裹在底层,然后用包裹的底层替换底层。他们有效地“代理”了底层!
现在 that 与 Java 中方面的工作方式非常相似!方面本身在机制和灵活性方面已经相当进化。但从本质上讲,他们所做的是 - 采用“建议”方法(我在 Spring AOP 术语中讨论,不确定它是否也适用于 AspectJ),将功能以及谓词等包装在它们周围,然后“将“建议”方法与包装方法进行代理。
请注意,这些思考处于非常抽象和概念的层面,以帮助了解全局。当您开始深入研究时,所有这些概念 - 装饰器、注释、方面 - 都有相当大的涉及范围。但在抽象层面上,它们非常具有可比性。
TLDR
就外观而言,Python 装饰器可以被认为与 Java 注释类似,但在底层,它们的工作方式与 Java 中方面的工作方式非常相似。
我以类似的方式使用它们:打开/关闭调试或测试选项。
例如(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 中,有一个名为“Docstring”的功能!
它只不过是一个特殊的注释行,必须是模块、类或函数中的第一行!
与注释行一样,您可以使用任何形式的文本。但在这种情况下,它对我来说如此特别的是,它可以通过 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 的注释”中使用的所有元数据!