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'] ...
随机推荐
- 如何查看电脑硬盘是gpt分区还是MBR分区
首先我们右键点击 我的电脑 ,然后在弹出的快捷菜单中我们点击 管理,如下图: 然后在 计算机管理 对话框中,我们可以看到在左侧的存储下有一个 磁盘管理,这里我们点击 磁盘管理,如下图: 点击 磁盘管理 ...
- shell基础复习笔记
变量的设置 以等号连接,等号两边不能有空格 变量名首个字符必须是英文,可以使用下划线,不能使用标点符号,不能使用bash里的关键字 可以使用转义字符\将特殊符号(如Enter.$.空格.!等)变成一般 ...
- 条款2:尽量以const enum inline 来替换 #define
这里说的意思其实相当于,宁可以用编译器来替换预处理器 因为使用预处理器可能使得被处理过的东西无法进入符号表,例如 #define MAXLEN 16 这里的MAXLEN并没有进入符号表,这样有编译错误 ...
- NSURLConnection / NSURLSession/ SDWebImage
1. NSURLConnection (iOS9开始被弃用)=========================================== 此类的对象加载一个URL请求对象,通过异步/同步的方 ...
- Java并发编程之CountDownLatch
一.场景描述 在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景 例如:百米赛跑,十名运动员同时起跑,由于速度的快慢,肯定有先到达和后到达的,而终点有个统计成绩的仪器,当所有选手到达终点时 ...
- Near Field Communication (NFC) applications
Near Field Communication (NFC) applications There has been little practical guidance available on NF ...
- Java虚拟机运行时数据区域划分
Java虚拟机数据运行时区域 方法区(Method Area) 存储加载的类信息,常量,静态变量,编译器编译后的代码等数据.虽然JVM规范把方法区描述为堆的一个逻辑部分,但它却有一个别名叫做N ...
- 《Ubuntu入门基础》第三篇
创建虚拟磁盘
- centOS 7 tomcat nginx 验证码乱码
将服务部署在centOS 7上,配置完tomcat和nginx之后,启动服务后,发现验证码这样了~~~ 一开始是以为nginx的原因,但是在Ubuntu系统相同操作发现没有问题,后发现,系统的字体库中 ...
- del语句
5.2. del 语句 有个方法可以从列表中按给定的索引而不是值来删除一个子项: del 语句.它不同于有返回值的 pop() 方法.语句 del 还可以从列表中删除切片或清空整个列表(我们以前介绍过 ...