为了学习,我试图链接由类定义的装饰器。我读了this question about decorators,它有很多关于用函数链接它们的好信息。它们也链接到documentation,但我试图找出更简单的例子。
基本上,我试图使用类来模仿类似的行为。这是我的第一个装饰器定义,它完美地运行。
class square_result(object):
def __init__(self, f):
pass
def __call__(self, x, y):
return (x+y)**2
@square_result
def add_two_numbers(x, y):
return x + y
print(add_two_numbers(2,5)) #Outputs 49, as expected
然后,我添加另一个装饰器来创建这段代码片段:
class square_result(object):
def __init__(self, f):
pass
def __call__(self, x, y):
return (x+y)**2
class append_abc(object):
def __init__(self, f):
pass
def __call__(self, *args):
return str(*args) + "abc"
@append_abc
@square_result
def add_two_numbers(x, y):
return x + y
print(add_two_numbers(2,5))
#Ideally, this should print "49abc" but prints "(2,5)abc" instead
这样做的正确方法是什么?我想我想要做的是创建一个类的形式的装饰器,它接受它所装饰的函数的输出(在这种情况下是square_result
)并将"abc"
附加到它上面。
我知道当我在我的代码中添加一个装饰器时,会编译add_two_numbers()
函数,并将该函数对象传递给square_result
类,它会创建类似函数的对象。替换原始add_two_numbers()
。但是,我不确定如何将其链接起来。
答案 0 :(得分:2)
这样做你想要的:
class square_result(object):
def __init__(self, f):
pass
def __call__(self, x, y):
return (x+y)**2
class append_abc(object):
def __init__(self, f):
self.f = f
def __call__(self, *args):
return str(self.f(*args)) + "abc"
@append_abc
@square_result
def add_two_numbers(x, y):
return x + y
print(add_two_numbers(2,5))
如果你想在装饰器的结果中使用它的输出,你需要实际在装饰器中运行内部函数。
我没有编辑你的第一个装饰器,因为它可以做你想要的,但实际上它并没有用作装饰器。由于它的输出与它正在装饰的功能没有任何关系,所以它只是取代了这个功能。如果你想用该类替换该函数,那么这样做的方法是
class square_result(object):
def __call__(self, x, y):
return (x+y)**2
# this has no effect at all after the reassignment
def add_two_numbers(x, y):
return x + y
add_two_numbers = square_result()
PEP8还建议使用CamelCase作为您的班级名称(SquareResult
)。
答案 1 :(得分:1)
square_result
不会“装饰”add_two_numbers
结果,而是覆盖它(执行添加以及平方)。它应该以与append_abc
相同的方式处理装饰函数,方法是存储它,然后在自己的实现中使用装饰函数。因此:
class square_result(object):
def __init__(self, f):
self.function = f
def __call__(self, *args):
return self.function(*args)**2
class append_abc(object):
def __init__(self, f):
self.function = f
def __call__(self, *args):
return str(self.function(*args)) + "abc"
@append_abc
@square_result
def add_two_numbers(x, y):
return x + y
print(add_two_numbers(2,5))