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'] ...
随机推荐
- Android调用系统相机拍照保存照片很小解决方案
保存图片小的一般操作步骤: 1. 调用系统相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityFo ...
- poj3683 2 -sat输出路径
tarjan缩点,拓扑排序染色输出(貌似挑战上面没有拓扑啊,而且这样写还过了= =) 主要是找s,t,d,三者之间的关系,找出合取范式这题就很容易了 #include<map> #incl ...
- 【scala】匿名函数和闭包
函数的类型和值 Scala是一种纯面向对象的语言,每个值都是对象.Java是一种不全面向对象的语言. Scala也是一种函数式语言,其函数也能当成值来使用.Java则是指令试编程. 但是Scala同时 ...
- 多种方式实现滑动p91--105
1.layout方法 2.offsetLeftAndRight()与offsetTopAndBottom()方法 3.LayoutParams(前提是要有父布局,根据父布局的类型决定LayoutPar ...
- Java8_01_新特性概述
一.前言 二.
- Java并发编程总结
基础概念 1.什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)?原子操作(atomic operation)意为"不可被中断的一个或一 ...
- ffmpeg推送RTSP直播流到EasyDarwin报错问题的修复
在之前的博客<ffmpeg推送,EasyDarwin转发,vlc播放 实现整个RTSP直播>中,我们介绍了如何采用ffmpeg进行RTSP推送,实现EasyDarwin直播分发的功能,近期 ...
- Is possible develop iOS game with Delphi Xe4 ? Pascal
下面的计划: 评估用Delphi XE4来开发游戏的可行性. 以及成本. (代价过大的话 估计还是不会被接受 所以某个角度来说这是个玩具) . 有几个选择, Asphyre 4.0 之后作者lifep ...
- 人生苦短之我用Python篇(深浅拷贝、常用模块、内置函数)
深浅拷贝 有时候,尤其是当你在处理可变对象时,你可能想要复制一个对象,然后对其做出一些改变而不希望影响原来的对象.这就是Python的copy所发挥作用的地方. 定义了当对你的类的实例调用copy.c ...
- everything 全盘文件查找工具及正则表达式的使用
首先需要开启 everything 工具在(字符串)查找时,对正则表达式功能的支持: [菜单栏]⇒ [Search]⇒ 勾选[Enable Regex] ctrl + i:字符大小写敏感/不敏感 1. ...