Python-功能装饰器导致功能被称为两次



我在我编写的一些单元测试中使用功能装饰器来测试代码。但是,我发现该装饰器导致该功能被称为两次(因此两次打印其输出(。

我在某些函数返回错误的返回值之后发现了此错误,这只有在函数两次时才会发生。

#!/usr/bin/env python3
def decorate(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print("#" * 40)
        print("Testing function {}".format(func.__name__))
        print("Arguments passed: {} ".format(args))
        print("Begin output of {}".format(func.__name__))
        print("#" * 40)
        try:
            func(*args, **kwargs)
        except Exception as e:
            print("Error occured: {}".format(e))
        print("#" * 40)
        print("End of output of {}".format(func.__name__))
        print("#" * 40)
        print("n" * 5)
        return func(*args,**kwargs) #Error happens on this line here
    return inner
#Add decorator to function definition. 
@decorate
def asdf():
    print("THIS SHOULD PRINT ONCE")
#Call function
asdf()

输出(完全按照复制为间距(:

########################################
Testing function asdf
Arguments passed: ()
Begin output of asdf
########################################
THIS SHOULD PRINT ONCE
########################################
End of output of asdf
########################################



THIS SHOULD PRINT ONCE

我所需的输出:

########################################
Testing function asdf
Arguments passed: ()
Begin output of asdf
########################################
THIS SHOULD PRINT ONCE
########################################
End of output of asdf
########################################

我正在尝试消除该功能的第二个调用。我知道我的错误在于装饰器,我只是找不到。

请注意,您是呼叫从装饰器内部两次功能:

  • 一次进入try/except块。
  • ,一次在返回语句中。

您将要更改第一个呼叫(Try Block中的呼叫(为:

res = func(*args, **kwargs)

,然后简单地:

return res

编辑 :(根据 @danielroseman的评论(

由于您没有从except块中升高或返回,因此您必须在其中(except内部(分配res,或者在装饰器开始时替代将其预先定义为None(或任何值适合您的程序(。

您确实在Boldface中两次拨打电话:

def decorate(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print("#" * 40)
        print("Testing function {}".format(func.__name__))
        print("Arguments passed: {} ".format(args))
        print("Begin output of {}".format(func.__name__))
        print("#" * 40)
        try:
            func(*args,**kwargs)
        except Exception as e:
            print("Error occured: {}".format(e))
        print("#" * 40)
        print("End of output of {}".format(func.__name__))
        print("#" * 40)
        print("n" * 5)
        return func(*args,**kwargs)
    return inner

您可能想省略两个之一,然后将结果存储在临时变量中,例如:

def decorate(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print("#" * 40)
        print("Testing function {}".format(func.__name__))
        print("Arguments passed: {} ".format(args))
        print("Begin output of {}".format(func.__name__))
        print("#" * 40)
        try:
            result = func(*args,**kwargs)
        except Exception as e:
            print("Error occured: {}".format(e))
            result = None
        print("#" * 40)
        print("End of output of {}".format(func.__name__))
        print("#" * 40)
        print("n" * 5)
        return result
    return inner

最新更新