文档章节

Python 学习 - 装饰器

乐搏学院
 乐搏学院
发布于 2017/03/31 09:51
字数 1118
阅读 7
收藏 0

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

 

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

比如说我传递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

 

wKioL1fGfAvwfoMgAAB_lmOBgy0357.png

 

 

登录乐搏学院官网http://www.learnbo.com/

或关注我们的官方微博微信,还有更多惊喜哦~

 

本文出自 “麻婆豆腐” 博客,请务必保留此出处http://beanxyz.blog.51cto.com/5570417/1844747

© 著作权归作者所有

乐搏学院
粉丝 9
博文 526
码字总数 707467
作品 0
丰台
程序员
私信 提问
python 装饰器及标准库functools中的wraps

最近在看 flask的视图装饰器 时,忽然想起预(复)习一下python的装饰器. 这里有一篇比较好的讲解装饰器的书写的 Python装饰器学习(九步入门) . 这里不单独记录装饰器的书写格式了,重点是工作...

L很失败L
2015/08/20
0
0
Python的三大神器,你知道是哪三大吗?史上最详细的入门教程!

Python的三大神器:装饰器.迭代器与生成器!这就是Python的三大神器,好了废话不多说。直接来上干货吧! 生成器 仅仅拥有生成某种东西的能力,如果不用next方法是获取不到值得。 创建一个生成...

q1622479435
2018/06/08
0
0
Python装饰器AOP 不定长参数 鸭子类型 重载(三)

1 可变长参数与关键字参数 代表任意长度可变参数 代表关键字参数 用和只是为了方便并没有强制使用它们. 缺省参数即是调用该函数时,缺省参数的值若未被传入,则传入默认预设的值。 注意 : 须...

善良小郎君
2018/06/17
0
0
设计模式之:理解 Python 中的装饰器

1、问题 文章先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: @makebold @makeitalic def say(): return "Hello" 打印出如下的输出: <b><i>Hello<i></b> 你会怎么做?最后给出......

大数据之路
2013/07/22
0
0
Python知识点:理解和使用装饰器 @decorator

我在我的个人博客“猿人学网站”和公众号“猿人学Python”上写Python教程,有兴趣的可以关注公众号和网站。 Python的装饰器(decorator)是一个很棒的机制,也是熟练运用Python的必杀技之一。...

呆木木人儿
03/12
0
4

没有更多内容

加载失败,请刷新页面

加载更多

Android双向绑定原理简述

Android双向绑定原理简述 双向绑定涉及两个部分,即将业务状态的变化传递给UI,以及将用户输入信息传递给业务模型。 首先我们来看业务状态是如何传递给UI的。开启dataBinding后,编译器为布局...

tommwq
今天
2
0
Spring系列教程八: Spring实现事务的两种方式

一、 Spring事务概念: 事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。...

我叫小糖主
今天
6
0
CentOS 的基本使用

1. 使用 sudo 命令, 可以以 root 身份执行命令, 必须要在 /etc/sudoers 中定义普通用户 2. 设置 阿里云 yum 镜像, 参考 https://opsx.alibaba.com/mirror # 备份mv /etc/yum.repos.d/CentO...

北漂的我
昨天
3
0
Proxmox VE技巧 移除PVE “没有有效订阅” 的弹窗提示

登陆的时候提示没有有效的订阅You do not have a valid subscription for this server. Please visit www.proxmox.com to get a list of available options. 用的是免费版的,所以每次都提示......

以谁为师
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部