这是一个 Python 装饰器的经典问题:既能 不带参数 使用,也能 带参数 使用。
基础思路
区别在于:
- 不带参数时:
@decorator → 直接传入函数。 - 带参数时:
@decorator(x=1) → 先传入参数,返回一个真正的装饰器。
所以需要写一个 兼容两种调用方式的装饰器工厂。
通用实现模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| import functools
def my_decorator(_func=None, *, param1=None, param2=None):
"""
通用装饰器:既支持 @my_decorator 也支持 @my_decorator(param1=xx)
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"参数: param1={param1}, param2={param2}")
return func(*args, **kwargs)
return wrapper
# 如果直接是 @my_decorator,_func 就是被装饰的函数
if _func is not None:
return decorator(_func)
# 如果是 @my_decorator(...),则返回真正的装饰器
return decorator
|
使用示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| @my_decorator
def foo():
print("执行 foo")
@my_decorator(param1=123)
def bar():
print("执行 bar")
foo()
# 输出:
# 参数: param1=None, param2=None
# 执行 foo
bar()
# 输出:
# 参数: param1=123, param2=None
# 执行 bar
|
总结
- 关键点:用
_func=None 区分是否直接传入函数。 - 无参数调用:
@my_decorator → _func 是函数对象。 - 有参数调用:
@my_decorator(param1=...) → _func=None,返回一个 decorator。