Py修行路 python基础 (十)装饰器
装饰器
一、定义
装饰器:顾名思义,就是对某个东西起到装饰修饰的功能。
python中的装饰器,其本质上就是一个python函数,它可以让其他函数在不需要任何代码变动的前提下增加额外功能。通俗理解就是 函数 闭包 的实用。
二、语法及注意事项
1、书写规范 @ *** ***指装饰器的函数名
2、装饰器作为一个函数,他会把其下一行的主函数名作为变量,传递到自己的函数去调用。再重新赋值主函数。
3、装饰器必须放到被装饰的函数上边,并且独占一行;多个装饰器下 ,按照先下后上执行。
三、为什么要用装饰器?
开放封闭原则
源代码上线之后,主函数的定义和调用方式尽量避免更改。装饰器本身在源代码中就是可调用的对象。
四、装饰器使用举例
原函数如下:
import time
def index():
time.sleep(3)
print("welcome to oldboy")
index()
执行结果:
welcome to oldboy
在原函数不被更改的情况下,增加新的功能:计算主函数执行的时间!
1、最原始的无参装饰器(无位置参数)。
import time def timer(func):
def wrapper():
start_time=time.time()
func()
stop_time = time.time()
print("running time:%s"%(stop_time-start_time))
return wrapper
@timer
def index():
time.sleep(3)
print("welcome to oldboy")
index()

执行结果:
welcome to oldboy
running time:3.000171422958374
2、无参装饰器(有位置参数)
#为定义可以传值的函数,添加计时的装饰器,此时要注意函数和装饰器中的位置参数传值的问题!!!
import time def timer(func):
def wrapper(*args,**kwargs): #有权接管,无权为空!
start_time = time.time()
func(*args,**kwargs) #home(name)
stop_time = time.time()
print("run time is %s"%(stop_time-start_time))
return wrapper @timer #index = timer(index)
def index():
time.sleep(1.5)
print("welcome to beijing!") @timer
def home(name): #wrapper('alex')
time.sleep(1)
print("welcome to %s home page"%name) @timer
def auth(name,passwd):
time.sleep(0.5)
print(name,passwd) @timer
def tell():
print("---***---") index()
home("alex")
auth("alex","alex3714")
tell()
执行结果如下:
welcome to beijing!
run time is 1.5000858306884766
welcome to alex home page
run time is 1.0000569820404053
alex alex3714
run time is 0.5010290145874023
---***---
run time is 0.0
3、无参装饰器(主函数带有返回值的情况!)
#给带有返回值的函数添加统计时间的装饰器! import time def timer(func):
def wrapper(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs) #my_max(1,2)
stop_time = time.time()
print("run time is %s"%(stop_time-start_time))
return res #先将所有的功能接收出来,然后在返回
return wrapper @timer
def my_max(x,y):
time.sleep(2)
print("max:")
res = x if x>y else y
return res #函数的返回值!
res = my_max(1,2) # res = wrapper(1,2)
print(res)
执行结果如下:
max:
run time is 2.0001144409179688
2
4、装饰器的实质既然是函数的调用,那么上面介绍完无参的情况,现在举例介绍有参的情况。
有参装饰器(登陆认证)
#为主函数添加认证功能。主函数不变,在主函数上@*** 一个装饰器,装饰器是靠函数来实现。
#认证功能是在真正的函数调用之前添加上认证的功能,所以认证是在装饰器中添加。
#有参装饰器是在装饰器上添加区分,认证的时候,需要区分不同类型信息的来源(如:本地文件,数据库),
#所以在装饰器上就需要添加认证参数,以区分开认证的来源,执行认证的时候,会在认证主函数中进行逻辑操作。
def auth2(auth_type): #参数认证函数
def auth(func):
def wrapper(*args,**kwargs): #认证函数
if auth_type == "file":
name = input("username:")
passwd = input("passwd:")
if name == "song" and passwd =="":
print("auth successful")
res = func(*args,**kwargs)
return res #认证成功之后源代码再运行。
else:
print("auth error")
elif auth_type == "sql":
print("不会!")
return wrapper
return auth #@auth2(auth_type="sql") #调用 不同认证类型的参数
#def index(): #index = auth(index)
# print("welcome to index page") @auth2(auth_type="file") #调用 不同认证类型的参数
def my_index():
print("welcome to inexd page")
#index()
my_index()
执行结果如下:
username:song
passwd123
auth successful
welcome to inexd page
5、多个装饰器调用!实现主函数的登录认证功能
#多个装饰器调用!
#1、加上了统计函数的执行时间
#2、加上了认证功能,为避免重复登录认证,执行功能完成之后再判断登录状态。已登录则跳过,第一次登录会有登录信息的认证。 import time
current_login={'name':None,'login':False} def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs) #my_max(1,2)
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return res
return wrapper def auth2(auth_type='file'):
def auth(func):
# print(auth_type)
def wrapper(*args,**kwargs):
if current_login['name'] and current_login['login']:
res=func(*args,**kwargs)
return res
if auth_type == 'file':
name=input('username: ')
password=input('password: ')
if name == 'zhejiangF4' and password == 'sb945':
print('auth successfull')
res=func(*args,**kwargs)
current_login['name']=name
current_login['login']=True
return res
else:
print('auth error')
elif auth_type == 'sql':
print('还他妈不会玩')
return wrapper
return auth @timmer
@auth2(auth_type='file') #@auth #index=auth(index)
def index():
print('welcome to inex page') @auth2()
def home():
print('welcome to home page') #调用阶段
index()
home()
执行结果如下:
username: zhejiangF4
password: sb945
auth successfull
welcome to inex page
run time is 10.760615348815918
welcome to home page
Py修行路 python基础 (十)装饰器的更多相关文章
- Py修行路 python基础 (十二) 协程函数应用 列表生成式 生成器表达式
一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._next_() 取下一个值 优点: 1.提供了 ...
- Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类
一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...
- Py修行路 python基础 (九)作用域 函数嵌套 闭包
名称空间与作用域 变量,函数 分成三种 #内置名称空间 内置函数, 系统函数内部自定义的. python查看内置函数,命令: import builtins dir(builtins) #全局名称空 ...
- Py修行路 python基础 (十七)property 静态方法 类方法
一.property 属性 特性 (装饰器是可调用对象,被装饰对象也是可调用对象) 1.在类内函数属性上添加一个@property,就会对函数属性进行伪装. import math class C ...
- Py修行路 python基础 (二十五)线程与进程
操作系统是用户和硬件沟通的桥梁 操作系统,位于底层硬件与应用软件之间的一层 工作方式:向下管理硬件,向上提供接口 操作系统进行切换操作: 把CPU的使用权切换给不同的进程. 1.出现IO操作 2.固定 ...
- Py修行路 python基础 (十四)递归 及 面向对象初识及编程思想
一.递归 1.定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. (1)递归就是在过程或函数里调用自身: (2)在使用递归策略时,必须有一个明确的递归结束条件 ...
- Py修行路 python基础 (十六)面向对象编程的 继承 多态与多态性 封装
一.继承顺序: 多继承情况下,有两种方式:深度优先和广度优先 1.py3/py2 新式类的继承:在查找属性时遵循:广度优先 继承顺序是多条分支,按照从左往右的顺序,进行一步一步查找,一个分支走完会走另 ...
- Py修行路 python基础 (十八) 反射 内置attr 包装
一.isinstance 和 issubclass1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象.2.issubclass(sub, super)检查sub类是否是 ...
- Py修行路 python基础 (十九)面向对象进阶(下)
item系列 __slots__方法 __next__ 和 __iter__实现迭代器 析构函数 上下文管理协议 元类一.item系列 把对象操作属性模拟成字典的格式. 例如:对象名['key'] ...
随机推荐
- linux中的kill命令
一. 定义 kill命令用来删除执行中的程序或工作.kill可将指定的信息送至程序.预设的信息为SIGTERM(15),可将指定程序终止.若仍无法终止该程序,可使用SIGKILL(9)信息尝试强制删除 ...
- Easyui 行编辑
之前没用过,突然用了的时候手忙脚乱的感觉 找了官方文档也好 百度了一大堆东西 表示个人脑袋跟不上思路 直接铺上简化的 以后自己 找起来也方便 以下代码已经执行 应该不会再错了 <tab ...
- 011-对象——interface接口说明与使用方式实例
<?php /** interface接口说明与使用方式实例 * * 接口里面的方法全是抽象方法,没有实体的方法.这样的类我们就叫做接口.定义的时候用Interface定义.实现接口时用impl ...
- 慕课网:4-2—— 使用DB facade实现CURD (09:11)
public function test1() { //新增数据: /* $bool=DB::insert('insert into student(name,age) VALUES (?,?)', ...
- deep learning新征程(二)
deep learning新征程(二) zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2016-4-5 声明 1)该Dee ...
- Ubuntu的root用户问题
在Ubuntu中系统是默认禁止root用户登入操作,要使用超级用户可以加sudo 例: sudo chown book:book /work -R 或者切换到root su root passwor ...
- Lua基础---流程控制语句
Lua提供了if语句和if else语句作为流程控制语句,当然,符合C的特点,流程语句之间可以实现嵌套操作,当然流程控制也可以和循环体结合进行控制. 1.if语句 if(布尔表达式) then --[ ...
- Arcgis for Androd API开发系列教程(一)——地图显示与GPS定位
序:最近呢,工作鸭梨不是怎么大,对于自己爱折腾的想法又冒出了水面,开始自己的android开发的学习之旅.但是呢,本人是做GIS的,所以呢,就打算从这方面入手看看,是不是有什么比较好玩的玩意呢,这才导 ...
- Golang使用MongoDB通用操作
MongoDB是Nosql中常用的一种数据库,今天笔者就简单总结一下Golang如何使用这些通用的供能的,不喜勿喷... 研究的事例结构如下: type LikeBest struct { Autho ...
- Linux paste 命令
Linux paste命令用于合并文件的列. paste指令会把每个文件以列对列的方式,一列列地加以合并. 语法 paste [-s][-d <间隔字符>][--help][--versi ...