Python 自定义装饰器 class 表现出奇怪的行为

Python custom decorator class exhibiting strange behaviour

我试图开发一个 python 库来使用 monads(一个玩具项目来理解 monads 以及 python 如何充当 "purely functional" 语言),但是这个问题与 monad 或函数式编程无关。

在需要一个运算符来组合函数时,我尝试了以下方法"decorator class":

class Composable(object):
    def __init__(self, func):
        self._func = func

    def __call__(self, *args):
        return self._func(*args)

    def _compose(self, func):
        @Composable
        def _func(*args):
            return func(self._func(*args))
        return _func

    def __mul__(self, func):
        return self._compose(other)

它应该在“_compose”方法中使用,如果我将它用于 "plain function decoration",它会完美地工作。也就是说,以下代码可以正常工作:

@Composable
def function1(n):
    return n + 1

@Composable
def function2(n):
    return n * 2

print((function1 * function2)(5)) #outputs (5 * 2) + 1 = 11

我不明白的是,如果我用 "Composable" 装饰两个函数装饰器,我将无法使用 "multiplication" 运算符直接将它们组合为装饰器正如我之前所做的那样:

@Composable
def decorator1(func):
    def decorated(n):
        return func(n) + 1
    return decorated

@Composable
def decorator2(func):
    def decorated(n):
        return func(n) * 2
    return decorated

#This triggers a "SyntaxError" (with or without enclosing parentheses)
@decorator1 * decorator2
def function(n):
    return n

#While this works fine
@decorator1._compose(decorator2)
def function(n):
    return n

#Not quite surprisingly, this works fine too
@decorator1.__mul__(decorator2)

#(as always, this outputs (5 * 2) + 1 = 11)
function(5)

我的观点是:我"was told"(见the mul magic method and python decorators)那个

a * b

只不过是

的语法糖而已
a.__mul__(b)

还有那个

@decorator
def f(n):
    pass

无非是

def f(n):
    pass
f = decorator(f)

所以这是我的问题:这是怎么回事?装饰器不是对 returns 可调用的任何表达式求值的结果吗?

哦,如果有人想知道:我正在使用 python3.5

language reference 提供装饰器的语法:

decorator ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE

decorator1._composedecorator1.__mul__ 在语法上都是 dotted_name,因此这是有效的语法。 @decorator1 * decorator2,然而,显然不匹配。

"Syntactic sugar" 并不意味着可以直接用一种形式的部分替换另一种形式的部分。形式:

@decorator
def f(n):
    pass

当然等价于:

def f(n):
    pass
f = decorator(f)

但它们并不相同,也不能完全互换。