装饰器语法糖运用
装饰器语法糖运用
-
前言:函数名是一个特性的变量,可以作为容器的元素,也可以作为函数的参数,也可以当做返回值。
-
闭包定义:
-
内层函数对外层函数(非全局)变量的引用,这个内层函数就可以成为闭包
-
在Python中我们用
__closure__
来检查函数是否是闭包 -
def func1(): name = '张三' def func2(): print(name) # 能够访问到外层作用域的变量 func2() print(func2.__closure__) # (<cell at 0x1036c7438: str object at 0x10389d088>,) func1() print(func1.__closure__) # None
-
-
装饰器
-
前言:软件设计原则:开闭原则,又称开放封闭原则
- 指对扩展代码的功能是开放的,但对修改源代码是封闭的,
-
def create_people(): print('女娲真厉害,捏个泥吹口气就成了人!') def a(func): def b(): print('洒点水') func() return b ret = a(create_people) ret()
-
通过装饰器语法等同于
-
def a(func): def b(): print('洒点水') func() return b @a # 装饰器语法糖的作用就是上述函数ret() def create_people(): print('女娲真厉害,捏个泥吹口气就成了人!') create_people()
-
-
装饰带返回值的函数,即return出被装饰函数的执行结果
-
def foo(func): # 接收的参数是一个函数名 def bar(): # 定义一个内层函数 print("这里是新功能...") # 新功能 r = func() # 在内存函数中拿到被装饰函数的结果 return r # 返回被装饰函数的执行结果 return bar # 定义一个有返回值的函数 @foo def f1(): return '嘿嘿嘿' # 调用被装饰函数 ret = f1() # 调用被装饰函数并拿到结果 print(ret)
-
-
装饰带参数的函数
-
def func1(func): # 接收的参数为一个函数名 def inner(*args, **kwargs): # 这里需要定义和被装饰函数相同的参数 print("新功能") # 新功能 ret = func(*args, **kwargs) #被装饰的函数和参数 print("新功能") return ret return inner # 定义一个需要俩个参数的函数 @func1 def func(a, b): return a + b ret = func(3, 5) print(ret)
-
-
带参数的装饰器 即在装饰器外在写一层函数,从而使其带参数
-
def d(a=None): # 定义一个外层函数,给装饰器传参数 def func1(func): # 接收的是一个函数名 def inner(*args, **kwargs): # 被装饰的函数,和参数 if a: print(f"欢迎来到{a}") #添加新功能 else: print("欢迎来到王者荣耀") func(*args, **kwargs) return inner return func1 # @d("英雄联盟") # def func(st): # print(st) # func("敌军还有三十秒到达战场") # 欢迎来到英雄联盟 # 敌军还有三十秒到达战场 @d() def func(st): print(st) func("敌军还有三十秒到达战场") # 欢迎来到王者荣耀 # 敌军还有三十秒到达战场
-
-
装饰器修复技术
-
定义:被装饰的函数最终都会失去本来的__doc__等信息, Python给我们提供了一个修复被装饰函数的工具。
-
from functools import wraps #导入 print(f1.__doc__) print(f1.__name__)
-
-
多个装饰器装饰同一函数
-
from functools import wraps def wrapper2(func): @wraps(func) def inner(*args, **kwargs): r = func(*args, **kwargs) return f"<2>{r}</2>" return inner def wrapper1(func): @wraps(func) def inner(*args, **kwargs): r = func(*args, **kwargs) return f"<1>{r}</1>" return inner @wrapper2 @wrapper1 def func(a): return a print(func("Hello World!!")) #<2><1>Hello World!!</1></2>
-
def foo1(func): print("d1") def inner1(): print("inner1") return "<i>{}</i>".format(func()) return inner1 def foo2(func): print("d2") def inner2(): print("inner2") return "<b>{}</b>".format(func()) return inner2 @foo1 @foo2 def f1(): return "Hello Andy" # f1 = foo2(f1) ==> print("d2") ==> f1 = inner2 # f1 = foo1(f1) ==> print("d1") ==> f1 = foo1(inner2) ==> inner1 ret = f1() # 调用f1() ==> inner1() ==> <i>inner2()</i> ==> <i><b>inner1()</b></i> ==> <i><b>Hello Andy</b></i> print(ret)
-
-
类装饰器
-
class D(object): def __init__(self, a=None): self.a = a self.mode = "装饰" def __call__(self, *args, **kwargs): if self.mode == "装饰": self.func = args[0] # 默认第一个参数是被装饰的函数 self.mode = "调用" return self # 当self.mode == "调用"时,执行下面的代码(也就是调用使用类装饰的函数时执行) if self.a: print("欢迎来到{}页面。".format(self.a)) else: print("欢迎来到首页。") self.func(*args, **kwargs) @D() def index(name): print("Hello {}.".format(name)) @D("电影") def movie(name): print("Hello {}.".format(name)) if __name__ == '__main__': index('张三') movie('张三')
-
-
装饰类
-
# 定义一个类装饰器 class D(object): def __call__(self, cls): class Inner(cls): # 重写被装饰类的f方法 def f(self): print('Hello 张三.') return Inner @D() class C(object): # 被装饰的类 # 有一个实例方法 def f(self): print("Hello world.") if __name__ == '__main__': c = C() c.f()
-