一、装饰器 

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

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

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

总结:原则如下:

  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()的内部执行。然后再这两个函数的前面加上@timmerindex()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 == '':
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 == '':
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 == '':
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 函数 装饰器的使用方法的更多相关文章

  1. Python函数装饰器原理与用法详解《摘》

    本文实例讲述了Python函数装饰器原理与用法.分享给大家供大家参考,具体如下: 装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值 ...

  2. Python函数装饰器高级用法

    在了解了Python函数装饰器基础知识和闭包之后,开始正式学习函数装饰器. 典型的函数装饰器 以下示例定义了一个装饰器,输出函数的运行时间: 函数装饰器和闭包紧密结合,入参func代表被装饰函数,通过 ...

  3. python函数-装饰器

    python函数-装饰器 1.装饰器的原则--开放封闭原则 开放:对于添加新功能是开放的 封闭:对于修改原功能是封闭的 2.装饰器的作用 在不更改原函数调用方式的前提下对原函数添加新功能 3.装饰器的 ...

  4. Python 函数装饰器

    首次接触到装饰器的概念,太菜啦! Python 装饰器可以大大节省代码的编写量,提升代码的重复使用率.函数装饰器其本质也是一个函数,我们可以把它理解为函数中定义了一个子函数. 例如我们有这么一个需求, ...

  5. Python @函数装饰器及用法

    1.函数装饰器的工作原理 函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示: #funA 作为装饰器函数 def funA(fn): #... fn ...

  6. Python @函数装饰器及用法(超级详细)

    函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示: #funA 作为装饰器函数 def funA(fn): #... fn() # 执行传入的fn参 ...

  7. Python高手之路【四】python函数装饰器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

  8. Python高手之路【四】python函数装饰器,迭代器

    def outer(func): def inner(): print('hello') print('hello') print('hello') r = func() print('end') p ...

  9. python 函数 装饰器 内置函数

    函数 装饰器 内置函数 一.命名空间和作用域 二.装饰器 1.无参数 2.函数有参数 3.函数动态参数 4.装饰器参数 三.内置函数 salaries={ 'egon':3000, 'alex':10 ...

随机推荐

  1. 状态压缩DP

    K - Necklace Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:327680KB     ...

  2. python多进程

    一.多进程池 from multiprocessing import Pool import time pool = Pool(processes=3) result=[];lr=range(t);a ...

  3. mysql innobackupex xtrabackup 大数据量 备份 还原

    大数据量备份与还原,始终是个难点.当MYSQL超10G,用mysqldump来导出就比较慢了.在这里推荐xtrabackup,这个工具比mysqldump要快很多. 一.Xtrabackup介绍 1, ...

  4. Windows 8.1 应用再出发 - 几种新增控件(2)

    本篇我们接着来介绍Windows 8.1 的新增控件,分别是:Flyout.MenuFlyout.SettingsFlyout.Hub 和 Hyperlink. 1. Flyout Flyout被称为 ...

  5. Why does my ListView scroll to the top when navigating backwards?

    I’ve seen a few people asking this question. They have a page which contains a ListView and when an ...

  6. [ An Ac a Day ^_^ ] CodeForces 680A Bear and Five Cards

    这两天回家了 家里电脑太卡 调试不方便 就只能写写水题了…… #include<stdio.h> #include<iostream> #include<algorith ...

  7. javaScript系列 [04]-javaScript的原型链

    [04]-javaScript的原型链 本文旨在花很少的篇幅讲清楚JavaScript语言中的原型链结构,很多朋友认为JavaScript中的原型链复杂难懂,其实不然,它们就像树上的一串猴子. 1.1 ...

  8. 手机端开发,基础设置1-body-fontsize

    一.设计稿设计大小按照750设计. 二.单位使用rem,相对于body  fontsize 相对大小计算. 三.假设750下,body fontsize 为100,为了方便计算. 四.通过设置当前设备 ...

  9. 金融量化分析【day110】:NumPy多维数组

    一.Numpy简介 NumPy 是高性能科学计算和数据分析的基础包,它是pandas等其他各种工具的基础 1.主要功能 1.ndarray,一个多维数组结构,高效且节省空间 2.无序循环对整组数据进行 ...

  10. MySQL分组查询,前3条数据

    SELECT tpn.news_id, tpn.title, tpn.news_group_id, tpn.send_date FROM t_pm_news tpn WHERE 3 > ( SE ...