最近学习python,其中decorator比较难理解,遂写一篇来总结供后续查阅。

定义一个函数,想在运行时动态的改变函数的功能,又不想改变函数本身的代码,可以使用高阶函数(可以使用函数作为参数)

  装饰器函数可以简化代码,避免每个函数编写重复的代码,也可以用在python web开发中进行登录限制。

1,一般的函数调用-硬编码调用,代码中直接调用函数(直接调用原函数):

  1. def func1():
  2. print ("func1")
  3.  
  4. def func2():
  5. print("before")
  6. func1()
  7. print("after")
  8.  
  9. func2()

输出为:

2,python中可将函数作为参数进行传递(高阶函数):

  1. def func1():
  2. print("func1")
  3.  
  4. def wrapper(func): #装饰器函数
  5. print("before")
  6. func()
  7. print("after")
  8. return func #如果不写return func,函数会自动返回,默认为0
  9.  
  10. func1=wrapper(func1)

调用结果同上。

wrapper函数最后如果不返回func,再次调用func1,则会包以下错误TypeError: 'NoneType' object is not callable:

3,python中的decorator中可以简化上述调用:

  1. def wrapper(func):
  2. print("before")
  3. func()
  4. print("after")
  5. return func
  6.  
  7. @wrapper
  8. def func1():
  9. print("func1")

直接执行,结果同上。

4,这种装饰器执行一次调用一次,我们如果希望显示调用,则可以在函数内部封装一层:

  1. def wrapper(func):
  2. def inner():
  3. print("before")
  4. func()
  5. print("after")
  6. return inner
  7.  
  8. @wrapper
  9. def f():
  10. print("call f")
  11.  
  12. f()#显示调用

5,上面是无参数的装饰器,python中可以实现有参装饰器调用:

  1. def wrapper(func):
  2. def inner(a,b):
  3. print("before wrapper")
  4. func(a,b)
  5. print("after wrapper")
  6. return inner
  7.  
  8. @wrapper
  9. def f(a,b):
  10. print ("call f: a+b=%d"% (a+b) )
  11.  
  12. f(2,3) # f=wrapper(f)=inner

6,有时候,不确定装饰器中参数个数的情况下,就不能使用一般参数、默认参数了,可以使用(*args, **kwargs)来自动适应变参和命名参数:

  1. #coding:utf-8
  2. def wrapper(func):
  3. def inner(*args, **kwargs):
  4. print("before %s"%func.__name__)
  5. result=func(*args,**kwargs)
  6. print("result of %s is %d"%(func.__name__,result))
  7. return inner
  8.  
  9. @wrapper
  10. def f1(a,b):
  11. print("call f1")
  12. return a+b
  13. @wrapper
  14. def f2(a,b,c):
  15. print("call f2")
  16. return a+b+c
  17.  
  18. f1(1,2)
  19. f2(2,3,4)

7,使用functools.wraps在装饰器中包裹传进来的函数,这样就不会丢失传进来的函数的__name__等属性:

  1. from functools import wraps
  2.  
  3. def my_decorator(func):
  4. @wraps(func)
  5. def wrapper(*args, **kwargs):
  6. print('wrapper')
  7. func(*args, **kwargs)
  8.  
  9. return wrapper
  10.  
  11. @my_decorator
  12. def my_fun():
  13. print('test')
  14.  
  15. #exec
  16. my_fun()

8,装饰器在flask中的应用:

  1. #只贴出装饰器核心代码
  2. def login_decorator(func):
  3. @wraps(func)
  4. def wrapper(*args, **kwargs):
  5. if session.get('manage_name'):
  6. return func(*args, **kwargs)
  7. else:
  8. return redirect(url_for('login'))
  9.  
  10. return wrapper
  11.  
  12. @app.route('/post')
  13. @login_decorator
  14. def post():
  15. if request.method == 'GET':
  16. return render_template('post.html')
  17. else:
  18. pass

具体代码可见我的github

参考:简书

浅析python中的装饰器decorator的更多相关文章

  1. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  2. [转] Python中的装饰器(decorator)

    想理解Python的decorator首先要知道在Python中函数也是一个对象,所以你可以 将函数复制给变量 将函数当做参数 返回一个函数 函数在Python中和变量的用法一样也是一等公民,也就是高 ...

  3. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  4. 写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...

  5. 【Python】python中的装饰器——@

    对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...

  6. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  7. python中@property装饰器的使用

    目录 python中@property装饰器的使用 1.引出问题 2.初步改善 3.使用@property 4.解析@property 5.总结 python中@property装饰器的使用 1.引出 ...

  8. python语法32[装饰器decorator](转)

    一 装饰器decorator decorator设计模式允许动态地对现有的对象或函数包装以至于修改现有的职责和行为,简单地讲用来动态地扩展现有的功能.其实也就是其他语言中的AOP的概念,将对象或函数的 ...

  9. python 语法之 装饰器decorator

    装饰器 decorator 或者称为包装器,是对函数的一种包装. 它能使函数的功能得到扩充,而同时不用修改函数本身的代码. 它能够增加函数执行前.执行后的行为,而不需对调用函数的代码做任何改变. 下面 ...

随机推荐

  1. IOS应用内购(一)内购的种类

    Glossary IAP - In App Purchase, 应用内购. 内购种类 consumable - 可消费的,比如游戏中的金币,金币可以购买游戏道具或者装备,这个金币是可以消费的,用完之后 ...

  2. 从yield 到yield from再到python协程

    yield 关键字 def fib(): a, b = 0, 1 while 1: yield b a, b = b, a+b yield 是在:PEP 255 -- Simple Generator ...

  3. MySQL字符集详解

    Reference:  https://www.cnblogs.com/wcwen1990/p/6917109.html MySQL字符集详解   一.字符集和校验规则 字符集是一套符合和编码,校验规 ...

  4. vim常用技巧

    # vim常用技巧 ## 行操作------------------------------ 行首 0- 行尾 $- 第一个非空字符 ^ ## 列编辑模式----------------------- ...

  5. 科普知识普及 - 桥接VS中继

    首先要说明一个很多人理解的误区,中继比桥接好用,真的是这么回事么? 答案是否定的. 我们在说桥接和中继的时候我们要先了解,桥接和中继的工作原理.还有一个问题,估计很多人都想不明白:为什么中继搜到的信号 ...

  6. 【GMT43智能液晶模块】例程十一:通用定时器实验——定时点亮LED

    实验原理: 通过STM32的一个GPIO口来驱动LED灯,设定GPIO为推挽输出模式,采用灌电流的方式与LED连接, 输出高电平LED灭,输出低电平LED亮,通过通用定时器TIM3实现500ms定时, ...

  7. linux的挂载的问题,重启后就挂载就没有了

    我用fdisk命令,分一个/dev/sda6出来,然后用mkfs格式化为ext3,然后挂载到根目录下的PPP文件夹中,挂载是成功了,但是用reboot和shutdown重启或关机后挂载就没有了 要修改 ...

  8. 【算法】八皇后问题 Python实现

    [八皇后问题] 问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子.皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子.在一个棋盘上如果要放八个皇后,使得她们互 ...

  9. 34对MyBatis的博客的整理心得

    对本博客的mybatis重新读一下,做一个整理.如下: 1:为什么会有mybatis,因为原生的jdbc方式有很大问题: (1)数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭 ...

  10. 【原创】SAP/Oracle 集团企业海外全球化实施注意事项: 一带一路本地化 (持续更新)

    ABC集团SAP的系统平台已经扩展到全球一百来个国家和地区,SAP系统平台的全球实施项目中, 当时是需要支持当地的业务和法律法规的合规要求. 当时客户也是缺乏当地的资源以及对当地法律法规和业务实践的了 ...