python基础-装饰器
一、什么是装饰器
装饰器本质就是函数,功能是为其他函数附加功能
二、装饰器遵循的原则
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基础-装饰器的更多相关文章
- python基础——装饰器
python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...
- python基础—装饰器
python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...
- python 基础——装饰器
python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...
- day5学python 基础+装饰器内容
基础+装饰器内容 递归特性# 1.必须有一个明确的结束条件# 2.每次进入更深一层递归时,问题规模相比上次递归应有所减少# 3.递归效率不高 def run(n): print(n) if int(n ...
- Python自动化 【第四篇】:Python基础-装饰器 生成器 迭代器 Json & pickle
目录: 装饰器 生成器 迭代器 Json & pickle 数据序列化 软件目录结构规范 1. Python装饰器 装饰器:本质是函数,(功能是装饰其它函数)就是为其他函数添加附加功能 原则: ...
- python基础 (装饰器,内置函数)
https://docs.python.org/zh-cn/3.7/library/functions.html 1.闭包回顾 在学习装饰器之前,可以先复习一下什么是闭包? 在嵌套函数内部的函数可以使 ...
- python基础-装饰器,生成器和迭代器
学习内容 1.装饰器 2.生成器 3.迭代器 4.软件目录结构规范 一:装饰器(decorator) 1.装饰器定义:本质就是函数,用来装饰其他函数,即为其他函数添加附加功能. 2.装饰器原则:1)不 ...
- python基础===装饰器@property 的扩展
以下来自Python 3.6.0 Document: class property(fget=None, fset=None, fdel=None, doc=None) Return a proper ...
- <Python基础>装饰器的基本原理
1.装饰器 所谓装饰器一般是对已经使用(上线)的函数增加功能. 但是因为一般的大公司的严格按照开放封闭原则(对扩展是开放的,对修改是封闭的),不会让你修改原本的函数. 装饰器就是在不改变原本的函数且不 ...
随机推荐
- linux文件目录详解
文件系统的是用来组织和排列文件存取的,所以她是可见的,在Linux中,我们可以通过ls等工具来查看其结构,在Linux系统中,我们见到 的都是树形结构:比如操作系统安装在一个文件系统中,他表现为由/起 ...
- docker中建立私有git服务器[gitlab]
现在使用git的很普遍,在开发内部如何建立个git服务器,本文以gitlab为例,让你分分钟就可以搭好一个环境[docker的威力非同一般] 首先在docker.com找到gitlab的下载源和信息, ...
- GCD封装的个人理解和应用
GCD封装的个人理解和应用 特点 >>将GCD封装,使我们从繁琐的方法记忆中解脱出来,能够直接快速的应用. 使用方法 1.将工程中的GCD文件中的9个文件拖入自己的工程中(你自己最好建一个 ...
- Android开发学习——Android项目的目录结构
Android项目的目录结构: 资源文件夹: 清单配置文件: Android的四大组件在使用前全部需要在清单文件中配置 <?xml version="1.0" encodin ...
- 自定义控件之圆形的image
需要添加点击事件的的时候在自定义的控件中覆写OnTouchEvent():方法进行点击事件的分发 package com.example.administrator.mvp.ui.widget; im ...
- iOS Swift-注释与分号
iOS Swift-注释与分号 注释 注释是每门语言都存在的一种解释方式,Swift的注释与C语言的注释非常相似,单行注释采用//. //这是一个注释 在Swift中也可以使用多行注释,起始标记使用( ...
- 敏捷开发与jira
项目背景 项目是基于一套公司自主研发的平台做企业信息化的项目管理业务,经过两个里程碑的交付,已经在客户现场使用,每次版本都能按期交付,延迟较少,客户满意度也高. 项目开发过程采用的敏捷的方法,用类Sc ...
- Cannot execute as the database principal because the principal "guest" does not exist, this type of principal cannot be impersonated, or you do not have permission.
今天遇到这样一个问题:一个系统的作业需要给系统Support人员开放SQL Agent下作业的查看.执行权限.数据库版本为SQL Server 2014 SP2,给这个系统Support人员的NT账号 ...
- 从零自学Hadoop(01):认识Hadoop
本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 阅读目录 序 Hadoop 项目起源 优点 核心 ...
- SQL Like模糊查询一些小知识
模糊查询: where mc like '值':返回值等同于where mc ='值' where mc like '%值':匹配 名称是 '*值'(以“值”作为结尾)的所有数据,*表示任何值任何长度 ...