一、什么是装饰器

  装饰器本质就是函数,功能是为其他函数附加功能

二、装饰器遵循的原则

1、不修改被修饰函数的源代码

2、不修改被修饰函数的调用方式

三、实现装饰器的知识储备

装饰器=高阶函数+函数嵌套+闭包

示例1: 用函数实现

 #计算从1-100,统计函数运行时间

 import time
def cal(l):
start_time=time.time()
res=0
for i in l:
time.sleep(0.1)
res+=i
stop_time = time.time()
print('函数的运行时间是%s' %(stop_time-start_time))
return res print(cal(range(100))) #直接打印得到运行的时间

执行结果:

 函数的运行时间是10.007169723510742
4950

示例2:用装饰器实现函数运行时间

 import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time = time.time()
print('函数运行时间是%s' %(stop_time-start_time))
return res
return wrapper @timmer #调用装饰器
def cal(l):
res=0
for i in l:
time.sleep(0.1)
res+=i
return res res=cal(range(20))
print(res)

四、高阶函数高阶函数定义

1.函数接收的参数是一个函数名

2.函数的返回值是一个函数名

3.满足上述条件任意一个,都可称之为高阶函数

高阶函数示例如下:

示例1:函数接收的参数是一个函数名

 #1.函数接收的参数是一个函数名
import time
def foo():
time.sleep(3)
print('你好啊林师傅') def test(func): #test高阶函数
# print(func) #获取到内存地址
start_time=time.time()
func()
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time))
# foo()
test(foo)

执行结果:

 你好啊林师傅
函数运行时间是 3.0003013610839844
来自foo

示例2

 def foo():
print('from the foo')
def test(func):
return func # res=test(foo)
# # print(res)
# res() foo=test(foo)
# # print(res)
foo() import time
def foo():
time.sleep(3)
print('来自foo') #不修改foo源代码
#不修改foo调用方式

示例3:

 #多运行了一次,不合格
import time
def foo():
time.sleep(3)
print('来自foo') def timer(func):
start_time=time.time()
func()
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time))
return func
foo=timer(foo)
foo()

示例4:

 #没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能
import time
def foo():
time.sleep(3)
print('来自foo') def timer(func):
start_time=time.time()
return func
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time)) foo=timer(foo)
foo()

执行结果:

 来自foo

结论:高阶函数,满足不了装饰器的功能。

高阶函数总结:

1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式

2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

五、函数的嵌套

1、什么是函数的嵌套?

通过在函数内部def的关键字再声明一个函数即为嵌套

示例:

 def father(name):
def son():
print('我的爸爸是%s' %name)
def grandson():
name='就是我自己'
print('我的爷爷是%s' %name)
grandson()
son()
father('linhaifeng')

执行结果:

 我的爸爸是linhaifeng

 我的爷爷是就是我自己

六、闭包

 #闭包:在一个作用域里放入定义变量,相当于打了一个包
def father(auth_type):
# print('from father %s' %name)
def son():
# name='linhaifeng_1'
# print('我的爸爸是%s' %name)
def grandson():
print('我的爷爷是%s' %auth_type)
grandson()
# print(locals())
son()
# father('linhaifeng')
father('filedb')

执行结果:

 我的爷爷是filedb

七、无参装饰器

无参装饰器=高级函数+函数嵌套

1、基本框架

 #这就是一个实现一个装饰器最基本的架子
def timer(func):
def wrapper():
func() return wrapper

2、基本装饰器(基本框架+参数+功能+返回值+使用装饰器+语法糖@)

import time

def timmer(func): #func=test
def wrapper():
# print(func)
start_time=time.time()
func() #就是在运行test()
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return wrapper @timmer #test=timmer(test) #在函数名前面加个@ ,这就是语法糖
def test():
time.sleep(3)
print('test函数运行完毕') test()

代码说明:

 # res=timmer(test)  #返回的是wrapper的地址
# res() #执行的是wrapper()
#
# test=timmer(test) #返回的是wrapper的地址
# test() #执行的是wrapper()
#
# @timmer 就相当于 test=timmer(test)

执行结果:

 test函数运行完毕
运行时间是3.000155210494995

3、加上返回值

 import time
def timmer(func): #func=test
def wrapper():
start_time=time.time()
res=func() #就是在运行test()
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return res
return wrapper @timmer #test=timmer(test)
def test():
time.sleep(3)
print('test函数运行完毕')
return '这是test的返回值' res=test() #就是在运行wrapper
print(res)

执行结果:

 test函数运行完毕
运行时间是3.0001416206359863
这是test的返回值

4、加上参数

 import time
def timmer(func): #func=test1
def wrapper(*args,**kwargs): #test('linhaifeng',age=18) args=('linhaifeng') kwargs={'age':18}
start_time=time.time()
res=func(*args,**kwargs) #就是在运行test() func(*('linhaifeng'),**{'age':18})
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return res
return wrapper # @timmer #test=timmer(test)
def test(name,age):
time.sleep(3)
print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
return '这是test的返回值' @timmer
def test1(name,age,gender):
time.sleep(1)
print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
return '这是test的返回值' # res=test('linhaifeng',age=18) #就是在运行wrapper
# # print(res)
# test1('alex',18,'male') test1('alex',18,'male')

执行结果:

 test1函数运行完毕,名字是【alex】 年龄是【18】 性别【male】
运行时间是1.0007386207580566

八、装饰器应用案例

写一个模拟京东网站,用户认证登录网站和购物加入购物车功能程序

实现功能:用装饰器给所有函数加上验证功能

1、基本框架

 def index():
pass def home():
pass def shopping_car()
pass def order()
pass

2、开始实现

示例1:没有判断验证方式,直接就显示购物车结果。

 user_list=[
{'name':'alex','passwd':''},
{'name':'linhaifeng','passwd':''},
{'name':'wupeiqi','passwd':''},
{'name':'yuanhao','passwd':''},
]
current_dic={'username':None,'login':False} def auth(auth_type='filedb'):
def auth_func(func):
def wrapper(*args,**kwargs):
print('认证类型是',auth_type)
if auth_type == 'filedb':
if current_dic['username'] and current_dic['login']:
res = func(*args, **kwargs)
return res
username=input('用户名:').strip()
passwd=input('密码:').strip()
for user_dic in user_list:
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_dic['username']=username
current_dic['login']=True
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
elif auth_type == 'ldap':
print('鬼才特么会玩')
res = func(*args, **kwargs)
return res
else:
print('鬼才知道你用的什么认证方式')
res = func(*args, **kwargs)
return res return wrapper
return auth_func @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type --->index=auth_func(index)
def index():
print('欢迎来到京东主页') @auth(auth_type='ldap')
def home(name):
print('欢迎回家%s' %name)
#
@auth(auth_type='sssssss')
def shopping_car(name):
print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) # print('before-->',current_dic)
# index()
# print('after--->',current_dic)
# home('产品经理')
shopping_car('产品经理')

执行结果:

 认证类型是 sssssss
鬼才知道你用的什么认证方式
产品经理的购物车里有[奶茶,妹妹,娃娃]

示例2 :给他加上验证功能装饰器(判断用户和密码,跟字典里的用户和密码进行比对)

 user_list=[
{'name':'alex','passwd':''},
{'name':'linhaifeng','passwd':''},
{'name':'wupeiqi','passwd':''},
{'name':'yuanhao','passwd':''},
]
current_dic={'username':None,'login':False} def auth_func(func):
def wrapper(*args,**kwargs):
if current_dic['username'] and current_dic['login']:
res = func(*args, **kwargs)
return res
username=input('用户名:').strip()
passwd=input('密码:').strip()
for user_dic in user_list:
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_dic['username']=username
current_dic['login']=True
res = func(*args, **kwargs)
return res #返回值
else:
print('用户名或者密码错误') return wrapper @auth_func #加证功能,也是装饰器
def index():
print('欢迎来到京东主页') @auth_func
def home(name):
print('欢迎回家%s' %name) @auth_func
def shopping_car(name):
print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) print('before-->',current_dic)
index()
print('after--->',current_dic)
home('产品经理')
shopping_car('产品经理')

执行结果:

 before--> {'username': None, 'login': False}
用户名:alex #输入字典里的用户名和密码,才能登录成功。
密码:123
欢迎来到京东主页
after---> {'username': 'alex', 'login': True}
欢迎回家产品经理
产品经理的购物车里有[奶茶,妹妹,娃娃]

python基础-装饰器的更多相关文章

  1. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  2. python基础—装饰器

    python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...

  3. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  4. day5学python 基础+装饰器内容

    基础+装饰器内容 递归特性# 1.必须有一个明确的结束条件# 2.每次进入更深一层递归时,问题规模相比上次递归应有所减少# 3.递归效率不高 def run(n): print(n) if int(n ...

  5. Python自动化 【第四篇】:Python基础-装饰器 生成器 迭代器 Json & pickle

    目录: 装饰器 生成器 迭代器 Json & pickle 数据序列化 软件目录结构规范 1. Python装饰器 装饰器:本质是函数,(功能是装饰其它函数)就是为其他函数添加附加功能 原则: ...

  6. python基础 (装饰器,内置函数)

    https://docs.python.org/zh-cn/3.7/library/functions.html 1.闭包回顾 在学习装饰器之前,可以先复习一下什么是闭包? 在嵌套函数内部的函数可以使 ...

  7. python基础-装饰器,生成器和迭代器

    学习内容 1.装饰器 2.生成器 3.迭代器 4.软件目录结构规范 一:装饰器(decorator) 1.装饰器定义:本质就是函数,用来装饰其他函数,即为其他函数添加附加功能. 2.装饰器原则:1)不 ...

  8. python基础===装饰器@property 的扩展

    以下来自Python 3.6.0 Document: class property(fget=None, fset=None, fdel=None, doc=None) Return a proper ...

  9. <Python基础>装饰器的基本原理

    1.装饰器 所谓装饰器一般是对已经使用(上线)的函数增加功能. 但是因为一般的大公司的严格按照开放封闭原则(对扩展是开放的,对修改是封闭的),不会让你修改原本的函数. 装饰器就是在不改变原本的函数且不 ...

随机推荐

  1. 有一个小效果而引出的appendTo()函数。

    在公司做项目的时候,始终不了解信息逐条向上滚的动画效果,后来查阅相关资料,终于明白了,在这个过程中,让我对appendTo这个函数有了一个全新的认识.话不多说,首先是demo: <!DOCTYP ...

  2. HTML5学习之 开发工具

    Notepad++.Editplus 是常用的开发编辑器.这些在Window系统下,比较容易找到,但是在MAC系统下,有的是收费的,有的是不支持.我开发的时候,用的是TextWrangler,如图: ...

  3. SharePoint 2013 定制搜索显示模板(二)

    前言 之前一篇博客,简单的介绍了如何定制搜索显示模板,这一次,我们介绍一下如何定制搜索显示时,弹出来的那个页面,相信这个大家也都会遇到的. 1.第一部分就是搜索显示模板的部分,第二部分就是搜索项目详情 ...

  4. maven:用appassembler-maven-plugin打包含有自定义目录的JAVA程序

    问题说明: 用maven构建了一个项目,目录结构如下: appassemblerd的配置: <plugin> <groupId>org.codehaus.mojo</gr ...

  5. Picasso设置圆角

    package liu.roundimagedemo.view; import android.graphics.Bitmap; import android.graphics.BitmapShade ...

  6. MVC MODEL Attribute 操纵速记

    目的: 扩充Attribute 任意读取并Render 需要的Attribute     用法: @Html.ParaLabelFor(x=>x.ServiceName):@Html.ParaN ...

  7. Android 框架学习之 第一天 okhttp & Retrofit

    最近面试,一直被问道新技术新框架,这块是短板,慢慢补吧. 关于框架的学习,分几个步骤 I.框架的使用 II.框架主流使用的版本和Android对应的版本 III.框架的衍生使用比如okhttp就会有R ...

  8. .Net Core 之 图形验证码 本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能。

    本文介绍.Net Core下用第三方ZKWeb.System.Drawing实现验证码功能. 通过测试的系统: Windows 8.1 64bit Ubuntu Server 16.04 LTS 64 ...

  9. ORA-02429: cannot drop index used for enforcement of unique /primary key

    相信不少人遇到过ORA-02429: cannot drop index used for enforcement of unique /primary key 这个错误,对应的中文提示"O ...

  10. CMS本质上是什么

    2015-121.数据可以任意取和构造,结构也很自由,不一定是“站点-栏目-文章-评论”.2.主要用于显示,前台不产生数据(评论.浏览次数除外).3.在模版进行循环.判断,也比后台写代码要方便很多很多 ...