装饰器及例题分析
知识点:
装饰器的定义:
- 装饰器的实现是函数里面嵌套函数;
- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;
- 装饰器需要传递一个函数, 返回值也是一个函数对象.
1、map函数
def f(x):return x * x"""map()传入的第一个参数是一个函数,第二个参数是一个序列,第二个序列作为第一个参数的输入值
也就是说第二个参数调用了第一个函数
"""print map(f, [1, 2, 3, 4])
2、匿名函数
#上面的函数也可以用一条语句代替,即匿名函数lambdax:
print map(lambda x: x * x, [1, 2, 3, 4])
3、带有参数的装饰器:
import functools
import time# 打印当前的时间
print time.ctime()def log(name):def add_log(fun):@functools.wraps(fun)def wrapper(*args, **kwargs):start_time = time.time()res = fun(*args, **kwargs)end_time = time.time()print '<%s> [%s] 函数名:%s,运行时间:%.5f,运行返回值结果:%d' %(name, time.ctime(), fun.__name__, end_time - start_time, res)return resreturn wrapperreturn add_log@log('lily')
def add(x,y):time.sleep(1)return x+yprint add(1,2)
4、多个装饰器的执行顺序
#定义两个装饰器,将两个装饰器给函数,探究其中调用的先后顺序
def decorator_a(func):print 'Get in decorator_a'def inner_a(*args, **kwargs):print 'Get in inner_a'res = func(*args, **kwargs)return resreturn inner_adef decorator_b(func):print 'Get in decorator_b'def inner_b(*args, **kwargs):print 'Get in inner_b'res = func(*args, **kwargs)return resreturn inner_b# 当有多个装饰器时,从下到上调用装饰器
@decorator_a
@decorator_b
def f(x):print 'Get in f'return x * 2f(1)
总结:
从运行结果可以看出,若将decorator_a和decorator_b按顺序给函数,则装饰器外部为从下岛上调用装饰器,内部仍按顺序调用。
例题分析:
1、多个装饰器的应用
要求:查看若要实现相同的功能python内置函数和自己编写的函数哪个运行时间更少
装饰器需求:获取每个函数的执行时间
1.函数执行之前计算时间
2.函数执行之后计算时间
3.运行时间=执行后时间-执行前时间
问题1:被装饰的函数有返回值的时候怎么办?
问题2:如何保留被装饰函数的函数名和帮助文档信息
import functools import random import string import time"""导入模块的快捷键为Alt+Enter并选择""" li = [random.choice(string.ascii_letters) for i in range(100)]def timeit(fun):"""装饰器"""@functools.wraps(fun)def wrapper(*args, **kwargs): # 接收可变参数和关键字参数"""这是一个wrapper函数"""# args:元组 kwargs:字典# 函数执行之前start_time = time.time()# 执行函数# 接收被装饰函数的返回值res = fun(*args, **kwargs)# 函数执行之后end_time = time.time()print '运行的时间为:%.6f' % (end_time - start_time)return resreturn wrapper@timeit def con_add():s = ''for i in li:s += (i + ',')print s@timeit def join_add():print ','.join(li)@timeit def fun_list(n):"""这是fun_list函数,被timeit装饰"""return [2 * i for i in range(n)]@timeit def fun_map(n):"""这是fun_map函数"""return list(map(lambda x: x * 2, range(n)))# 匿名函数 # map传入的第一个参数为一个函数,第二个为一个序列con_add() join_add() print fun_list(50000) print fun_map(50000)#保留被装饰函数的函数名和帮助文档信息 print fun_list.__name__ print fun_list.__doc__
总结:从上面的运行时间可以看出:
用python的内置函数比自己编写的函数运行时间少,所以我们在调用函数的时候尽量使用python的内置函数。
2、
在我们实际的应用中,会应用到多个装饰器,例如: 先验证是否登陆成功再验证权限的方法
要求:用户登陆验证的装饰器 is_login
1.如果用户登陆成功,则执行被装饰的函数
2.如果用户登陆不成功,则执行登陆函数
import functools
# 让函数统一
import inspectdef is_root(fun):@functools.wraps(fun)def wrapper(*args, **kwargs):inspect_res = inspect.getcallargs(fun, *args, **kwargs)print 'inspect_res的返回值:%s' % inspect_resif inspect_res.get('name') == 'root':res = fun(*args, **kwargs)return reselse:print 'Error:no perminssion add student'return wrapperdef is_login(fun):@functools.wraps(fun)def warrper(*args, **kwargs):if args[0] in login_session:res = fun(*args, **kwargs)return reselse:print 'Error:%s未登陆'return warrper@is_login
@is_root
def add_student(name):print '添加学生信息'login_session = ['root', 'admin', 'redhat']
# 调用函数
add_student('root')
3、
要求:用户登陆验证的装饰器 is_login
1.如果用户登陆成功,则执行被装饰的函数
2.如果用户登陆不成功,则执行登陆函数
import functoolslogin_users = ['admin', 'root']def is_login(fun):@functools.wraps(fun)def wrapper(*args, **kwargs):# 判断写博客这个用户是否登陆成功if kwargs.get('name') in login_users:res = fun(*args, **kwargs)return reselse:res = login()return resreturn wrapperdef login():return '登陆。。。'@is_login def writeBlog(name):return '编写博客。。'print writeBlog(name='admin')
若最后调用函数时为:
print writeBlog(name='admin')
4、
要求:
创建装饰器, 要求如下:
1. 创建add_log装饰器, 被装饰的函数打印日志信息;
2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx
import time import functools #print time.ctime()def add_log(fun):@functools.wraps(fun)def wrapper(*args,**kwargs):start_time = time.time()res = fun(*args,**kwargs)end_time = time.time()print '[%s] 函数名:%s,运行时间:%.5f,运行返回值结果:%d' %(time.ctime(),fun.__name__,end_time-start_time,res)return resreturn wrapper@add_log def add(x,y):time.sleep(1)return x+yprint add(1,2)
5、
编写装饰器required_ints, 条件如下:1). 确保函数接收到的每一个参数都是整数;2). 如果参数不是整形数, 打印 TypeError:参数必须为整形import functoolsdef required_ints(fun):@functools.wraps(fun)def wrapper(*args, **kwargs):for i in args:if not isinstance(i, int):print 'TypeError:参数必须为整形'breakelse:res = fun(*args, **kwargs)return resreturn wrapper@required_ints def add(a, b):return a + b@required_ints def myMax(a,b,c,d):return max(a,b,c,d)print add(1,2) print myMax(1,2,3,4)
6、
要求:编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类型
import functoolsdef required_types(*kinds):def required_ints(fun):@functools.wraps(fun)def wrapper(*args, **kwargs):for i in args:if not isinstance(i, kinds):print 'TypeError:参数必须为',kindsbreakelse:res = fun(*args, **kwargs)return resreturn wrapperreturn required_ints@required_types(float,float) def add(a, b):return a + bprint add(1.1,3)
相关文章:

iOS开发系列--让你的应用“动”起来
概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画、关键帧动画、动画组、转场动画,如何通…

ios app 砸壳
这里介绍使用dumpdecrypted砸壳。原理是用DYLD_INSERT_LIBRARIES这个环境变量加载脱壳的动态链接库dumpdecrypted.dylib 1.ssh连接上越狱的机器,输入密码alpine ssh root192.168.7.116 2.打开要砸的app,ps aux | grep var找到它的目录 yigewangde-iPhone…

基于visual Studio2013解决面试题之0804复杂链表
题目解决代码及点评/*复杂链表的拷贝,现在有一个复杂链表,完成一个clone函数拷贝一个链表复杂链表是指struct Node{struct Node* _next;struct Node* _sibling; // sibling指向链表中任意一个节点,或者…
python考试编程题
3. a: while True: s raw_input(变量名为:) if s exit: print 退出 break #判断是否由字母或下划线组成 if s[0].isalpha() or s[0] _: for i in s[1:]: if not (i.isalnum() or i _): print %s变量…

【分享】bootstrap学习笔记
一、基础知识 1.整体架构以响应式设计为理念,css组件、js插件jquery、基础布局组件和12栅格系统搭建。1.1响应式设计:结合media query查询,适应更多设备,自动适应用户的设备环境,不必为每个终端做一个特定的版本。2.cs…

大三下学期总结
本学期的最后一门考试已经考完了,就相当于本学期要结束了,本学期结束了,就相当于大学的学习生活接近尾声了。感觉大三下开学也只在不久之前,但是真的要结束了,我觉得这学期实在是过得太充实了,一直是在追着…

通过 cygwin64 自己编译对应的 Tera Term cyglaunch.exe
步骤如下: 将 cygterm.tar.gz解压到任意目录,当然要cygwin容易操作。(本例直接放到$HOME目录下,启动cygwin后的默认目录,如果之前没有更改的话)将 Makefile 中的 -mno-cygwin 选项删除。执行make࿰…
面向对象概念及三大特点
面向对象: 面向对象的基本概念 面向对象 oop : object oriented programming 我们之前学习的编程方式就是面向过程的 面向过程和面向对象,是两种不同的编程方式 对比面向过程的特点,可以更好的了解什么是面向对象 过程和函数(都是对一段…
【Android】ViewPager实现无限循环滚动
最近做的一个项目,客户要求在ViewPager实现的主页面中滑动到最后一页后继续滑动能返回到第一页,也就是实现无限循环滚动,效果如下: 看了下ViewPager没有滑到尽头的回调方法,因此想到的解决方案是,在原来的最…

LabVIEW 三维机器人展示
本程序是使用solidworks绘制模型图,通过LabVIEW 2013导入wrl文件完成. 程序效果如下: (工程文件) (3维机器人模型) (控制界面,未做美化....因为实际上这部分程序只是一小部分,主程序运行时,这部分面板是不显示的~\(≧▽≦)/~啦啦啦) 程序下载: 百度网盘: http://pan.baidu.com/…

SqlServer2008查询性能优化_第一章
转载于:https://www.cnblogs.com/MiaoXin/p/5813207.html
Python之类
1、类的结构 1.使用面向对象开发,第一步是设计类 2.使用 类名() 创建对象,创建对象的动作有两步 1.在内存中为对象分配空间 2.调用初始化方法__init___ 为对象初始化 3.对象创建后,内存中就有了一个对象的实实在在的存在--实例 因此…

祝大家圣诞节快乐!
在圣诞节来临之际,分享这份网页的代码,祝愿大家圣诞节快乐!点击这里查看效果 以下是源代码,可以保存到html文件打开看效果: 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht…
【iOS官方文档翻译】UICollectionView与UICollectionViewFlowLayout
(一)先来简单回顾一下UICollectionView *UICollectionView的简单使用可以看我以前写的这篇博文:UICollectionView的基本使用 UICollectionView与UITableView很相似,必须实现两个代理:UICollectionViewDataSource和UI…
python之文件
1、什么是文件指针? 文件指针 文件指针标记从哪个位置开始读取数据 第一次打开文件时,通常文件指针会指向文件的开始位置 当执行了read方法后,文件指针会移动到读取内容的末尾 创建一个当前目录下的文件pass 内容为: westos …

一个6年的菜鸟,在4年之前做的一些功能(二)
前戏:针对上一篇列出来的功能点,今天和大家分享下这个自定义的公式是怎么设计的,由于我的第一篇博客在首页被管理员移走了,大家可以点击这里来跳转,看下第一篇的目录结构。本人作为老菜鸟,和大家分享的也是…

Oracle11.2新特性之listagg函数 (行列转换)
SELECT regexp_substr(公司1,贵公司2, [^,], 1, LEVEL, i) FROM dualCONNECT BY LEVEL < length(公司1,贵公司2) - length(REPLACE(公司1,贵公司2, ,, )) 1 以上为字符串带分隔符的转换为列 Oracle11.2新增了LISTAGG函数,可以用于字符串聚集,测试如下…
Mac 安装Android Studio
一、下载 可以通过以下这些网站下载Mac版的Android Studio http://www.androiddevtools.cn http://www.android-studio.org 二、安装 双击下载好的dmg文件,拖曳安装。 拷贝完成之后,在应用程序中打开Android Studio。这时候会引导进行环境安装和设置…
iscsi网络磁盘共享
iscsi(Internet SCSI)支持从客户端(发起端)通过IP向远程服务器上的ISCSI存储设备(目标)发送scsi命令。ISCSI限定名称用于确定发起端和目标,并采用iqn.yyy-mm.{reverse domain}:label的格式。 默认情况下,网…
转: IO设计模式:Reactor和Proactor对比
转: https://segmentfault.com/a/1190000002715832 平时接触的开源产品如Redis、ACE,事件模型都使用的Reactor模式;而同样做事件处理的Proactor,由于操作系统的原因,相关的开源产品也少;这里学习下其模型结构ÿ…

程序员该怎样放松?8个好网站推荐
1)看风景程序员每天在液晶屏幕下工作很长时间,应该让干涩的眼睛得到好好的放松,偶尔看看窗外的绿树或远处的风景可能是不错的方式,但是这在北京上海广州这样的大城市里不太现实,所以这里推荐一个纯粹的分享旅行照片的网…
【iOS】UIButton 图标在上文字在下
iOS默认的UIButton是图片在左文字在右,但是很多时候需求是图片在上文字在下(如效果图1、效果图2),因此想到,通过写一个JXButton继承自UIButton,并重写相关方法即可,以后项目中需要用的话就直接使…
多线程和mysql
多线程 1、多线程的定义: 什么是线程: 线程是操作系统能够进行运算调度的最小单位(程序执行流的最小单元)。它被包含在进程之中, 是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程并行执行不…

poj2154-color-polyan次二面体+欧拉函数优化
N<1e9,O(nlogn)的做法会超时。从枚举置换转变为枚举轮换长度,然后可以利用欧拉函数,把复杂度变为O(√n * logn) 1 /*--------------------------------------------------------------------------------------*/2 3 #include <algorithm>4 #in…
【iOS】通讯录分组方式展示数据
本例子是将后台返回的医生列表(包含姓名和电话,demo从plist文件读取),按拼音进行分组显示(A-Z),最终效果如下图: 一、创建Doctor医生类: Doctor类属性包括姓名、电话以及姓名第一个字的拼音首字母ÿ…
LVS_DR实现(负载均衡)及LVS_DR+keepalived实现(高可用+负载均衡)
client->VS->RS->client(VS只做调度,RS为虚拟服务器) LVS_DR原理图解: 优点:负载均衡器只负责将请求包分发给物理服务器,而物理服务器将应答包直接发给用户。所以,负载均衡器能处理 很巨大的请求量,这种方式…

【LeetCode】136. Single Number 解题小结
题目: Given an array of integers, every element appears twice except for one. Find that single one. Note:Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 这题目的要求不仅是要求是线性时间…
iOS小技巧积累
平时项目中用到的,记录下来(持续更新)。1.在导航栏右边添加多个UIBarButtonItemUIBarButtonItem *searchScheduleBtn [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:"search_small"] style:UIBarButtonItemStylePl…

(转)iPhone开发经典语录集锦
1:如果无法保证子类行为的一致性,那么就用委托 If the subClass cannt keep with superClass,use delegate rather than inheritance. 2:屏幕上看到的,都是UIVew Everything you see on Screen is UIView. 3:如果对性能要求高,慎…
varnish 实现 CDN 缓存系统构建
cdn 搭建 (server1:172.25.1.1 ) : [roottest1 ~]# ls varnish-3.0.5-1.el6.x86_64.rpm varnish-libs-3.0.5-1.el6.x86_64.rpm [roottest1 ~]# yum install * -y [roottest1 ~]# cd /etc/varnish/ [roottest1 varnish]# vim /etc/sysconfig/varnish [roottest1 varnish]# sysct…