这一节了解了一些装饰器的简单使用。
首先来看一个预备知识,把一个函数当做参数,传入另外一个函数
比如说我传递outer(f1),我传入的是f1的内存地址,a=func()其实执行了f1()这个函数,并把返回值赋给了a,因此当我打印print(a),他会输出hee
>>> def outer(func): print(func) a=func() print(a) def f1(): print("aaa") return "hee" outer(f1) ------------ <function f1 at 0x0000023D3FF3D510> aaa hee
装饰器(decorator)就是利用可以把函数当做传递这一点,他可以统一给一些函数添加一些“修饰”功能,但是又不会去破坏原有的代码。装饰器本身也是一个函数,其他函数调用他的时候,在其他函数前面 @ +装饰器名的格式就行了
这个格式执行了2个功能:
1. 自动执行装饰器函数并且将其下面的函数名f1当作参数传递
2. 将装饰器函数的返回值,重复赋值给 f1
简单的说就是这样
f1=decortor(f1)
把上面的例子稍微修改成装饰器,如下所示,结果是一样的
def outer(func): def innner(*args,**kwargs): print(func) a=func(*args,**kwargs) print(a) return a return innner @outer def f1(): print("aaa") return "hee" f1()
再看另外一个复杂一些的例子:
我定义了3个函数f1,f2,f3,他们有不同的参数,我需要每个函数在现在的结果前面添加一个‘before‘,结果后面添加一个‘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(arg) return "F1" @outer def f2(a1, a2): print("F2") @outer def f3(): print("F3") f1("hhh") f2("bbb",444) f3()
结果如下:
before hhh after before F2 after before F3 after
注意要点:
- 当使用装饰器outer的时候,他传递参数 outer(f1),这里传递的是f1的地址;r=func()其实执行的就是f1(),然后把返回值赋给了r,这里的目的是为了保证inner返回的结果和f1返回的结果一样;最后再把装饰过的inner函数地址赋给f1,实现装饰的效果;
- 记得前面的万能参数 f(*args,**kwargs),可以接受任意的参数
例2:装饰器一个广泛使用的场景是登录验证;很多功能必须判断登录之后才能使用。
下面的例子装饰器通过一个全局变量LOGIN_USER来判断是否已经登录。
#!/usr/bin/env python # -*- coding:utf-8 -*- LOGIN_USER = {"is_login": False } def outer(func): def inner(*args, **kwargs): if LOGIN_USER[‘is_login‘]: r = func() return r else: print("请登录") return inner def outer1(func): def inner(*args, **kwargs): if LOGIN_USER[‘is_login‘] and LOGIN_USER[‘user_type‘] == 2: r = func() return r else: print("请登录,或者权限不够") return inner @outer1 def order(): print("欢迎%s登录" % LOGIN_USER[‘current_user‘]) @outer def changepwd(): print("欢迎%s登录" % LOGIN_USER[‘current_user‘]) @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,后台管理;2,登录") if inp == ‘1‘: manager() elif inp == ‘2‘: username = input("请输入用户名") pwd = input("请输入密码") login(username, pwd) main()
例3.
如果有多个装饰器,我可以嵌套的使用,因为一层的装饰器之后其实也是一个函数,那他自然可以再继续被装饰。
比如说,注意他的调用顺序是从下往上的
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32 >>> def outer(func): def innner(*args,**kwargs): print(func) a=func(*args,**kwargs) print("装饰1") return a return innner def outer2(func): def inner(*args,**kwargs): print(func) a=func(*args,**kwargs) print("装饰2") return a return inner @outer2 @outer def f1(): print("原函数") return "hee" f1() <function outer.<locals>.innner at 0x000001FF89A6D620> <function f1 at 0x000001FF89A6D598> 原函数 装饰1 装饰2
时间: 2024-10-12 17:01:41