我正在学习装饰器,在这里我正在尝试将下面的内容更改为装饰器模式。
def invert(x):
return 1/x
print invert(5)
可以使用装饰器进行更改。
def safe(fun, *args):
if args[0]!=0:
return fun(*args)
else:
"Division by 0"
def invert(x):
return 1/x
print safe(invert, 5)
使用@wapper语法,
def safe(fun, *args):
if args[0]!=0:
return fun(*args)
else:
"Division by 0"
@safe
def invert(x):
return 1/x
print invert(5)
上面的代码给出了错误IndexError: tuple index out of range
。我试图了解是什么导致错误以及如何纠正它。
答案 0 :(得分:4)
你的主要问题是装饰者需要返回一个函数,而不是一个值。装饰器将基于它的新函数替换为已定义的函数。
除此之外,return
块中没有else
语句,只是一个字符串文字。你可能想要归还。
def safe(fun):
def f(*args):
if not args[0] == 0:
return fun(*args)
else:
return "Division by 0"
return f
就像一个注释,我认为这只是为了练习的目的,但错误不应该在Python中无声地传递 - 发出异常的行为通常比返回更有用错误的字符串。事实上,为了更自然地为Python实现这一点,你想要遵循请求宽恕,而不是许可 mantra:
def safe(fun):
def f(*args):
try:
return fun(*args)
except ZeroDivisionError:
return "Division by 0"
return f
另外,请注意像“安全”这样的清晰语句名称 - 仍然可能抛出其他异常。
答案 1 :(得分:3)
你做错了。
def safe(fun):
def wrapper(*args)
if args[0]!=0:
return fun(*args)
else:
return "Division by 0"
return wrapper
对于您用它装饰的每个函数,函数safe
被称为一次。然后在每次调用修饰函数时调用由safe
返回的内部函数 - 此处称为wrapped
。它负责调用原始函数或完全执行其他操作。
所以装饰器只需要一个参数:要包装的函数。 BUT ,有装饰器函数,这是一个返回装饰器的函数(所以还有一层包装函数):
def safe(singularities):
def decorator(fun):
def wrapper(*args)
if args[0] not in singularities:
return fun(*args)
else:
return "Division by 0"
return wrapper
return decorator
因此safe
装饰器函数现在可以返回无数个不同的装饰器。使用方式如下:
@safe([0])
def invert(x):
return 1 / x
@safe([-1, 1])
def foo(x)
return 1 / ((x - 1) * (x + 1))
对于那些想知道为什么我在贴出他的帖子之后我发布了与Lattyware基本相同答案的答案:直到我开始写我的答案后,答案才解决所有问题,现在我添加的信息比在他的,所以我不会删除它,因为它不是一个完全重复。