一、什么是装饰器

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

二、装饰器遵循的原则

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. Android—android与js交互以及相互传参

    Android中可以通过WebView来实现与js的交互,让用户可以在android客户端看到js写的页面,接下来为大家介绍的就是怎样实现此功能: 首先android项目目录下有“assets”文件夹 ...

  2. Android动画例子。

    例子一: 补间动画效果,从右进,从左出. ImageSwitcher mImageSwitcher = new ImageSwitcher(this); mImageSwitcher.setFacto ...

  3. php 7.0 安装以及老版本php删除

    一, 安装php7 php7对php5是99%的兼容, 而且性能更好, 网上很多的优秀的库都对版本有一定的要求, 所以推荐安装php7 低于ubuntu 16.04的系统默认的源不带php7, 所以需 ...

  4. WaterfallFlowLayout瀑布流用重写UICollectionViewFlowLayout类实现

    最近调研瀑布流,在gitHub上下了个Demo发现它的所有视图都是用Main.storyboard拖的, 自己研究半天没研究明白; 然后就又找了一个Demo, 它的视图全是手打的, 但是实现的方法不太 ...

  5. 谈谈Fragment中的onActivityResult

    大家或许有遇到这个神坑,在Fragment中使用startActivityForResult能够成功,可是在Fragment中的onActivityResult却无法被调用.一不注意就让人一夜愁白了头 ...

  6. JNI笔记1

    一.什么是JNI Java Native Interface(JNI)是Java语言的本地编程接口 是 Java 与操作系统本地代码互相调用的功能的接口 二.Java 调用C/C++步骤: 1.在Ja ...

  7. SQL SERVER中什么情况会导致索引查找变成索引扫描

    SQL Server 中什么情况会导致其执行计划从索引查找(Index Seek)变成索引扫描(Index Scan)呢? 下面从几个方面结合上下文具体场景做了下测试.总结.归纳. 1:隐式转换会导致 ...

  8. asp.net mvc 之旅—— 第四站 学会用Reflector调试我们的MVC框架代码

    我们知道,现在能调试.net程序通常有两个,第一个是ILSpy,还是一个是Reflector,这两个小反编译软件算是我们研究底层代码中所拥有的一把 锋利小尖刀~~~,比如你看到的ILSpy这样的界面图 ...

  9. (转载)SQL去除回车符,换行符,空格和水平制表符

    http://www.cnblogs.com/insus/p/4815336.html MS SQL去除回车符,换行符,空格和水平制表符,参考下面语句,一般情况是SQL接受富文本或是textarea的 ...

  10. linux命令详解:md5sum命令

    前言 在网络传输.设备之间转存.复制大文件等时,可能会出现传输前后数据不一致的情况.这种情况在网络这种相对更不稳定的环境中,容易出现.那么校验文件的完整性,也是势在必行的. 使用说明 md5sum命令 ...