标签:tool ima user from font 调用 **kwargs 源代码 ret
一. 什么是装饰器?
在说装饰器之前啊. 我们先说一个软件设计的原则: 开闭原则, 又被成为开放封闭原则,你的代码对功能的扩展是开放的你的程序对修改源代码是封闭的. 这样的软件设计思路可以更好的维护和开发。
开放:对功能扩展开放
封闭:对修改代码封闭
谈装饰器前,还要先要明白一件事,Python 中的函数可以像普通变量一样当做参数传递给另外一个函数,例如:
def foo(): print("foo") def bar(func): func() bar(foo)
装饰器的目的: 在不改变原来代码的基础上. 给代码添加新功能。
二. 装饰器形成过程
01. 简单版装饰器:
def func1(): print("欢迎访问主页") # 添加一个登录验证的功能 def wrapper(fn): def inner(): print("请先登录....") fn() return inner func1 = wrapper(func1) func1() # 装饰器的基本雏形 # def wrapper(fn): # fn:目标函数. # def inner(): # ‘‘‘执行函数之前‘‘‘ # fn() # 执行被装饰的函数 # ‘‘‘执行函数之后‘‘‘ # return inner
来看一下,执行流程:
02 . 语法糖
但是如果有多个函数,都需要添加登录验证的功能,每次都得func1 = timer(func1)?这样还是有点麻烦,因为这些函数的函数名可能是不相同,有func1,func2,graph,等等,所以更简单的方法,python给你提供了,那就是语法糖。 @装饰器
def wrapper(fn): def inner(): print("请先登录....") fn() return inner @wrapper # 相当于 => func1 = wrapper(func1) def func1(): print("欢迎访问主页") func1()
有个小问题,就是查看func1函数名和函数注释都变成inner了。
print(func1.__doc__) # 查看函数注释信息 print(func1.__name__) # 查看函数名 # 我是内部函数 # inner 如何解决??? from functools import wraps def wrapper(fn): @wraps(fn) # 改变inner的名字 def inner(): """我是内部函数""" print("请先登录....") fn() return inner @wrapper # 相当于 => func1 = wrapper(func1) def func1(): """ 主页函数 """ print("欢迎访问主页") func1() print(func1.__doc__) print(func1.__name__) # 主页函数 # func1
03. 被装饰函数带参数和返回值
from functools import wraps def wrapper(fn): # fn: 目标函数, 被装饰的函数 @wraps(fn) # 改变inner的名字 def inner(*args,**kwargs): # 万能参数 *args, **kwargs: 接收参数 """我是内部函数""" print("请先登录....") ret = fn(*args,**kwargs) # 调用目标函数. """被装饰函数执行之后""" return ret # 返回结果 return inner @wrapper # 相当于 => func1 = wrapper(func1) def func1(usernamee): """ 主页函数 """ print("欢迎 %s 访问主页" % usernamee) return True @wrapper # 相当于 => func2 = wrapper(func2) def func2(name,age): print("名字:%s 年龄:%s" %(name,age)) return True ret = func1("lishichao") # 实际执行的是inner 参数传给了inner函数 print(ret) func2("lishichao","19")
04. 带有参数的装饰器
给装饰器传参,可以控制装饰器是否使用。
def wrapper(flag): # 装饰器参数 def inner1(fn): # fn: 目标函数, 被装饰的函数 def inner2(*args,**kwargs): # 万能参数 *args, **kwargs: 接收参数 """我是内部函数""" if flag: # 判断传入的参数 True就执行装饰器 False不执行装饰器 print("请先登录....") ret = fn(*args,**kwargs) # 调用目标函数. """""" return ret # 返回结果 return inner2 return inner1 @wrapper(False) # 执行流程: 先执行wrapper(False) 返回装饰器 再和 @ 拼接起来 @inner1 def func1(usernamee): """ 主页函数 """ print("欢迎 %s 访问主页" % usernamee) return True ret = func1("lishichao") # 实际执行的是inner 参数传给了inner函数 print(ret)
执行流程:
05.多个装饰器装饰一个函数
def wrapper1(fn): def inner(*args, **kwargs): print("第一个装饰器开始") ret = fn(*args, **kwargs) print("第一个装饰器结束") return ret return inner def wrapper2(fn): def inner(*args, **kwargs): print("第二个装饰器开始") ret = fn(*args, **kwargs) print("第二个装饰器结束") return ret return inner def wrapper3(fn): def inner(*args, **kwargs): print("第三个装饰器开始") ret = fn(*args, **kwargs) print("第三个装饰器结束") return ret return inner @wrapper1 @wrapper2 @wrapper3 def func(): print("瞬间来三") func() # 执行结果 # 第一个装饰器开始 # 第二个装饰器开始 # 第三个装饰器开始 # 瞬间来三 # 第三个装饰器结束 # 第二个装饰器结束 # 第一个装饰器结束
执行流程:
wrapper1
wrapper2
wrapper3 # 调用函数执行之前
func
wrapper3 # 调用函数执行之后
wrapper2
wrapper1
标签:tool ima user from font 调用 **kwargs 源代码 ret
原文地址:https://www.cnblogs.com/root0/p/10307600.html