python之路第五篇之装饰器:(进阶篇)
装饰器:
学前必备知识:
def f1():
print "f1"
f1() #表示函数执行
f1 #表示函数,指向内存地址
f1 = lambda x: x + 1
f1() # 执行这个lambda表达式,而不再是原来的f1函数,因为函数f1被重新定义了
装饰器代码剖析:
假如有这么一个需求,公司临时规定将某块业务加上访问权限,因为代码太多,又不想改变原有已经封装好的
代码,于是乎,基础平台的同志们想出了这么一个解决办法:利用装饰器解决
那么什么是装饰器?这个问题先留着,直接看代码:(代码剖析:)
def auth_login(func): # func = f1 ,func() = f1()
def inner():
print "welcome to login ..." #验证的内容加在这里
func() # func() = f1() #相当于执行f1()
reture inner # 返回 inner函数体
def f1():
#print "welcome to login ..." #需求是在这块加上验证(那么怎么实现?)
print "f1..."
result = auth_login(f1) #等于inner函数(包括它下面那一段代码)
f1 = result
f1() #函数执行
上面代码梳理:
基础平台代码:(在业务平台不需要修改调用方式的时候,直接调用基础平台这块代码)
bash.py #代码名称
#!/usr/bin/env python
#-*- coding:utf-8 -*-
def auth_login(func):
def inner():
print "auth user ..." # 认证模块
func()
return inner
@auth_login #@auth_login 是python默认封装好的一种方法,#相当于 result=auth_login(f1) # f1() = result()#(和上面的执行效果一样)
def f1():
print "I'm f1"
def f2():
print "I'm f2"
f1() #函数执行,这个是属于业务部门来调用执行的,单独拿出来调用,如下:
业务部门调用bash.py函数下的某个方法:
yw.py #业务程序名称
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import bash
bash.f1() #调用bash.f1 方法
执行业务程序 yw.py 结果如下:
auth user ...
I'm f1
显然上面已经达到我们的需求了,@auth_login 就是我们的装饰器,上面的列子就是对它使用的
其中一种方式;
那么问题来了:如果平台需要再调用基础平台的 f2 方法,并且还是带参数的”传入参数“的方法去调用,
显然上面的程序已经不再满足需求了;
那么我们可以不可以这么做?就是我们再另外定义另外一个装饰器,而这个装饰器是可以接受参数的;
代码如下:
bash.py #代码名称
def auth_login(func):
def inner():
print "auth user ..."
func()
return inner
def auth_arg_login(func): #这块代码是新加入的,传入参数
def inner(arg): #参数
print "auth user arg ..."
func(arg)
return inner
@auth_login
def f1():
print "I'm f1"
@auth_arg_login # 调用新装饰器
def f2(arg): #参数
print "I'm f2",arg
业务部门再次调用bash.py函数下的方法:
yw.py #业务程序名称
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import bash
base.f1()
base.f2(”new programs") # 传入参数
执行业务程序 yw.py 结果如下:
auth user ...
I'm f1
auth user arg ... #这块输出
I'm f2 new programs #这块输出
这个时候,需求又变了,业务部门说,我们需要传递2个参数,于是乎,基础平台啪啪啪,又写了几个方法,
又实现了,过了一段时间,业务平台的同志来的时候说了一句话,兄弟,不好意思,我还需要传递几个参数,
这个时候基础平台的同志发现自己快疯了,CTO 老大看不下去了,这个时候,他告诉基础平台这么一个方法,
也就是下面的代码(传递动态参数)
bash.py #代码名称
#!/usr/bin/env python
#-*- coding:utf-8 -*-
def auth_login(func):
def inner(*arg,**kwagrs): #动态参数
print "auth user ..." #认证模块
func(*arg,**kwargs) #动态参数
return inner
@auth_login #在函数上面加上这么一句 @auth_login: 这个是python默认封装好的一种方法,
#相当于 result = auth_login(f1) # f1() = result()
#(和上面的执行效果一样)
def f1(arg):
print "I'm f1",arg
业务部门调用bash.py函数下的某个方法:
yw.py #业务程序名称
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import bash
bash.f1('test') #调用bash.f1 方法
执行业务程序 yw.py 结果如下:
auth user ...
I'm f1 test # 执行结果
装饰器总结:
1.装饰器是一个函数
2. 执行auth_login 函数,被装饰的函数作为参数auth_login(f1) auth_login 函数的返回值,
赋值给被装饰的函数的函数名
@auth_login
def f1():
pass
3.动态参数,可以装饰含有n个参数的函数
4.函数返回值
5.多装饰器
6.至少3层,3层的如何使用?
@auth_login
1.执行auth_login函数
2.将auth_login函数的返回值给赋值给被装饰器的函数的函数名
@auth_login(arg)
1.执行auth_login函数,得到返回值,result
2.创建装饰器,@ + result结合:@result
3...
1).执行result 函数
2).将result函数的返回值给被装饰器的函数的函数名
装饰器返回值(return):
获取主机列表:
bash.py #代码名称
def auth_login(func):
def inner(*arg,**kwargs)
print "welcome to login..."
temp = func(*arg,**kwargs)
print "login after..."
return temp
return inner
@auth_login
def fetch_server_list():
server_list = ['server1','server2','server3']
return server_list
执行业务程序 yw.py 结果如下:
import base
server_list = base.fetch_server_list('test')
print server_list
程序执行结果:
welcome to login...
login after...
['server1', 'server2', 'server3']
上面的列子说了这么多,好,现在我们来做一个用户登陆验证:
def login(): # 这里定义一个login 函数
name = "Allen" # 如果这里是“Allen“,则下面的函数调用,验证成功,否则失败
if name == "Allen":
return True
else:
return False
def auth_login(func):
def inner(*arg,**kwargs):
is_login = login() #这里加入一个验证判断
if not is_login:
print "非法用户"
print "welcome to login..."
temp = func(*arg,**kwargs)
print "login after..."
return temp
return inner
@auth_login
def fetch_server_list(arg):
server_list = ['server1','server2','server3']
return server_list
执行业务程序 yw.py 结果如下:
import base
server_list = base.fetch_server_list('test')
print server_list
函数执行结果:
welcome to login...
login after...
['server1', 'server2', 'server3']
如果name = ”aaaa“, 不是”Allen“,则执行结果:验证失败:
非法用户
welcome to login...
login after...
['server1', 'server2', 'server3']
那么又有人问,这个有个鸟用,我还需要密码验证,那么这个怎么做呢?
少废话,直接上代码:
def login(key):
local_key = "123456" #这里做个一个key验证
if local_key == key:
return True
else:
return False
def auth_login(func):
def inner(*arg,**kwargs):
#key = kwargs['token'] #注意这里
#del kwargs['token']
key = kwargs.pop('token') #这一句等于 上面注释的两句 #这句含义:因为下面的login 只接受一个参数,这里多一个参数,所有删除
is_login = login(key) #注意这里
if not is_login:
print "非法用户"
print "welcome to login..."
temp = func(*arg,**kwargs)
print "login after..."
return temp
return inner
@auth_login
def fetch_server_list(arg):
server_list = ['server1','server2','server3']
return server_list
执行业务程序 yw.py 结果如下:
import base
server_list = base.fetch_server_list('test',token=‘key1111’) #注意这里
print server_list
多装饰器:
@auth_login
@auth_login
def f1():
pass
执行的结果:
就是一层套一层
双装饰用途:
双层装饰器,可以用在以下途径:
比如用户权限管理,第一层装饰器用于用户名密码验证,
第二层用在 判断用户是什么身份的用户,比如:普通用户,超级用户等
需求:
需求又来了,在上面获取 fetch_server_list 之前执行一个函数,
可不可以在fetch_server_list 之后再执行一个函数?
作业1:
将如下三层装饰器用语言解释一遍:
#!/usr/bin/env python
#coding:utf-8
def Before(request,kargs):
print 'before'
def After(request,kargs):
print 'after'
def Filter(before_func,after_func):
def outer(main_func):
def wrapper(request,kargs):
before_result = before_func(request,kargs)
if(before_result != None):
return before_result;
main_result = main_func(request,kargs)
if(main_result != None):
return main_result;
after_result = after_func(request,kargs)
if(after_result != None):
return after_result;
return wrapper
return outer
@Filter(Before, After)
def Index(request,kargs):
print 'index'
更多链接:http://www.cnblogs.com/wupeiqi/articles/4980620.html
python之路第五篇之装饰器:(进阶篇)的更多相关文章
- python入门(十五):装饰器
1.装饰器(decorator):设计模式 作用:给不同的函数和方法,增加不同的公用的功能. @classmethod,@staticmethod等均是装饰器 定义一个装饰函数,函数必须返回一个闭包函 ...
- Python 全栈开发五 迭代器 生成器 装饰器
一.迭代器 迭代协议:对象必须提供一个next方法,执行该方法后会返回迭代的下一项或者抛出Stopiteration异常,终止迭代.切只能往前,不能倒退. 可迭代对象:遵循迭代写一点对象就是可迭代对象 ...
- NO.4:自学python之路------内置方法、装饰器、迭代器
引言 是时候开始新的Python学习了,最近要考英语,可能不会周更,但是尽量吧. 正文 内置方法 Python提供给了使用者很多内置方法,可以便于编程使用.这里就来挑选其中大部分的内置方法进行解释其用 ...
- python之路 内置函数,装饰器
一.内置函数 #绝对值 abs() #所有值都为真才为真 all() #只要有一个值为真就为真 any() #10进制转成二进制 bin() #10进制转成八进制 oct() #10进制转成十六进制 ...
- python之路_函数实例及装饰器介绍
一.习题讲解 1.写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组.例如:[(‘红心’,2), (‘草花’,2), …(‘黑桃,‘A’)] def cards(): num=[] for v ...
- python 基础篇 12 装饰器进阶
本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...
- python 装饰器 一篇就能讲清楚
装饰器一直是我们学习python难以理解并且纠结的问题,想要弄明白装饰器,必须理解一下函数式编程概念,并且对python中函数调用语法中的特性有所了解,使用装饰器非常简单,但是写装饰器却很复杂.为了讲 ...
- Python的高级特性7:闭包和装饰器
本节跟第三节关系密切,最好放在一起来看:python的高级特性3:神奇的__call__与返回函数 一.闭包:闭包不好解释,只能先看下面这个例子: In [23]: def outer(part1): ...
- (转)python装饰器进阶一
Python装饰器进阶之一 先看例子 网上有很多装饰器的文章,上来说半天也没让人看明白装饰器到底是个什么,究竟有什么用,我们直接来看几个例子. Python递归求斐波那契数列 def fibonacc ...
- Python 闭包、迭代器、生成器、装饰器
Python 闭包.迭代器.生成器.装饰器 一.闭包 闭包:闭包就是内层函数对外层函数局部变量的引用. def func(): a = "哈哈" def func2(): prin ...
随机推荐
- Grails笔记二:grails 2.4.3版本下generate-*失效问题解析
最近在学grails框架,因为其敏捷性让我非常喜欢,不过有点让人恼怒的是也许因为grails框架太新了,所以关于grails的书籍很少,而且市面上的书籍大部分都是2007或者2009年的,官方文档又都 ...
- 在centos6上实现编译安装lamp和wordpress,并编译xcache
author:JevonWei 版权声明:原创作品 软件环境: centos6.9 httpd-2.4.27.tar.bz2 apr-1.5.2.tar.bz2 apr-util-1.5.4.tar. ...
- Kafka Streams 剖析
1.概述 Kafka Streams 是一个用来处理流式数据的库,属于Java类库,它并不是一个流处理框架,和Storm,Spark Streaming这类流处理框架是明显不一样的.那这样一个库是做什 ...
- Angular+ionic2 web端 启动程序出现短暂 白屏或黑屏 的处理小妙招
在ionic2项目启动是会出现短暂的白屏或者黑屏,虽然很短,但是用户体验不太好.上网查了相关的资料,都是针对打包APP的解决办法,针对浏览器端使用的项目没有效果,所以自己写了样式,巧妙的避开这个问题, ...
- [我所理解的REST] 2.REST用来干什么的?
笔者每当遇到一个新事物的想去了解的时候,总是会问上自己第一个问题,这个新事物是干什么用的?在解释我所理解的REST这个过程中也不例外,这篇博客我们先关注一下REST是干什么用的,然后后续再解释REST ...
- 关于js中单双引号以及转义符的理解
关于js中单引号(')和双引号(")的使用以及转义的理解 这几天一直在画页面,身为开发人员的我之所以要画页面是因为当前项目中的页面上所有的东西都是从数据库中取得的,也就是动态的,类似于我们设 ...
- 配置VNC SERVER 远程访问
1.安装软件包 # yum install tigervnc-server -y 2. 配置VNC用户 # vim /etc/sysconfig/vncservers VNCSERVERS=" ...
- 团队作业4——第一次项目冲刺(Alpha版本)2017.4.23
1.当天站立式会议照片 本次会议为第一次会议 本次会议在5号公寓1楼召开,本次会议内容: ①:做第一天的简单分工 ②:讨论每个人是否对安排的任务有苦难 ③:规定完成时间是在第二天之前 ④:遇到困难,及 ...
- 201521123101 《Java程序设计》第14周学习总结
1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 在自己建立的数据库上执行常见SQL语句(截图) 2 ...
- Linux下的定时任务 - Cron服务
最近搞咕自己的笔记系统,虽然现在是个人的使用,对于数据库的数据还是比较少,但是安全还是一个我必须注意的东西. (特别是前段时间中了比特币的病毒之后,更是让我关注了我的主机的安全的问题.) 今天的随记是 ...