带参数的装饰器

Mar*_*kus 3 python decorator python-decorators

代码如下

def my_dec(func):
    def wrap(w):
        t = func(w)
        return t * 4
    return wrap


@my_dec
def testing(n):
    return n


new = testing(3)
print(new)  # This prints 12
Run Code Online (Sandbox Code Playgroud)

这个示例工作正常,但是现在我尝试将以下内容添加到装饰器中@my_dec(100),我需要将给定的数字乘以100。

当我尝试这个

@my_dec(100)
def testing(n):
    return n
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

def my_dec(func):
    def wrap(w):
        t = func(w)
        return t * 4
    return wrap


@my_dec
def testing(n):
    return n


new = testing(3)
print(new)  # This prints 12
Run Code Online (Sandbox Code Playgroud)

如何将其传递100给装饰器?

shx*_*hx2 6

在第一个示例中,您将装饰器正确定义为一个函数,该函数采用包装的函数并返回一个新函数。

要添加参数,您需要编写一个使用参数的函数,并返回decorator,即,返回使用包装函数并返回函数的函数。

一种方法:

def my_dec(x):
    def dec(func):
        def wrap(w):
            t = func(w)
            return t * x
        return wrap
    return dec
Run Code Online (Sandbox Code Playgroud)

如果考虑一下@语法扩展到什么,这可能会稍微清楚一些:

@my_dec(100)
def testing(n):
    return n
Run Code Online (Sandbox Code Playgroud)

扩展为:

def testing(n):
    return n
testing = my_dec(100)(testing)
Run Code Online (Sandbox Code Playgroud)

另外,为降低高级嵌套级别并使装饰器更具可读性和可维护性,您可以改为定义装饰器类,该类在其装饰器中接受其参数__init__,并在其中调用包装的函数__call__。在线上有很多示例。您可以先阅读此问题

还有一些方法可以使装饰器采用可选参数(即,使两个示例均起作用)。


如果您真的想深入了解装饰工,请阅读Graham Dumpleton的博客。强烈推荐。