带参数的装饰器
https://blog.csdn.net/e15273/article/details/78617498
回顾普通的装饰器
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
1
2
3
4
5
6
7
8
9
10
11
>>> foo=outer(foo)
>>> foo(2,2)
before func
after func
4
1
2
3
4
5
与下面使用@outer修饰等同
>>> @outer
... def foo(a,b):
... return a+b
...
>>> foo(1,3)
before func
after func
4
1
2
3
4
5
6
7
8
functools.wraps
我们在使用 Decorator 的过程中,难免会损失一些原本的功能信息。
也就是说,原函数的属性失效了。
如果想要保留原函数的属性,就可以用到functools.wraps了。
>>> print(foo.__name__)
wrapper
1
2
而functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 module、name、doc,或者通过参数选择。代码如下:
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
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> print(foo.__name__)
foo
1
2
带参数的装饰器
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> res=foo(3,3)
before func
use args: hello
after func
>>> res
6
1
2
3
4
5
6
带参数修饰器效果等价于:
>>> foo=outer("hello")(foo)
1
这种语法有点奇怪,下面来解释这种语法:
一般而言,调用一个函数是加一个括号。如果看见括号后还有一个括号,说明第一个函数返回了一个函数,如果后面还有括号,说明前面那个也返回了一个函数。以此类推。例子如下:
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;
1
2
3
4
5
6
>>> from test import *
>>> fun('hello')('world')
now in the outer hello
now in the inner world
1
2
3
4
这叫做python method chaining
类似的也有类后面多个括号连续写的代码写法:
class add(int):
def __call__(self,n):
return add(self+n)
print add(1)(2)(3)
1
2
3
4
5
6
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
1
2
3
4
5
6
7
现在可以对 Person 实例直接调用:
>>> p = Person('Bob', 'male')
>>> p('Tim')
My name is Bob.
My friend is Tim.
---------------------
作者:Avalonist
来源:CSDN
原文:https://blog.csdn.net/e15273/article/details/78617498
版权声明:本文为博主原创文章,转载请附上博文链接!