python装饰器简析
python装饰器
本篇尽可能的用简单易懂的方法解释装饰器的用法,所以不会出现高深的语言,同样,也可能不够严谨。
1 一些基本方法
1 函数的命名
def a():
print("Hello")
b = a #将函数a()的地址赋值给b
b() #输出b(),执行a地址
#输出:Hello
- 当函数为有括号的形式时,如
a()
,b()
代表一个函数本身 - 当函数为没有括号形式时,如
a
,代表a()
函数的地址
2 闭包
- 定义一个函数中包含了另一个定义函数
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)
2 装饰器
1 使用意义
-
简单说就是在不改变函数本身的情况下,附加功能
-
#现有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()
- 如上,在仅仅增加了一段代码,并且不改变原有代码的情况下,便完成了验证这一附加功能
- 一般情况下,代码不会只有这些,不改变原有代码增加功能是极其重要的
2 补充
修饰器是可以带参数的
如果原函数有参数,如
@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}