Python -- 函数装饰器导致函数被调用两次
Python -- Function Decorator results in function being called twice
我在为测试代码编写的一些单元测试中使用了函数装饰器。然而,我发现这个装饰器导致函数被调用两次(因此打印它的输出两次)。
我在一些函数 returning 错误的 return 值之后发现了这个错误,这些值只有在函数被调用两次时才会发生。
#!/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
区块后。
- 并且一次在 return 声明中。
您可能希望将第一个调用(try 块中的调用)更改为:
res = func(*args, **kwargs)
然后简单地:
return res
编辑:(根据@DanielRoseman 的评论)
因为你没有从 except
块加注或 returning,你必须在那里(在 except
内)分配 res
或者 pre-define 它在装饰器的开始处变为 None
(或者任何适合你的程序的值)。
你打了两次电话,确实,这里用粗体显示:
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:
<b>func(*args,**kwargs)</b>
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 <b>func(*args,**kwargs)</b>
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:
<b>result =</b> func(*args,**kwargs)
except Exception as e:
print("Error occured: {}".format(e))
<b>result = None</b>
print("#" * 40)
print("End of output of {}".format(func.__name__))
print("#" * 40)
print("\n" * 5)
return <b>result</b>
return inner
我在为测试代码编写的一些单元测试中使用了函数装饰器。然而,我发现这个装饰器导致函数被调用两次(因此打印它的输出两次)。
我在一些函数 returning 错误的 return 值之后发现了这个错误,这些值只有在函数被调用两次时才会发生。
#!/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
区块后。 - 并且一次在 return 声明中。
您可能希望将第一个调用(try 块中的调用)更改为:
res = func(*args, **kwargs)
然后简单地:
return res
编辑:(根据@DanielRoseman 的评论)
因为你没有从 except
块加注或 returning,你必须在那里(在 except
内)分配 res
或者 pre-define 它在装饰器的开始处变为 None
(或者任何适合你的程序的值)。
你打了两次电话,确实,这里用粗体显示:
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:
<b>func(*args,**kwargs)</b>
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 <b>func(*args,**kwargs)</b>
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:
<b>result =</b> func(*args,**kwargs)
except Exception as e:
print("Error occured: {}".format(e))
<b>result = None</b>
print("#" * 40)
print("End of output of {}".format(func.__name__))
print("#" * 40)
print("\n" * 5)
return <b>result</b>
return inner