python-装饰器
一、函数基础
1.函数基础
定义函数,未调用,函数内部代码块不会被执行
函数名即不带括号,代指函数
函数名+(),即f1() ,表示执行f1()函数
'''例1''' def foo(): print('foo') foo #表示是函数,函数名指函数所在内存中的位置,如果带后面括号表示执行函数 foo() #表示执行函数 '''例2:''' def foo(): print('foo') foo = lambda x=1: x+1 foo() #执行下面的lambda表达式,而不再是原来的foo函数,因为函数foo被重新定义
以上code说明:从成晨博客里看到的。引用一下。
1.在def 函数时,以顺序执行,如果相同的函数名,会被最后函数覆盖以前的
2.如果直接func名而没有后面的圆括号的话,只指向函数在内存中的位置
3.lambda表达式会自动return结果,而def需要定义return值
2.把函数作为参数传递
def f1(): print('123') def f2(xx): xx() f2(f1)
输出结果:
12
将函数名称f1作为参数,传递给f2()函数,此时f1== xx ,xx() == f1, 函数f2()内执行xx() 实际上是执行函数f1()
二、装饰器
1.
def outer(func): return "132" @outer def f1(): print("F1")
@ + 函数名
功能:
1.自动执行outer函数并且将其下面的函数名f1当作参数传递
2.将outer函数的返回值,重新赋值给f1, 相当于把函数f1重写了,即 f1 = "123"
下面证明一下上面的结论:
def outer(func): def inner(): print('before') return inner @outer def f1(): print("F1") f1()
输出结果:
before
函数f1() 被装饰器装饰之后,如果执行f1() 那么不再是执行print("F1")了,而是执行的是inner()函数。因为装饰器outer返回了inner,即把inner整个函数返回给了f1,此时也就是把f1函数重写为inner函数了,也就是把原来的f1()函数用inner()函数给覆盖掉了。。所以执行的结果是 : before 而不是 F1
2.深入理解装饰器
def outer(func): def inner(): print('before') func() print('after') return inner @outer def f1(): print("F1") f1()
输出结果:
before
F1
after
@ + 函数名
功能:
1.自动自行outer函数并且将其下面的函数名f1当作参数传递,即f1 = func 如果执行 func() 那么执行的就是f1()函数,即print("F1")
2.将outer函数的返回值,重新赋值给f1,即把函数f1重写了。即 f1函数变成了inner函数。
3.一个函数f1一旦被装饰器装饰之后,那么这个函数f1将会被重新赋值,赋值为装饰器的内层函数,即:,如果执行f1()函数的时候,实际上是执行函数,又因为inner()函数里面的 func ==原来的 f1 即func() 为print("F1"),所以执行func()函数,就是执行原来的f1()函数,即执行print("F1")
三、装饰器python解释的步骤:
装饰器执行之前首先是pyhton解释器解释代码:
步骤如下:
四、装饰器执行步骤
五、装饰器返回值:
def outer(func): def inner(): print('before') r = func() print('after') return r return inner @outer def f1(): print("F1") return "好好学习,天天向上" ret = f1() print("返回值:" ,ret)
输出结果:
before
F1
after
返回值: 好好学习,天天向上
六、带参数的装饰器:
def outer(func): def inner(*args,**kwargs): print('before') r = func(*args,**kwargs) print('after') return r return inner @outer def f1(arg): print("f1函数的参数:%s" %arg) return "好好学习" @outer def f2(a1,a2): print("f2函数的第一个参数:%s, 第二个参数:%s" %(a1,a2)) return "天天向上" ret1 = f1("F1") print("f1函数返回值:" ,ret1) ret2 = f2("a","b") print("f1函数返回值:" ,ret2)
输出结果:
before
f1函数的参数:F1
after
f1函数返回值: 好好学习
before
f2函数的第一个参数:a, 第二个参数:b
after
f1函数返回值: 天天向上
七、装饰器练习:
#!/usr/bin/env python # -*- coding:utf-8 -*- LOGIN_USER = {"is_login":False} def outer(func): def inner(*args,**kwargs): if LOGIN_USER['is_login'] == True: r = func() return r else: print("请登录") pass return inner @outer def manager(): print("欢迎%s登录" % LOGIN_USER['current_user']) def login(user,pwd): if user == "alex" and pwd == "123": LOGIN_USER['is_login'] = True LOGIN_USER['current_user'] = user manager() def main(): while True: inp = input("1,后台管理:\n2,登录:") if inp == '1': manager() elif inp == '2': username = input("请输入用户名:") pwd = input("请输入密码:") login(username,pwd) main()
输出结果:
1,后台管理:
2,登录:1
请登录
1,后台管理:
2,登录:2
请输入用户名:alex
请输入密码:123
欢迎alex登录
1,后台管理:
2,登录:
八、多层装饰器:
首先我们看一个例子:模拟登录,普通用户权限,管理员权限
#!/usr/bin/env python # -*- coding:utf-8 -*- # Auther: pangguoping USER_INFO = {} def check_login(func): def inner(*args,**kwargs): if USER_INFO.get('is_login',None): ret = func(*args,**kwargs) return ret else: print('请登录') return inner def check_admin(func): def inner(*args,**kwargs): if USER_INFO.get('is_login',None): if USER_INFO.get('user_type',None) == 2: ret = func(*args,**kwargs) return ret else: print('无权限查看') else: print('请登录') return inner @check_login @check_admin def index(): print('Index') @check_login def home(): """ 普通用户的功能 :return: """ print('home') def login(): user = input('请输入用户名:') if user == 'admin': USER_INFO['is_login'] = True USER_INFO['user_type'] = 2 else: USER_INFO['is_login'] = True USER_INFO['user_type'] = 1 #主函数 def main(): while True: inp = input('1,登录;2,查看信息;3,超级管理员管理\n >>>') if inp == '1': login() elif inp == '2': home() elif inp == '3': index() else: pass main()
输入结果:
从结果中可以看出,已经满足需求
这个例子有明显缺点:
装饰器的功能应该单一,不应该混合
check_admin 即判断登录,又判断权限。
#!/usr/bin/env python # -*- coding:utf-8 -*- # Auther: pangguoping USER_INFO = {} def check_login(func): def inner(*args,**kwargs): if USER_INFO.get('is_login',None): ret = func(*args,**kwargs) return ret else: print('请登录') return inner def check_admin(func): def inner(*args,**kwargs): if USER_INFO.get('user_type',None) == 2: ret = func(*args,**kwargs) return ret else: print('无权限查看') return inner @check_login @check_admin def index(): print('Index') @check_login def home(): """ 普通用户的功能 :return: """ print('home') def login(): user = input('请输入用户名:') if user == 'admin': USER_INFO['is_login'] = True USER_INFO['user_type'] = 2 else: USER_INFO['is_login'] = True USER_INFO['user_type'] = 1 #主函数 def main(): while True: inp = input('1,登录;2,查看信息;3,超级管理员管理\n >>>') if inp == '1': login() elif inp == '2': home() elif inp == '3': index() else: pass main()
优化后的代码我们使用了多层装饰器
九、多层装饰器 python解释器解释过程:
解释过程:从下往上
十、多层装饰器执行过程: