本文实例讲述了Python函数装饰器常见使用方法。分享给大家供大家参考,具体如下:

一、装饰器

首先,我们要了解到什么是开放封闭式原则?

软件一旦上线后,对修改源代码是封闭的,对功能的扩张是开放的,所以我们应该遵循开放封闭的原则。

也就是说:我们必须找到一种解决方案,能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能。

总结:原则如下:

1、不修改源代码

2、不修改调用方式

目的:在遵循1和2原则的基础上扩展新功能。

二、什么是装饰器?

器:指的是工具,

装饰:指的是为被装饰对象添加新功能。

完整的含义:装饰器即在不修改装饰对象源代码与调用方式的前提下,为被装饰器对象添加新功能的一种函数,这个函数的特殊之处就在于它的返回值也是一个函数。

一般而言,我们想要拓展原来函数的代码,直接的办法就是侵入代码里面修改,例如:

import time

def index():

start_time=time.time()

time.sleep(3)

print('hello word')

stop_time=time.time()

print('run time is %s'%(stop_time-start_time))

index()

输出:

hello word

run time is 3.000171422958374

以上代码就是让你过三秒才打印'hello word',下面我们要再添加一个新功能,和上面的功能一样,但是要传参数进去,过5秒输出结果。

修改1:

import time

def index():

time.sleep(3)

print('hello word')

def home(name):

time.sleep(5)

print('welcome %s to home page'%name)

def wrapper(func):

start_time=time.time()

func('haolo')

stop_time=time.time()

print('run time is %s'%(stop_time-start_time))

wrapper(home)

输出:

welcome haolo to home page

run time is 5.000286102294922

这样写感觉还是不怎么好,而且我们还修改了函数的调用方式,很不符合规矩。所以我们还是换一种方式来修改它。通过装饰器的方式。

修改2

import time

def index():

time.sleep(3)

print('hello word')

def home(name):

time.sleep(5)

print('welcome to %s'%name)

def outter(func): # func为最原始的inde 和home

def warpper():

start_time=time.time()

func('yuan')

stop_time=time.time()

print(stop_time-start_time)

return warpper

home=outter(home) ###home这个变量名是新赋值的,把原来的home给覆盖了。

home()

输出:

welcome to yuan

5.000286102294922

这种方式虽然满足了不修改源代码和不修改调用方式的条件,但还是不能够实现两个函数同时运行的功能,说到底还是不行,我们还得想个方式出来。就是让他们两个同时运行。这时,我又想到了上节课所学的知识,就是*args和**kargs,用两个函数通过可变参数形式来实现内嵌函数的形式传入,所以它支持运行是构建参数列表,这对于以上两次不能解决的办法是最有效的。下面我们来试试,看到底能不能成功。

方式3:

import time

def index():

time.sleep(3)

print('hello word')

def home(name):

time.sleep(5)

print('welcome %s to home page'%name)

def timmer(func): #func为最原始的home

def warpper(*args,**kwargs):

start_time=time.time()

res=func(*args,**kwargs) #调用了最原始的home

stop_time=time.time()

print(stop_time-start_time)

return res

return warpper

index=timmer(index) #为最新的index = wrapper

home=timmer(home) #为最新的home = wrapper

home(name='yuan') #wrapper=('yuan')

index() #wrapper

输出:

welcome yuan to home page

5.000285863876343

hello word

3.000171661376953

看吧,很快就实现了两个功能并用,而且我们还没有修改原始代码,还有调用方式。

其实很简单,我只是用了一个无参装饰器的模板,这个模板可以说是万能的,在以后很多的函数代码都可以用这种方式来套用。

模板:

def outer(func):

def inner(*args,**kwargs):

res=func(*args,**kwargs)

return res

return inner

现在又有问题来了,我们调装饰器的时候,每调一次,又要把装饰器对象传进来,调一次又传一次,这样不会觉得很麻烦吗?那么我们又想到了一种方法,就是装饰器语法糖,在被装饰对象的上面加@timmer 用它来取代 index=timmer(index)

并且把返回值正常的返回给它。

import time

def timmer(func): #func为最原始的home

def warpper(*args,**kwargs):

start_time=time.time()

res=func(*args,**kwargs) #调用了最原始的home

stop_time=time.time()

print(stop_time-start_time)

return res

return warpper

@timmer #就是取代底下的 index=timmer(index)

def index():

time.sleep(3)

print('hello word')

@timmer #就是取代底下的home=timmer(home) home(name='yuan')

def home(name):

time.sleep(5)

print('welcome %s to home page'%name)

index()

home('liuyuan')

输出:

hello word

3.000171661376953

welcome liuyuan to home page

5.000286102294922

注意:这里的timmer函数就是最原始的装饰器,它的参数就是一个函数,然后返回值也是一个函数。其中作为参数的这个函数index()和hemo(name)就是在返回函数的wrapper()的内部执行。然后再这两个函数的前面加上@timmer,index()和home(name)函数就相当于被注入了计时功能,现在只需要调用index()和home('yuan'),它就已经变身为'新功能更多的函数了。'

所以这里的装饰器就像一个注入的符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。

用装饰器来实现认证功能:

import time

current_user={

'username':None,

#'login_time':None

}

def auth(func):

# func = index

def wrapper(*args,**kwargs):

if current_user['username']:

print('已经登录过了')

res=func(*args,**kwargs)

return res

uname = input('输入用户名:').strip()

pwd = input('密码:').strip()

if uname == 'yuan' and pwd == '123':

print('登录成功')

current_user['username']=uname

res = func(*args,**kwargs)

return res

else:

print('用户名或密码错误')

return wrapper

@auth #index = auth(index)

def index():

time.sleep(1)

print('welcom to index page')

@auth

def home(name):

time.sleep(2)

print('welcome %s to home page'%name)

input()

home('yuan')

有参数的装饰器来用于用户认证

import time

current_user={

'username':None,

# 'login_time':None

}

def auth(func):

# func=index

def wrapper(*args,**kwargs):

if current_user['username']:

print('已经登陆过了')

res=func(*args,**kwargs)

return res

uname=input('用户名>>: ').strip()

pwd=input('密码>>: ').strip()

if uname == 'yuan' and pwd == '123':

print('登陆成功')

current_user['username']=uname

res=func(*args,**kwargs)

return res

else:

print('用户名或密码错误')

return wrapper

def timmer(func):

def wrapper(*args,**kwargs):

start_time=time.time()

res=func(*args,**kwargs)

stop_time=time.time()

print(stop_time-start_time)

return res

return wrapper

@timmer # timmer 统计的是auth+index的执行时间

@auth

def index():

time.sleep(1)

print('welcome to index page')

return 122

index()

叠加多个装饰器:

import time

current_user={

'username':None,

# 'login_time':None

}

def auth(func):

# func=index

def wrapper(*args,**kwargs):

if current_user['username']:

print('已经登陆过了')

res=func(*args,**kwargs)

return res

uname=input('用户名>>: ').strip()

pwd=input('密码>>: ').strip()

if uname == 'egon' and pwd == '123':

print('登陆成功')

current_user['username']=uname

res=func(*args,**kwargs)

return res

else:

print('用户名或密码错误')

return wrapper

def timmer(func):

def wrapper(*args,**kwargs):

start_time=time.time()

res=func(*args,**kwargs)

stop_time=time.time()

print(stop_time-start_time)

return res

return wrapper

@timmer # timmer 统计的是auth+index的执行时间

@auth

def index():

time.sleep(1)

print('welcome to index page')

return 122

index()

关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

本文标题: Python函数装饰器常见使用方法实例详解

本文地址: http://www.cppcns.com/jiaoben/python/255644.html

python装饰器函数-Python函数装饰器常见使用方法实例详解相关推荐

  1. python实战经典例子_Python基础之列表常见操作经典实例详解

    本文实例讲述了Python基础之列表常见操作.分享给大家供大家参考,具体如下: Python中的列表操作 列表是Python中使用最频繁的数据类型[可以说没有之一] 一组有序项目的集合 可变的数据类型 ...

  2. python队列怎么用_Python队列的定义与使用方法实例详解

    这篇文章主要介绍了Python队列的定义与使用方法,结合具体实例形式分析了Python定义及使用队列的具体操作技巧与注意事项,需要的朋友可以参考下 本文实例讲述了Python队列的定义与使用方法.分享 ...

  3. python中rstrip 函数,Python rstrip()方法实例详解

    Python 字符串 描述 Python rstrip() 删除 string 字符串末尾的指定字符(默认为空格). 语法 rstrip()方法语法: str.rstrip([chars]) 参数 c ...

  4. python strptime函数转时间数组_python time.strptime格式化实例详解

    在python的时间使用时,我们无非就是输出字符串的形式,又或者是其他的形式跟字符串之间的来回转换.时间数组对于我们获取具体的年或是天数,都是常用的首段.本篇需要讲到的time.strptime函数, ...

  5. python中类的构成_Python中类型关系和继承关系实例详解

    本文详细介绍了Python中类型关系和继承关系.分享给大家供大家参考.具体分析如下: 如果一个对象A持有另一个对象B的ID,那么检索到A之后就可以检索到B,我们就说存在一个A到B的导航.这种导航关系使 ...

  6. python标准类型内建模块_Python内建模块struct实例详解

    本文研究的主要是Python内建模块struct的相关内容,具体如下. Python中变量的类型只有列表.元祖.字典.集合等高级抽象类型,并没有像c中定义了位.字节.整型等底层初级类型.因为Pytho ...

  7. python数据清理的实践总结_python 数据的清理行为实例详解

    python 数据的清理行为实例详解 数据清洗主要是指填充缺失数据,消除噪声数据等操作,主要还是通过分析"脏数据"产生的原因和存在形式,利用现有的数据挖掘手段去清洗"脏数 ...

  8. python生成表格文件_python 读取excel文件生成sql文件实例详解

    python 读取excel文件生成sql文件实例详解 学了python这么久,总算是在工作中用到一次.这次是为了从excel文件中读取数据然后写入到数据库中.这个逻辑用java来写的话就太重了,所以 ...

  9. python脚本例子_python dict 字典 以及 赋值 引用的一些实例(详解)

    最近在做一个很大的数据库方面的东东,要用到根据数值来查找,于是想到了python中的字典,平时没用过dict这个东东 用的最多的还是 list 和 tuple (网上查 用法一大堆) 看了一下创建字典 ...

最新文章

  1. linux sdk 窗口句柄,Venus: 针对Linux平台上,对常用的系统API进行面向对象的封装SDK。...
  2. 【前端就业课 第一阶段】HTML5 零基础到实战(五)基础元素
  3. C++获取本机所有ip地址,可区分类型是有线无线虚拟机还是回环
  4. 十年架构师:我是这样手写Spring的,用300行代码体现优雅之道
  5. 阿里研究院:2020阿里农产品电商报告
  6. 架构设计:数据服务系统0到1落地实现方案
  7. 设计配色专辑,很值得设计师拥有
  8. android开机启动shell脚本
  9. git拉取github上的分支和本地分支提交到github
  10. STL源码剖析(一)
  11. 信息系统项目管理师论文范例4-进度管理
  12. 推荐一本Python数据挖掘的好书
  13. xampp mysql使用教程_nodejs使用xampp中的mysql教程
  14. vultarget-a红日靶场全面解析(完整版)
  15. 我们总是喜欢拿顺其自然来敷衍人生道路上的荆棘坎坷,却很少承认,真正的顺其自然是竭尽所能之后的不强求,而非两手一摊的不作为。
  16. 计算机网络自顶向下-套接字编程作业
  17. 第12课:如何理解技术管理者(上)
  18. ProcessOn在线画流程图介绍
  19. 利用不蒜子统计网站的访问量
  20. MATLAB atan 和 atan2

热门文章

  1. 在 Ubuntu 14.04/15.04 上配置 Node JS v4.0.0
  2. typedef,static,const用法
  3. C# 3.0新特性系列(1):隐含类型局部变量
  4. 文件上传oss服务器
  5. centos6.5编译安装php7,及配置与nginx通信。
  6. awk匹配以aaa开头,以bbb结尾的内容,同时aaa和bbb之间还包含ccc
  7. JavaScript 公有 私有 静态属性和方法
  8. js引用action层变量
  9. php 两次post,ajax跨域往php程序post数据时,php程序总是执行两次的解决办法
  10. python使用缩进作为语法边界-重庆铜梁高校邦数据科学通识课【Python基础语法】答案...