首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更改为装饰器模式

更改为装饰器模式
EN

Stack Overflow用户
提问于 2012-06-21 18:46:22
回答 2查看 131关注 0票数 0

我正在学习装饰器,在这里我试着将下面的模式改为装饰器模式。

代码语言:javascript
复制
def invert(x):
    return 1/x

print invert(5)

可以使用装饰器进行更改。

代码语言:javascript
复制
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语法,

代码语言:javascript
复制
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。我正在试图理解是什么让它错了,以及如何纠正它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-21 18:48:43

您的主要问题是装饰器需要返回一个函数,而不是一个值。装饰器将定义的函数替换为基于它的新函数。

除此之外,else块中没有return语句,只有一个字符串文字。你可能是想把它还回去。

代码语言:javascript
复制
def safe(fun):
    def f(*args):
        if not args[0] == 0:
            return fun(*args)
        else:
            return "Division by 0"
    return f

作为说明,我假设这只是为了练习的目的,但是错误不应该在Python中静默传递-发出异常的行为通常比在错误时返回字符串更有用。事实上,要在Python中更自然地实现这一点,您需要遵循的是请求宽恕,而不是允许的咒语:

代码语言:javascript
复制
def safe(fun):
    def f(*args):
        try:
            return fun(*args)
        except ZeroDivisionError:
            return "Division by 0"
    return f

此外,要注意像“safe”这样的语句名称--其他异常仍然可能被抛出。

票数 4
EN

Stack Overflow用户

发布于 2012-06-21 18:59:52

你做错了。

代码语言:javascript
复制
def safe(fun):
    def wrapper(*args)
        if args[0]!=0:
            return fun(*args)
        else:
            return "Division by 0"
    return wrapper

函数safe会为您用它修饰的每个函数调用一次。然后,每次调用修饰后的函数时,都会调用由safe返回的内部函数--这里称为wrapped。它负责调用原始函数,或者执行完全不同的操作。

因此,装饰器只有一个参数:要包装的函数。但是,还有装饰器函数,这是一个返回装饰器的函数(所以多了一层包装函数):

代码语言:javascript
复制
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装饰器函数现在可能返回无限数量的不同装饰器。像这样使用:

代码语言:javascript
复制
@safe([0])
def invert(x):
    return 1 / x

@safe([-1, 1])
def foo(x)
    return 1 / ((x - 1) * (x + 1))

对于那些想知道为什么我在Lattyware发布了他的答案后发布了本质上与Lattyware相同的答案的人来说:这个答案直到我开始写我的答案之后才解决了所有的问题,现在我添加了比他的更多的信息,所以我不会删除它,因为它不是完全重复的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11136479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档