本篇尽可能的用简单易懂的方法解释装饰器的用法,所以不会出现高深的语言,同样,也可能不够严谨。
def a():
print("Hello")
b = a #将函数a()的地址赋值给b
b() #输出b(),执行a地址
#输出:Hello
a()
,b()
代表一个函数本身a
,代表a()
函数的地址def a(): # 定义一个函数a()
x = 1
y = 2
def b(): # 在函数a()中定义一个函数b()
print(x + y) # 函数b()的内容
return b # 将函数b()的地址返回给函数a(),相当于a() = 函数b()的地址
a()() # 这时a()代表b的地址,a()()=b(),怎么写可以执行但相当不规范,只为理解方便
#输出:3
将上面函数规范化
def a(): # 定义一个函数a()
x = 1
y = 2
def b(): # 在函数a()中定义一个函数b()
print(x + y) # 函数b()的内容
return b # 将函数b()的地址返回给函数a(),相当于a() = 函数b()的地址
c = a() # 此时将b的地址赋给c
c() # 执行c(),也就是执行b()
# 输出:3
以规范化后的函数为例
函数的执行顺序为
a() #执行a()
x=1 #将1赋予x
y=2 #将2赋予y
def b() #定义一个函数b()
return b #返回b地址,a()=b
c=b #执行c=a(),因为a()=b,所以c=b
c() #c()=b(),相当于执行b()
print(x+y)
简单说就是在不改变函数本身的情况下,附加功能
例
#现有4份文件,任何人都可以查阅
def screat0():
print("机密0")
def screat1():
print("机密1")
def screat2():
print("机密2")
def screat3():
print("机密3")
num = input("请输入编号")
if num == "0":
screat0()
elif num == "1":
screat1()
elif num == "2":
screat2()
elif num == "3":
screat3()
#有一天老板觉得文件1,和文件2只能对特定的人开放
#于是要求增加验证
#必须在不改变现代码的情况下增加功能
#这就是装饰器的意义
#要用到上面闭包和给函数命名
# 闭包****************************************************************************************
databass = {‘name‘: ‘aot‘, ‘password‘: ‘123‘}
def login(func):
def inner():
name = input("name:")
password = input("password:")
if name == databass[‘name‘] and password == databass[‘password‘]:
func()
else:
print("无访问权限")
return inner
#闭包*******************************************************************************************
def screat0():
print("机密0")
def screat1():
print("机密1")
def screat2():
print("机密2")
def screat3():
print("机密3")
#-------------------------------------------------------------------------------------------------
screat1 = login(screat1) #将screat1地址传入login(func),函数调用不发生改变,见上文函数的命名
screat2 = login(screat2) #这两行代码可以用语法糖表示,见下文
#------------------------------------------------------------------------------------------------
num = input("请输入编号")
if num == "0":
screat0()
elif num == "1":
screat1()
elif num == "2":
screat2()
elif num == "3":
screat3()
#语法糖
screat1 = login(screat1) # 可以表示为@login放在对应的语句前,这句是放在 def screat1():前
#如
@login
def screat1(): # 这时不需要再写 screat1 = login(screat1)
#同理,也可以装饰screat0,1,2,3,只需在相应定义前增加即可,极大的方便了代码的修改
#最终形态
# 闭包****************************************************************************************
databass = {‘name‘: ‘aot‘, ‘password‘: ‘123‘}
def login(func):
def inner():
name = input("name:")
password = input("password:")
if name == databass[‘name‘] and password == databass[‘password‘]:
func()
else:
print("无访问权限")
return inner
#闭包*******************************************************************************************
def screat0():
print("机密0")
@login
def screat1():
print("机密1")
@login
def screat2():
print("机密2")
def screat3():
print("机密3")
num = input("请输入编号")
if num == "0":
screat0()
elif num == "1":
screat1()
elif num == "2":
screat2()
elif num == "3":
screat3()
修饰器是可以带参数的
如果原函数有参数,如
@login
def screat2(level):
if(level<=5):
print("机密2.1")
if(level>5):
print("机密2.2")
这时在调用原login(func)
会报错,所以需要稍加修改
#原代码
def inner():
func()
#修改为
def inner(*args,**swargs):
func(*args,**swargs)
*args
表示不定长传参,且不需要知道参数名称,以元组方式传入
**swargs
也表示不定长传参,但需要知道参数名称,以字典方式传入
#例
def a(*a):
print(a)
a(1,2,12,3)
#输出:(1, 2, 12, 3)
def b(**b):
print(b)
b(a=1,b=2,c=3)
#输出:{‘a‘: 1, ‘b‘: 2, ‘c‘: 3}
原文:https://www.cnblogs.com/aotaot/p/14485395.html