title: "Python 装饰器杂录" categories: Tech updated: comments: true
装饰器基础, 以及常用装饰器略了, 比如 staticmethod
, classmethod
, property
, functools.lru_cache
.
官方文档, New in version 3.8.
类似 C++ 或 Java 的 final
.
A decorator to indicate to type checkers that the decorated method cannot be overridden, and the decorated class cannot be subclassed.
比如 pandas/core/groupby/groupby.py 用到了, 很多其他库也会用到.
官方文档.
仅仅用来做 type hint. 严格使用 type annotation 时, 如果对不同的输入类型, 输出类型不同, 可以用这个装饰器. 用法参考 Python Type Hints - How to Use @overload - Adam Johnson. 比如 locust/user/task.py 用到了这个.
@overload
def task(weight: TaskT) -> TaskT:
...
@overload
def task(weight: int) -> Callable[[TaskT], TaskT]:
...
def task(weight: Union[TaskT, int] = 1) -> Union[TaskT, Callable[[TaskT], TaskT]]:
# 实际实现
如果真的要 "重载" Python 的函数, 可以参考 The Correct Way to Overload Functions in Python, 用第三方 multipledispatch 库. 不过感觉没必要. Python 内置有 functools.singledispatch
, 暂时没见到很好的用例.
目标是即可以写成 @dec
也可以写成 @dec(param=...)
. 基本写法是
import functools
def decorator(func=None, param=None):
if func is None:
return functools.partial(decorator, param=param)
@functools.wraps(func)
def wrapper(*args, **kwargs):
if param:
pass
result = func(*args, **kwargs)
return result
return wrapper
更完整的例子可以见我写的 计时器装饰器. 参考了
很多库也会实现带参数的装饰器, 用到的 trick 也差不多.
TODO.
见 pandas/util/_decorators.py, 选几个.
比如 doc
装饰器, 配合 textwrap.dedent
可以让多行字符串更易读.
其他