目录
1、函数装饰器-不带参数的二阶装饰器
import functools
def deco(func):
print('外部函数')
@functools.wraps(func)
def wrap():
print('内部函数')
return func()
return wrap
@deco
def test():
print('被装饰函数')
print(f'被装饰函数的名称={test.__name__}')
test()
D:\pycharm_workspace\Demo\venv\Scripts\python.exe D:/pycharm_workspace/Demo/demo/test.py
外部函数
被装饰函数的名称=test
内部函数
被装饰函数
Process finished with exit code 0
代码从上向下执行,当执行到 @deco的时候,会执行 test=deco(test),这时候test=wrap,所以执行结果中,会先打印出 “外部函数”,然后继续向下执行,打印出函数的名称,再继续向下执行,调用test(),相当于调用wrap(),后面的就省略不说了
2、函数装饰器-带参数的二阶装饰器
import functools
def deco(func):
print('外部函数')
@functools.wraps(func)
def wrap(*args, **kwargs):
print('内部函数')
return func(*args, **kwargs)
return wrap
@deco
def test(a, b, c):
print(f'被装饰函数{a}-{b}-{c}')
print(f'被装饰函数的名称={test.__name__}')
test(1, 2, 3)
D:\pycharm_workspace\Demo\venv\Scripts\python.exe D:/pycharm_workspace/Demo/demo/test.py
外部函数
被装饰函数的名称=test
内部函数
被装饰函数1-2-3
Process finished with exit code 0
内部函数可以传形参,也可以用通用 *args和**kwargs参数
3、函数装饰器-不带参数的三阶装饰器
import functools
def demo(text):
print('第一层')
def deco(func):
print('外部函数')
@functools.wraps(func)
def wrap(*args, **kwargs):
print('内部函数', text)
return func(*args, **kwargs)
return wrap
return deco
@demo('gg')
def test():
print(f'被装饰函数')
print(f'被装饰函数的名称={test.__name__}')
test()
D:\pycharm_workspace\Demo\venv\Scripts\python.exe D:/pycharm_workspace/Demo/demo/test.py
第一层
外部函数
被装饰函数的名称=test
内部函数 gg
被装饰函数
Process finished with exit code 0
当代码执行到 @demo('gg'),相当于test=demo('gg')(test),所以控制台先输入 第一层,然后输出 外部函数,后面流程同之前逻辑一样
4、函数装饰器-带参数的三阶装饰器
import functools
def demo(text):
print('第一层')
def deco(func):
print('外部函数')
@functools.wraps(func)
def wrap(*args, **kwargs):
print('内部函数', text)
return func(*args, **kwargs)
return wrap
return deco
@demo('gg')
def test(a, b):
print(f'被装饰函数{a}-{b}')
print(f'被装饰函数的名称={test.__name__}')
test(11, 22)
就是多了传参而已
5、类装饰器-不带参数
import functools
class Demo(object):
def __init__(self, func):
print('初始化函数开始')
self.func = func
print('初始化函数结束')
def __call__(self, *args, **kwargs):
print('调用函数开始')
return self.func(*args, **kwargs)
@Demo
def test():
print(f'被装饰函数')
print('准备调用test')
test()
D:\pycharm_workspace\Demo\venv\Scripts\python.exe D:/pycharm_workspace/Demo/demo/test.py
初始化函数开始
初始化函数结束
准备调用test
调用函数开始
被装饰函数
Process finished with exit code 0
当代码执行到 @Demo,相当于 test=Demo(test),因为是类,所以执行初始化init函数,所以打印:初始化函数开始、初始化函数结束,然后继续向下执行,当调用test,相当于对实例化对象进行调用,会调用call函数,然后继续。。。
6、类装饰器-带参数
import functools
class Demo(object):
def __init__(self, kk):
print('初始化函数开始')
self.kk = kk
print('初始化函数结束')
def __call__(self, func):
print('调用函数开始')
@functools.wraps(func)
def wrap(*args, **kwargs):
print('inner', self.kk)
return func(*args, **kwargs)
return wrap
@Demo('kk')
def test():
print(f'被装饰函数')
print('准备调用test')
test()
print(test.__name__)
D:\pycharm_workspace\Demo\venv\Scripts\python.exe D:/pycharm_workspace/Demo/demo/test.py
初始化函数开始
初始化函数结束
调用函数开始
准备调用test
inner kk
被装饰函数
test
Process finished with exit code 0
当代码运行到 @Demo('kk'),相当于 test=Demo('kk')(test),所以控制打印的数据,一直到call方法里面的 调用函数开始,继续向下执行 调用test(),相当于调用call方法里面的 wrap()函数,
@functools.wraps(func)的作用是让函数名称不会变化,否则test.__name__的值是wrap