带参数的装饰器

回顾普通的装饰器

def outer(func):
    def wrapper(*args,**kwargs): #装饰后的方法
        print("before func")
        wrapper_result=func(*args,**kwargs)
        print("after func")
        return wrapper_result
    return wrapper

def foo(a,b):
    return a+b
>>> foo=outer(foo)
>>> foo(2,2)
before func
after func
4

与下面使用@outer修饰等同

>>> @outer
... def foo(a,b):
...     return a+b
... 
>>> foo(1,3)
before func
after func
4

functools.wraps

我们在使用 Decorator 的过程中,难免会损失一些原本的功能信息。
也就是说,原函数的属性失效了。
如果想要保留原函数的属性,就可以用到functools.wraps了。

>>> print(foo.__name__)
wrapper

而functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 modulenamedoc,或者通过参数选择。代码如下:

from functools import wraps
def outer(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        print("before func")
        wrapper_result=func(*args,**kwargs)
        print("after func")
        return wrapper_result
    return wrapper

@outer
def foo(a,b):
    return a+b
>>> print(foo.__name__)
foo

带参数的装饰器

def outer(outer_args):
    def middle(func):
        def wrapper(*args,**kwargs):
            print("before func")
            print("use args: "+outer_args)
            wrapper_result=func(*args,**kwargs)
            print("after func")
            return wrapper_result
        return wrapper
    return middle

@outer("hello")
def foo(a,b):
    return a+b
>>> res=foo(3,3)
before func
use args: hello
after func
>>> res
6

带参数修饰器效果等价于:

>>> foo=outer("hello")(foo)

这种语法有点奇怪,下面来解释这种语法:
一般而言,调用一个函数是加一个括号。如果看见括号后还有一个括号,说明第一个函数返回了一个函数,如果后面还有括号,说明前面那个也返回了一个函数。以此类推。例子如下:

def fun(args_outer):
    print("now in the outer"+" "+args_outer);
    def inner_fun(args_inner):
        print("now in the inner"+" "+args_inner);
    return inner_fun;
>>> from test import *
>>> fun('hello')('world')
now in the outer hello
now in the inner world

这叫做python method chaining

类似的也有类后面多个括号连续写的代码写法:

class add(int):
    def __call__(self,n):

        return add(self+n)

print add(1)(2)(3)

1、首先要理解这个call方法,当类中定义了call方法后,类的实例对象可以带括号调用。
class_x(arguments)<=>class_ x.__call__(arguments)
2、add(1) 是你类的实例对象。
由于类中定义了方法__call__ 所以你的实例对象
add(1)(2) 是调用__call__方法,__call__方法要参数,所以这里传了一个实际参数2。

在这里又要讲讲python特殊函数 __call__()

在Python中,函数其实是一个对象,由于函数可以被调用,所以,函数对象被称为可调用对象。一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。我们把 Person 类变成一个可调用对象:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def __call__(self, friend):
        print 'My name is %s.' % self.name
        print 'My friend is %s.' % friend

现在可以对 Person 实例直接调用:

>>> p = Person('Bob', 'male')
>>> p('Tim')
My name is Bob.
My friend is Tim.
在Python中,装饰器是一种用于修改函数行为的函数。而带参数装饰器就是在普通装饰器的基础上,给装饰器传递额外的参数。这样可以在装饰器内部使用这些参数来改变装饰函数的行为。 在给装饰器传递参数时,需要在装饰器函数上面再包裹一层函数来接收参数,并返回装饰器函数。例如,示例代码中的@wrapper_out('QQ')就是一个带参数装饰器。 当函数执行到带参数装饰器@wrapper_out('QQ')这句时,会先执行wrapper_out('QQ')这个函数,将参数'QQ'传给parameter并得到返回值wrapper函数。然后,再将@符号与wrapper函数结合,得到一个标准的装饰器,按照装饰器的执行流程来装饰函数。 通过带参数装饰器,可以在装饰器内部对被装饰函数进行进一步的处理或设置,从而实现更灵活的函数装饰。这对于需要根据不同的参数来选择不同装饰方式的情况非常有用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [python中带有参数的装饰器](https://blog.youkuaiyun.com/weixin_44799217/article/details/118695357)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [python如何修改装饰器中参数](https://download.youkuaiyun.com/download/weixin_38570854/12870003)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值