今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找。虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python 2.7在用法上差不多。

  现在某个视频公司有一段代码,,代码的主要功能就是看电影。

 def watchfilm():
     print('You are watching film now....')

 watchfil()

  运行之后输出:

You are watching film now....

  现在要求来了,老板提出看电影之前必须要进行登录。

  此时小A想到开放封闭原则,原有的代码不能更改,但是需要进行扩展。于是小A有了以下想法:

    1.可以定义一个登录函数,将看电影函数的内存地址作为参数传入

    2.运行登录函数,将原先看电影函数的内存地址返回

    3.使用新的变量存储原先看电影函数的内存地址,将新变量和原先看电影函数的函数名定义为相同的名字

    4.运行新变量的时候就就会找到内存地址,运行原先看电影函数的代码

  基于以上想法,小A写出了如下代码:

 def login(func):
     print('username&password verification....')
     return func

 def watchfilm():
     print('You are watching film now....')

 watchfilm=login(watchfilm)
 watchfilm()

  运行之后输出:

username&password verification....
You are watching film now....

  老板看后很满意,然后说:不行!

  因为看电影函数是基础平台,而调用是业务部门再进行调用,如果这样修改,就需要业务部门修改大量的代码。

  方案被老板否定了,但是活还得接着干啊。小A一筹莫展。

  某一天,小A遇见了小B,向小B倾诉了自己的苦恼,小B说道:“使用python的装饰器啊。”

  小B解释到,装饰器实现的东西和你做的东西是一样的,不过装饰器使用语法糖@来装饰函数。装饰器执行时,把被装饰函数的内存作为参数传给装饰器,同时执行装饰器函数,最后返回新定义的函数名,和被装饰的函数名相同,只不过内存地址可不一定就是被装饰的函数的内存地址了。再执行被装饰函数时,其实执行的是新的函数。

  小A一听,有门,来了精神。经过了一段时间的研究,于是有了一下代码:

 def login(func):
     print('username&password verification....')
     return func

 @login
 def watchfilm():
     print('You are watching film now....')

 watchfilm()

  运行之后输出:

username&password verification....
You are watching film now....

  能够满足要求,小A顿时兴奋起来。小A马上又测试了几次,没有问题。就在小A想着可以交差的时候,他发现了一个问题。

 def login(func):
     print('username&password verification....')
     return func

 @login
 def watchfilm():
     print('You are watching film now....')

 print('other operation.....')
 watchfilm()

  运行之后输出:

username&password verification....
other operation.....
You are watching film now...

  明明没有调用函数,为什么会有输出呢?登录程序应该是在其它操作之后,看电影之前才对啊?小A看了看程序,马上明白了问题所在,因为程序只要启动,就会执行装饰器函数,执行装饰器函数就会执行登录程序,导致了现在这种情况。

  这样不行啊,怎么才能解决呢?

  忽然小A灵机一动,想到了一个办法,于是有了代码2.0

 def login(func):
     def inner():
         print('username&password verification....')
         func()
     return inner

 @login
 def watchfilm():
     print('You are watching film now....')

 print('other operation.....')
 watchfilm()

  运行之后输出:

other operation.....
username&password verification....
You are watching film now....

  完美解决了问题,小A长出了一口气。

  第二天,小A赶紧找到老板,说出了自己的想法。

  老板满意的点点头,对小A说道:你做的很好,但是现在咱们需求变了,目前还想在看电影之前放一段广告而且看完电影之后推荐几部电视节目,你看咱们能不能实现一下。

  小A虎躯一震,擦了擦头上的汗,点头应承了下来。但是小A此时也犯了难,如何使用装饰器进行实现呢?小A想到了小B,于是赶紧去请教小B,一顿酒肉计下来,小B跟小A说,你想想装饰器的原理,如果我在有一层def呢?小A一拍大腿,对啊,我怎么没有想到。

  小A赶紧进行设计,于是有了代码3.0

 def advert():
     print('advertisement time...')

 def recommend():
     print('recommend TV show...')

 def login(adv,rec):
     def inner(func):
         def inner2():
             print('username&password verification....')
             adv()
             func()
             rec()
         return inner2
     return inner

 @login(advert,recommend)
 def watchfilm():
     print('You are watching film now....')

 print('other operation.....')
 watchfilm()

  运行之后输出:

other operation.....
username&password verification....
advertisement time...
You are watching film now....
recommend TV show...

  装饰器带参数之后会首先运行带参数的函数,本例中是login(advert,recommend),函数返回inner函数的内存地址,之后装饰器开始执行,就会变成执行@inner装饰器,之后因为之前两个函数已经传入过,所以再调用函数的时候就能显示输出了。

  小A很高兴,这次真是又快又好的完成了任务,于是他唯恐事件有变,赶在老板下班之前向老板进行了汇报。

  老板听了小A的汇报相当满意,高声称赞小A,忽然话锋一转,说道:但是小A啊,咱们的需求现在。。。。。。。

  (未完待续)

python 3.x 的装饰器笔记的更多相关文章

  1. python函数与方法装饰器

    之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...

  2. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  3. python设计模式之内置装饰器使用(四)

    前言 python内部有许多内建装饰器,它们都有特别的功能,下面对其归纳一下. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python设计模式之装饰 ...

  4. python 中多个装饰器的执行顺序

    python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...

  5. Python函数编程——闭包和装饰器

    Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...

  6. python基础-内置装饰器classmethod和staticmethod

    面向对象编程之classmethod和staticmethod classmethod 和 staticmethod都是python内置的装饰器 classmethod 的作用:给在类内部定义的方法装 ...

  7. Python 入门之 Python三大器 之 装饰器

    Python 入门之 Python三大器 之 装饰器 1.开放封闭原则: (1)代码扩展进行开放 ​ 任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改.所以我们必须允许代 ...

  8. python中面向对象之装饰器

    python面向对象内置装饰器property,staticmethod,classmethod的使用 @property 装饰器作用及使用 作用:面向对象中的方法伪装成属性 使用如下: class ...

  9. 《Python cookbook》 “定义一个属性可由用户修改的装饰器” 笔记

    看<Python cookbook>的时候,第9.5部分,"定义一个属性可由用户修改的装饰器",有个装饰器理解起来花了一些时间,做个笔记免得二刷这本书的时候忘了 完整代 ...

随机推荐

  1. python 之sqlalchemy many to one

    通过查询多个父亲,对应一个儿子 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @author: zengchuny ...

  2. scala 打印一个乘法口诀表 (&lt;&lt;scala 编程&gt;&gt; P87)

    (for(i <- 1 to 9;j <- 1 to i; s = s"$j*$i=${i*j}\t") yield {if(j==1) s"$s\n&quo ...

  3. animate.css

    这是个css3动画框架,现在很流行,在小动画效果有很多,使用的方式 <div class="animated bounce"></div> /*只要修改bo ...

  4. UVa 1642 (综合) Magical GCD

    题意: 给出一个数列,求一个连续的子序列,使得MGCD(i, j) =  该子序列的长度(j-i+1) × 子序列的gcd 最大,并输出这个最大值. 分析: 感觉可能要用优先队列,但貌似也用不上. 但 ...

  5. android的tabhost+RadioGroup+PopupWindow

    根据网上的代码稍作修改了下,放着记录学习. 效果图如下: 主代码如下: package com.andyidea.tabdemo; import android.app.TabActivity; im ...

  6. SpringMVC4+thymeleaf3的一个简单实例(篇三:页面参数获取)

    本篇将通过示例介绍页面参数是如何传递到后台的.我们继续沿用之前搭好的程序结构,如果你不知道,请参照前两篇.为方便跳转页面,我们在首页以及zoolist.html页面都加上彼此地址的链接:首页: zoo ...

  7. bzoj2741【FOTILE模拟赛】L

    http://www.lydsy.com/JudgeOnline/problem.php?id=2741 分块或可持久化trie 可以先看看这个:高斯消元解XOR方程组 分块做法: 我们先求出前i个数 ...

  8. [android] 内容提供者实现

    [android] 内容提供者实现 上一节的主机名类似网络上的域名,协议是content://,可以定义一下规则 content://主机名/insert 添加操作 content://主机名/del ...

  9. 使用docker搭建gitlab版本控制系统

    1. GitLab 简介 GitLab 是一款基于 git 的开源代码仓库系统   GitLab 与著名的 GitHub 最大的区别就是:  允许我们搭建自己的 git 代码私有仓库,非常方便   2 ...

  10. 基于LNMP(fastcgi协议)环境部署、原理介绍以及fastcgi_cache配置以及upstream模块负载均衡讲解

    ngx_http_proxy_module只能反向代理后端使用HTTP协议的主机.而ngx_http_fastcgi_module只能反向代理后端使用FPM或者使用FastCGI协议的客户端. 一.部 ...