我正在尝试开发一个使用monads的python库(一个玩具项目来理解monad以及python如何充当“纯功能”语言),但这个问题与monad或函数式编程无关。 / p>
由于操作员需要编写函数,我尝试了以下“装饰器类”:
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”方法内部,如果我用它来进行“普通功能装饰”,它可以完美地工作。也就是说,以下代码可以正常工作:
@Composable
def function1(n):
return n + 1
@Composable
def function2(n):
return n * 2
print((function1 * function2)(5)) #outputs (5 * 2) + 1 = 11
我不明白的是,如果我使用“Composable”装饰两个函数装饰器,我将无法直接将它们组成装饰器,使用像之前我所做的“乘法”运算符: / p>
@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)
我的观点是:“我被告知”(见the mul magic method和python decorators)
a * b
不仅仅是语法糖
a.__mul__(b)
那个
@decorator
def f(n):
pass
只不过是
def f(n):
pass
f = decorator(f)
所以这是我的问题:这里发生了什么?装饰器不是评估任何返回可调用的表达式的结果吗?
哦,如果有人想知道:我正在使用python3.5
答案 0 :(得分:1)
language reference提供装饰器的语法:
decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
decorator1._compose
和decorator1.__mul__
都是语法dotted_name
,因此这是有效的语法。但是,@decorator1 * decorator2
显然不匹配。
“语法糖”并不意味着能够直接用一种形式的部分替换另一种形式的部分。表格:
@decorator
def f(n):
pass
当然等同于:
def f(n):
pass
f = decorator(f)
但它们并不相同,也不完全可以互换。