# ===== CodeLab: Python 装饰器详解 =====
# 来源: https://aoerliang.dpdns.org/articles/python-decorators
# 以下代码片段按文章出现顺序拼接, 共 5 段

# ----- 片段 1 (python) -----
def greet(name):
    return f"你好,{name}"

say = greet          # 函数也是对象,可以赋值
print(say("Ada"))    # 你好,Ada

# ----- 片段 2 (python) -----
def shout(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper() + "!"
    return wrapper

@shout
def hello(name):
    return f"hello {name}"

print(hello("python"))  # HELLO PYTHON!

# ----- 片段 3 (python) -----
from functools import wraps

def logger(func):
    @wraps(func)          # 复制原函数的名字和文档
    def wrapper(*args, **kwargs):
        print(f"调用 {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@logger
def add(a, b):
    """两数相加"""
    return a + b

print(add.__name__, add.__doc__)  # add 两数相加

# ----- 片段 4 (python) -----
def repeat(times):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(times):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def ping():
    print("ping")

ping()  # 连续打印三次 ping

# ----- 片段 5 (python) -----
import time
from functools import wraps, lru_cache

def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        t0 = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} 耗时 {time.perf_counter() - t0:.3f}s")
        return result
    return wrapper

@timer
@lru_cache(maxsize=128)   # 缓存相同参数的返回值
def fib(n):
    return n if n < 2 else fib(n - 1) + fib(n - 2)

print(fib(35))
