Python 学习笔记 - 装饰器

这一节了解了一些装饰器的简单使用。


首先来看一个预备知识,把一个函数当做参数,传入另外一个函数

比如说我传递outer(f1),我传入的是f1的内存地址,a=func()其实执行了f1()这个函数,并把返回值赋给了a,因此当我打印print(a),他会输出hee

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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)


把上面的例子稍微修改成装饰器,如下所示,结果是一样的

1
2
3
4
5
6
7
8
9
10
11
12
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’


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def outer(func):
    def inner(*args, **kwargs):
        print('before')
        = 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()


结果如下:

1
2
3
4
5
6
7
8
9
before
hhh
after
before
F2
after
before
F3
after


注意要点:

  1. 当使用装饰器outer的时候,他传递参数 outer(f1),这里传递的是f1的地址;r=func()其实执行的就是f1(),然后把返回值赋给了r,这里的目的是为了保证inner返回的结果和f1返回的结果一样;最后再把装饰过的inner函数地址赋给f1,实现装饰的效果;

  2. 记得前面的万能参数 f(*args,**kwargs),可以接受任意的参数


例2:装饰器一个广泛使用的场景是登录验证;很多功能必须判断登录之后才能使用。

下面的例子装饰器通过一个全局变量LOGIN_USER来判断是否已经登录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
LOGIN_USER = {"is_login"False }
def outer(func):
    def inner(*args, **kwargs):
        if LOGIN_USER['is_login']:
            = 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:
            = 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.

如果有多个装饰器,我可以嵌套的使用,因为一层的装饰器之后其实也是一个函数,那他自然可以再继续被装饰。 


比如说,注意他的调用顺序是从下往上的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 201622: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


Python 学习笔记 - 装饰器






本文转自 beanxyz 51CTO博客,原文链接:http://blog.51cto.com/beanxyz/1844747,如需转载请自行联系原作者

上一篇:Python装饰器学习(九步入门)


下一篇:Operations Manager 2007 R2系列之报表服务安装