Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';Python修饰符是否可以跨定义链接?_Python_Decorator - Fatal编程技术网

为什么可以';Python修饰符是否可以跨定义链接?

为什么可以';Python修饰符是否可以跨定义链接?,python,decorator,Python,Decorator,为什么以下两个脚本不相等 (摘自另一个问题:) def makebold(fn): def wrapped(): 返回“+fn()+” 退货包装 def MAKE斜体(fn): def wrapped(): 返回“+fn()+” 退货包装 @马克博尔德 @使斜体 def hello(): 返回“你好,世界” 打印hello()##返回hello world 还有一个装饰师: def makebold(fn): def wrapped(): return "<b&g

为什么以下两个脚本不相等

(摘自另一个问题:)

def makebold(fn):
def wrapped():
返回“+fn()+”
退货包装
def MAKE斜体(fn):
def wrapped():
返回“+fn()+”
退货包装
@马克博尔德
@使斜体
def hello():
返回“你好,世界”
打印hello()##返回hello world
还有一个装饰师:

def makebold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped

@makebold
def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped

@makeitalic
def hello():
    return "hello world"

print hello() ## TypeError: wrapped() takes no arguments (1 given)
def makebold(fn):
def wrapped():
返回“+fn()+”
退货包装
@马克博尔德
def MAKE斜体(fn):
def wrapped():
返回“+fn()+”
退货包装
@使斜体
def hello():
返回“你好,世界”
print hello()##TypeError:wrapped()不接受任何参数(给定1个)
为什么我想知道?我编写了一个
retry
decorator来捕获MySQLdb异常-如果异常是暂时的(例如超时),它将在休眠一点后重新调用该函数


我还有一个
modifies\u db
decorator,它负责一些与缓存相关的管理工作
modifies\u db
retry
修饰,因此我假设所有用
modifies\u db
修饰的函数也会隐式重试。我哪里出错了?

原因是makebold中的wrapped()不接受任何参数

当你像那样使用装饰器时,它可能会引起一些问题,我将发布一个如何实现你想要的东西的示例,请给我一点时间

下面是一个您需要的工作示例

def makebold(rewrap=False):
    if rewrap:
        def inner(decorator):
            def rewrapper(func):
                def wrapped(*args, **kwargs):
                    return "<b>%s</b>" % decorator(func)(*args,**kwargs)
                return wrapped
            return rewrapper
        return inner

    else:
        def inner(func):
            def wrapped(*args, **kwargs):
                return "<b>%s</b>" % func(*args, **kwargs)    
            return wrapped
        return inner

@makebold(rewrap=True)
def makeitalic(fn):
    def wrapped(*args, **kwargs):
        return "<i>%s</i>" % fn(*args, **kwargs)
    return wrapped

@makeitalic
def hello():
    return "hello world"

@makebold()
def hello2():
    return "Bob Dole"    

if __name__ == "__main__":
    print hello()   
    print hello2()
请注意,makebold是唯一的递归修饰符。还要注意用法上的细微差别:
@makebold()
@makeitalic

问题在于将“makeitalic”(接受一个参数)替换为“makebold”中接受零参数的“wrapped”函数

使用
*args、**kwargs
将参数传递到链的下游:

def wrapped(*args, **kwargs):
    return "<b>" + fn(*args, **kwargs) + "</b>"
def包装(*args,**kwargs):
返回“+fn(*args,**kwargs)+”

第二个例子的问题是

@makebold
def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped

这里
makeitalic
使用
makebold
装饰
wrapped

好问题。几个月前,我在做自己的重试修饰符时遇到了相同的场景。这需要重试次数,因此问题本身与您的有点不同,但具有与下面所示相同的解决方案。问题比实际情况更严重。包装另一个装饰者还有一些问题。+1这正好指出了问题所在以及需要如何做。基本上,问题来自于认为decorators做函数合成,但他们没有。是的,这正是我想做的,是的,我误解了decorators==函数合成-1。。。过于复杂,“makeitalic”是粗体+斜体的一个坏名字。看看哪一个在几行代码中做同样的事情。
def wrapped(*args, **kwargs):
    return "<b>" + fn(*args, **kwargs) + "</b>"
@makebold
def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped
def makeitalic(fn):
    @makebold
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped