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._compose
和 decorator1.__mul__
在语法上都是 dotted_name
,因此这是有效的语法。 @decorator1 * decorator2
,然而,显然不匹配。
"Syntactic sugar" 并不意味着可以直接用一种形式的部分替换另一种形式的部分。形式:
@decorator
def f(n):
pass
当然等价于:
def f(n):
pass
f = decorator(f)
但它们并不相同,也不能完全互换。
我试图开发一个 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._compose
和 decorator1.__mul__
在语法上都是 dotted_name
,因此这是有效的语法。 @decorator1 * decorator2
,然而,显然不匹配。
"Syntactic sugar" 并不意味着可以直接用一种形式的部分替换另一种形式的部分。形式:
@decorator
def f(n):
pass
当然等价于:
def f(n):
pass
f = decorator(f)
但它们并不相同,也不能完全互换。