装饰器不带参数:
例子中的功能:在函数运行前打印一句话
装饰器
- note one:
*arg
: allow all the tuple input for func**kwarg
: allow all the dict input for func
- note two:
return func()
or xx = func()
: run the func
return func
or xx = func
: just return the func address, not run it
1
2
3
4
5
6
7
| from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*arg, **kwarg):
print("decorator: run func now")
return func(*arg, **kwarg)
return wrapper
|
装饰函数的方法
@decorator
语法糖
如果不导入wraps
, 将会丢失原来函数名称,则输出为func_name: wrapper
1
2
3
4
5
6
7
8
9
10
| @decorator
def org_func():
print("org_func: hello world")
org_func()
print("func name:", org_func.__name__)
# output:
# decorator: run func now
# org_func: hello world
# func_name: org_func
|
本质上, 等价于以下代码
可以看出@decorator
在不带参数的情况下会把被装饰的函数当作第一个参数传入装饰器
1
2
| org_func = decorator(org_func)
org_func()
|
解除装饰器:.wrapped__()
方法
1
2
3
| org_func.__wrapped__()
# output
# org_func: hello world
|
装饰函数带参数
带参数的装饰器
装饰器功能: 用来修改 dataloader 中的__len__
函数,让其返回我们设定的sample_size
1
2
3
4
5
6
7
8
9
10
11
12
| from functools import wraps, partial
def change_len(func=None, sample_size=5):
if not func:
return partial(change_len, sample_size=sample_size)
@wraps(func)
def wrapper(*arg, **kwarg):
return sample_size
return wrapper
|
装饰函数
- 语法糖
1
2
3
4
5
| @change_len(sample_size=7)
def print_len(dataset):
return len(dataset)
print(print_len([1, 2, 3]))
|
- 等价于
1
| print_len = change_len(sample_size=7)(print_len)
|
- 可以看出被包装函数没有被传入
change_len
函数,所以需要利用functools.partial
方法来返回一个为完全初始化的自身,除了被包装函数,别的部分都已经确定下来