python
from functools import wraps
def deco(func):
@wraps(func) # 保留原函数的 __name__、__doc__ 等
def _deco(*args, **kwargs):
print(f"before {func.__name__} called.")
#或者写作
#print("before %s called." % func.__name__)
ret = func(*args, **kwargs)
print(f" after {func.__name__} called. result: {ret}")
return ret
return _deco
@deco
def myfunc(a, b):
print(f" myfunc({a},{b}) called.")
return a + b
@deco
def myfunc2(a, b, c):
print(f" myfunc2({a},{b},{c}) called.")
return a + b + c
# 示例调用
myfunc(1, 2)
myfunc2(1, 2, 3)
逐行讲解
def deco(func):
定义装饰器工厂deco,参数func就是"被装饰的原函数"。
def _deco(*args,**kwargs):
定义包装器_deco。用*args,**kwargs接住原函数可能的所有位置参数/关键字参数,使装饰器对任意签名的函数都通用
@deco
def myfunc(a,b):
语法糖:等价于myfunc=deco(myfunc)
从这一行开始,"myfunc"这个名字实际上指向的是包装器_deco,内部再去调原来的myfunc函数体
语法糖
在最后面补充个有意思的东西:语法糖
一、为什么要有 @deco
语法?
这两句是完全等价的:
python
@deco
def myfunc():
...
python
def myfunc():
...
myfunc = deco(myfunc)
那 Python 为什么还要多此一举加一个 @
语法呢?
------因为 Python 追求的是可读性和简洁性。
如果有多个装饰器:
python
@deco1
@deco2
@deco3
def myfunc():
...
这相当于:
python
def myfunc():
...
myfunc = deco1(deco2(deco3(myfunc)))
明显使用@语法 简化了代码结构 + 提高了可读性
这就是"语法糖"的作用。
二、"语法糖"是什么意思?
@deco
是 myfunc = deco(myfunc)
的语法糖
"语法糖(syntactic sugar)"的意思是:
语法上更甜、更好看,但不增加任何新功能。
它不会改变语言本身的功能,只是让代码写起来更自然、更"人类友好"。
比如👇
普通写法 | 语法糖写法 | 说明 |
---|---|---|
myfunc = deco(myfunc) |
@deco |
装饰器的语法糖 |
a = a + 1 |
a += 1 |
语法糖(更短) |
for i in range(len(lst)): |
for i, v in enumerate(lst): |
语法糖(更优雅) |
def f(x): return x*x |
f = lambda x: x*x |
lambda 语法糖 |
Python 的设计哲学之一是:"让代码像自然语言一样优雅 ",
所以引入了很多这样的"糖"式语法,让程序员写起来更舒服。