Python装饰器
mazinga 人气:11、装饰器的本质
装饰器本质上是一个闭包函数,可以让其它函数在不需要任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数。
-
闭包函数
1)必须是嵌套函数,即外函数中定义了一个内函数;
2)内函数引用了外函数作用域中(注意:非全局)的变量;
3)外函数的返回值是内函数的引用;
4)检测函数是否为闭包函数:
function.__closure__
,是闭包,返回一个cell
,不是闭包,返回None
; -
函数
1)什么是函数:组织好的、可重复使用的,用来实现单一或相关联功能的代码段;
2)函数的优点:函数能提高应用的模块性和代码的重复利用率;
3)函数的定义:使用
def
关键字;def func(): print("Hello, World!")
4)函数的参数:根据函数在定义时和调用时,函数的参数有不同的概念;
- 定义时:位置参数、默认参数、不定长参数;
def func(a, b=0, *args, **kwargs): print(f"位置参数:{a}") print(f"默认参数:{b}") print(f"不定长参数:元组{args},字典{kwargs}")
- 调用时:必备参数(必须传)、关键字参数(可传可不传)、不定长参数(可传可不传);
func("Hello") # "Hello" >> a func("Hello", b=1) # "Hello" >> a, 1 >> b func("Hello", 2) # "Hello" >> a, 2 >> b func("Hello", 2, 3, c="World") # "Hello" >> a, 2 >> b, 3 >> *args, c="World" >> **kwargs
5)匿名函数:使用
lambda
关键字,只是一个表达式,不是代码块,逻辑有限;add = lambda a, b: a + b
6)变量作用域:LEGB;
- L:Local,局部作用域;
- E:Enclosing,闭包函数外的函数中;
- G:Global,全局作用域;
- B:Built-in,内建作用域;
7)有关函数的几个概念;
- 函数即变量:函数可作为参数,也可作为返回值;
- 高阶函数:以函数作为参数或返回值的函数,内置函数
map()
、filter()
、functools
包中的reduce()
; - 嵌套函数:函数里定义函数;
- 嵌套函数中变量的生命周期:正常情况下,一个函数运行结束,函数所有局部对象都会被回收,释放内存。但是闭包是一种特殊情况。闭包中,如果外函数在结束时,外函数作用域中的临时变量被内函数调用,外函数就会将该变量绑定给内函数,然后再结束;
2、装饰器应满足条件
- 给被装饰函数添加新的功能;
- 不能改变被装饰函数的代码;
- 不能改变被装饰函数的调用方式;
3、装饰器的应用场景
- 插入日志;
- 性能测试;
- 事务处理;
- 缓存、权限校验;
4、装饰器的固定格式
-
格式1
def decorator(func): # decorator函数中嵌套了inner函数 def inner(*args, **kwargs): """something before func""" f = func(*args, **kwargs) # 内函数inner调用了外函数decorator作用域中的变量func """something after func""" return f return inner # 外函数decorator的返回值是inner(对内函数inner的引用)
-
格式2
from functools import wraps def decorator(func): @wraps def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper
5、装饰器的演进
-
将被装饰的函数显式传入装饰器,被装饰函数没有参数和返回值;
import time def func(): print("I'm func.") def timer(f): def inner(): start = time.time() f() end = time.time() print(end - start) return inner func = timer(func) # 将函数func作为参数传递给timer装饰器,将返回结果赋值给变量func func() # func(),即执行了func
-
将被装饰函数放在语法糖下一行,被装饰函数不带参数,没有返回值;
import time def timer(f): def inner(): start = time.time() f() end = time.time() print(end - start) return inner @timer # @timer被称为语法糖,等价于func=timer(func) def func(): print("I'm func.") func()
-
将被装饰函数放在语法糖下一行,被装饰函数带1个参数,没有返回值;
import time def timer(f): def inner(i): start = time.time() f(i) end = time.time() print(end - start) return inner @timer def func(x): print(x) func("Hello, World!")
-
将被装饰函数放在语法糖下一行,被装饰函数带2个参数,没有返回值;
import time def timer(f): def inner(*args, **kwargs): start = time.time() f(*args, **kwargs) end = time.time() print(end - start) return inner @timer def func(x, y): print(f"The first argument is {x}, the second is {y}.") func(2, 24)
-
将被装饰函数放在语法糖下一行,被装饰函数带多个参数,有返回值;
import time def timer(f): def inner(*args, **kwargs): start = time.time() r = f(*args, **kwargs) end = time.time() print(end - start) return r return inner @timer def func(x, y, z=3): print(f"Arguments are {}、{} and {}.") return 'Over' func(1, 2, z=3) print(func(1, 2, z=3))
-
带参数的装饰器,被装饰函数不带参数,没有返回值;
def outer(flag): def decorator(f): def inner(*args, **kwargs): if flag: print("Ahead func") r = f(*args, **kwargs) if flag: print("After func") return r return inner return decorator @outer(True) def func(): print("Hello, World!") func()
-
多个装饰器装饰同一个函数,被装饰函数不带参数,没有返回值;
def decorator1(f): def inner(): print('Decorator1, before f') f() print('Decorator1, after f') return inner def decorator2(f): def inner(): print('Decorator2, before f') f() print('Decorator2, after f') return inner @decorator2 @decorator1 def func(): print("I'm func.")
6、装饰器的总结
Python中的装饰器一共有4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类;
-
函数装饰函数:函数作为参数被传入装饰器函数中;
def decorator(f): def inner(*args, **kwargs): print(f"function name: {f.__name__}") r = f(*args, **kwargs) return r return inner @decorator # @decorator 等价于 addition=decorator(addition) def addition(x, y): return x + y print(addition(3, 7))
-
函数装饰类:类作为参数被传入装饰器函数中;
def decorator(cls): def inner(*args, **kwargs): print(f"class name: {cls.__name__}") return cls(*args, **kwargs) return inner @decorator # @decorator 等价于 Func=decorator(Func) class Func: def __init__(self, item): self.item = item def func(self): print(f"self.a = {self.a}") f = Func('Hello, World!') f.func()
-
类装饰函数:函数作为参数被传入装饰器类中;
class Decorator: def __init__(self, f): self.f = f def __call__(self, item): print(f"function name: {self.f.__name__}") return self.f(item) @Decorator # @Decorator 等价于 func = Decorator(func).__call__ def func(i): return i print(func("Hello, World!"))
-
类装饰类:类作为参数被传入装饰器类中;
class Decorator: def __init__(self, cls): self.cls = cls def __call__(self, item): print(f"class name: {self.cls.__name__}") return self.cls(item) @Decorator # @Decorator 等价于 Func = Decorator(Func).__call__ class Func: def __init__(self, v): self.v = v def func(self): print(self.v) f = Func("Hello, World!") f.func()
加载全部内容