Python 装饰器与 Java 注解或带有切面的 Java 是否相同?

67

Python装饰器与Java注释、Spring AOP或Aspect J是否相同、相似或根本不同?


Python 也有注释,所以我认为它们在本质上是不同的。 - mgilson
可能是"@" Decorator (in Python)的重复问题。 - Matt Ball
请查看编辑以扩展有关Java方面的问题。 - bn.
可能是理解Python装饰器的重复问题。 - Peter O.
4个回答

75

Python的装饰器只是一种语法糖,可以将一个函数作为参数传递给另一个函数,并用返回值替换第一个函数:

@decorator
def function():
    pass

是语法糖,用于

def function():
    pass
function = decorator(function)

Java注释本身只是存储元数据,需要有东西来检查它们以添加行为。

 

Java AOP系统是基于Java构建的庞大系统,而装饰器只是带有很少或没有语义附加的语言语法,你不能真正比较它们。


33

这是一个非常合理的问题,任何同时涉足这两种语言的人都可能会遇到。我自己花了一些时间学习Python,并最近在加快掌握Java,以下是我的比较看法。

Java注释只是注释。它们是标记;包含关于它们所标记/注释的基础对象的额外元数据的容器。它们的存在本身不会改变基础对象的执行流程,也不会在其上添加封装/包装。那么它们有什么用处?它们由注释处理器读取和处理。它们包含的元数据可以被自定义的注释处理器使用,以添加一些辅助功能,使生活更轻松;但是,它们既不改变底层的执行流程,也不包裹在其上。

对于使用Python装饰器的人而言,“不改变执行流”这个重点将是清晰明确的。 Python装饰器虽然在外观上与Java注释相似,但在内部却非常不同。它们采取底层并以任何方式将自己包裹起来,如用户所需,甚至完全避免运行底层,如果选择这样做的话。它们采取底层,将自己包裹起来,并用包裹后的方法替换底层。它们有效地'代理'了底层!

现在,这与Java中Aspect的工作方式非常相似!就本质而言,方面在其机制和灵活性方面都得到了很大发展。但是它们所做的只是 - 获取“建议”的方法(我正在谈论Spring AOP术语,不确定是否也适用于AspectJ),在其周围包装功能,以及谓词和类似的东西,并使用包装的方法“代理”“建议”方法。

请注意,这些思考是在非常抽象和概念性的水平上,以帮助把握全局。当您开始深入研究时,所有这些概念 - 装饰器、注释、方面 - 都具有相当广泛的范围。但在抽象层面上,它们是可以相互比较的。

简短总结:

就外观和感觉而言,Python 装饰器可以被视为类似于 Java 注解的东西,但在内部实现上,它们的工作方式非常类似于 Java 中的 Aspects 机制。


1
很好的解释 - userx
对于Java注解,我仍然不理解“不改变执行流程”,因为这似乎与我心中的“添加一些辅助功能”相矛盾。可能需要通过示例来完全理解这一点。 - dtc
1
Python装饰器只能在类和函数声明中指定,而您可以使用Java注释注释字段。 - dodecaplex
在Java中,原始函数保持不变。生成的子类或代理将进行包装。只有与依赖注入框架(如Spring)结合使用时,它才会看起来像包装器替换了原始函数(因为您调用的是子类或代理而不是手动编码的原始类)。 - julaine

2

我会用类似的方式来使用它们:打开/关闭调试或测试选项。

例如(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等方法来完成类似或更复杂的工作。


0

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类注释”中使用的所有元数据!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接