带参数的装饰器 [英] Decorators with arguments

查看:54
本文介绍了带参数的装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码如下

  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)#这会打印12

此示例运行良好,但现在我尝试将以下内容添加到装饰器 @my_dec(100)中,我需要乘以给定的数字乘以100。



当我尝试此操作

  @ my_dec(100)
def测试(n):
返回n

I出现以下错误:

 跟踪(最近一次通话):
File ./deco2,第10行,< module>
@my_dec(100)
文件 ./deco2,第5行,包装中
t = func(w)
TypeError:'int'对象不可调用

如何将 100 传递给装饰器? / p>

解决方案

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

要添加参数,您需要编写一个带有参数的函数,并返回装饰器,即返回带包装函数的函数并返回一个函数。



一种方法:

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

如果您考虑 @ 语法扩展为:

  @my_dec(100 )
def测试(n):
返回n

扩展为:

  def测试(n):
返回n
测试= my_dec(100)(测试)

此外,要降低较高的嵌套级别并使装饰器更具可读性和可维护性,您可以定义装饰器类而是在 __ init __ 中接受参数,并在 __ call __ 中调用包装函数。在线上有很多示例。您可以先阅读这个问题



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






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


Code as follows

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

This example is working fine, but now I'm trying to add the following to the decorator @my_dec(100), I need to multiply the given number by 100.

When I try this

@my_dec(100)
def testing(n):
    return n

I get the following error:

Traceback (most recent call last):
  File "./deco2", line 10, in <module>
    @my_dec(100)
  File "./deco2", line 5, in wrap
    t = func(w)
TypeError: 'int' object is not callable

How can I pass the 100 to the decorator?

解决方案

In the first example, you correctly define the decorator as a function which takes the wrapped function, and returns a new function.

To add arguments, you need to write a function which takes the arguments, and returns the decorator, i.e. returns the function which takes the wrapped function and returns a function.

One way to do it:

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

This might be slightly clearer if you think about what the @ syntax expands to:

@my_dec(100)
def testing(n):
    return n

expands to:

def testing(n):
    return n
testing = my_dec(100)(testing)

Also, to reduce the high nesting level and make your decorator more readable and maintainable, you can define a decorator class instead, which takes its arguments in its __init__, and calls the wrapped function in its __call__. There are plenty of examples online. You can start by reading this question.

There are also ways to make your decorator take optional arguments (i.e. so that both your examples work).


And if you really want to understand decorators in depth, read Graham Dumpleton's blog. Highly recommended.

这篇关于带参数的装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆