python复习--装饰器
一、Python 的底层视角:名字绑定(非常重要)
Python 中没有“变量”,只有“名字 → 对象”的绑定关系
你平时把 a 叫“变量”——在日常编程交流中没错;
但在 Python 的语言模型和解释器视角中,
更准确的说法是:a 是“名字(name)”,不是传统意义上的变量。
a = 10
含义是:
解释器创建一个值为 10 的 int 对象,并将该对象绑定到当前作用域中的名字 a
二、什么是装饰器(一句话定义)
装饰器就是:
在“定义阶段”,
接收一个对象(函数 / 类),
返回一个新对象,
并让原来的名字重新指向这个新对象。
三、装饰器语法只是语法糖(重点)
不管是函数还是类:
@decorator
obj
永远等价于:
obj = decorator(obj)
这是理解装饰器的一切基础,装饰器只是语法糖
四、装饰器什么时候执行?
装饰器在 定义阶段 执行
不是在函数调用 / 类实例化时执行
1. 什么叫“定义阶段”
函数的两个阶段
def foo():
print("hello")
foo() # 调用阶段
这里有 两个完全不同的时间点:
-
定义阶段
def foo(): print("hello")Python 读取 def foo():
创建一个函数对象
把名字 foo 绑定到这个函数对象
但 不执行函数体定义阶段就是指 Python 在执行模块顶层代码时,
遇到 def 语句并创建函数对象的那个时刻。 -
调用阶段
foo() # 调用阶段才会执行 print(“hello”)
装饰器发生在 第 1 步:定义阶段
2. 例子
def my_decorator(func):
print("装饰器执行了") # 关键
return func
@my_decorator
def hello():
print("hello 函数执行")
如果没有装饰器@my_decorator,这两个函数只是创建了对象,不会执行内部代码,不会有任何输出
但是加了装饰器实际运行结果:
装饰器执行了
你还没有调用 hello()
但装饰器里的 print 已经执行了
-
等价写法(理解核心)
def my_decorator(func): print("装饰器执行了") return func def hello(): print("hello 函数执行") hello = my_decorator(hello) # 在函数对象定义完成后立即执行① 创建 my_decorator 函数对象
② 创建 hello 函数对象
③ 调用 my_decorator(hello)
④ hello 重新绑定
更清晰的例子
def my_decorator(func):
print("① 装饰器执行")
def wrapper():
print("③ wrapper 执行")
func()
return wrapper
@my_decorator
def hello():
print("④ hello 执行")
print("② 定义结束")
hello()
-
执行顺序结果
① 装饰器执行
② 定义结束
③ wrapper 执行
④ hello 执行 -
执行顺序解析
1 解释器读到 @my_decorator
2 创建函数对象 hello
3 执行 my_decorator(hello) (定义阶段)
4 把返回的 wrapper 绑定给名字 hello
5 程序继续往下执行
6 调用 hello(),其实调用的是 wrapper()
五、函数装饰器(基础版)
示例
def my_decorator(func):
def wrapper():
print("前置逻辑")
func()
print("后置逻辑")
return wrapper
@my_decorator
def hello():
print("hello")
等价写法(名字绑定视角)
def my_decorator(func):
def wrapper():
print("前置逻辑")
func()
print("后置逻辑")
return wrapper
hello = my_decorator(hello)
含义:
右边 hello:原函数对象
左边 hello:名字被重新绑定
新对象是 wrapper
六、带参数的装饰器(三层结构)
标准结构(一定记)
def case(param1, param2):
def decorator(obj):
# 装饰逻辑
return obj
return decorator
@case("01", "测试用例")
def func():
pass
等价于
def case(param1, param2):
def decorator(obj):
# 装饰逻辑
return obj
return decorator
def func():
pass
func = case("01", "测试用例")(func)
@case(…)
不是“只执行 case”,
而是语法强制要求:
先执行 case(…),再执行它的返回值(func)。
执行顺序
- 执行 case(“01”, “测试用例”)
- 返回 decorator
- 执行 decorator(func)
- 名字重新绑定
七、最基础的类装饰器
def class_decorator(cls):
cls.tag = "测试类"
return cls
@class_decorator
class MyClass:
pass
等价写法
def class_decorator(cls):
cls.tag = "测试类"
return cls
MyClass = class_decorator(MyClass)
-
右边的 MyClass
是一个名字
指向类对象
作为参数传入装饰器 -
左边的 MyClass
是同一个名字
被重新绑定
指向装饰器返回的新对象
八、装饰器返回的对象,可能是哪几种?
-
情况 1(最常见)
def class_decorator(cls): cls.tag = "demo" return cls返回 原类对象
名字仍然指向同一个类 -
情况 2(换了一个新类)
def class_decorator(cls): class NewClass(cls): pass return NewClass返回 全新的类对象
MyClass 指向 NewClass -
情况 3(返回实例,不推荐)
def class_decorator(cls): return cls()MyClass 不再是类
而是实例对象
九、类装饰器的执行时间线
@class_decorator
class MyClass:
pass
执行顺序:
- 执行 class 代码块
- 创建类对象
- 调用 class_decorator(MyClass)
- 名字 MyClass 重新绑定
十、带参数的类装饰器(结合你最初的 case)
def case(testcase_id, testcase_name):
def decorator(cls):
cls.testcase_id = testcase_id
cls.testcase_name = testcase_name
return cls
return decorator
@case("01", "test")
class Template:
pass
等价于:
def case(testcase_id, testcase_name):
def decorator(cls):
cls.testcase_id = testcase_id
cls.testcase_name = testcase_name
return cls
return decorator
Template = case("01", "test")(Template)
十一、总结
装饰器就是:
在定义阶段,
把一个“名字指向的对象”传进去加工,
再让这个名字重新指向加工后的返回对象。
更多推荐


所有评论(0)