装饰器

一、定义

装饰器:顾名思义,就是对某个东西起到装饰修饰的功能。

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基础 (十)装饰器的更多相关文章

  1. Py修行路 python基础 (十二) 协程函数应用 列表生成式 生成器表达式

    一.知识点整理: 1.可迭代的:对象下有_iter_方法的都是可迭代的对象 迭代器:对象._iter_()得到的结果就是迭代器 迭代器的特性: 迭代器._next_() 取下一个值 优点: 1.提供了 ...

  2. Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类

    一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...

  3. Py修行路 python基础 (九)作用域 函数嵌套 闭包

    名称空间与作用域 变量,函数 分成三种 #内置名称空间  内置函数, 系统函数内部自定义的. python查看内置函数,命令: import builtins dir(builtins) #全局名称空 ...

  4. Py修行路 python基础 (十七)property 静态方法 类方法

    一.property 属性 特性 (装饰器是可调用对象,被装饰对象也是可调用对象)   1.在类内函数属性上添加一个@property,就会对函数属性进行伪装. import math class C ...

  5. Py修行路 python基础 (二十五)线程与进程

    操作系统是用户和硬件沟通的桥梁 操作系统,位于底层硬件与应用软件之间的一层 工作方式:向下管理硬件,向上提供接口 操作系统进行切换操作: 把CPU的使用权切换给不同的进程. 1.出现IO操作 2.固定 ...

  6. Py修行路 python基础 (十四)递归 及 面向对象初识及编程思想

    一.递归 1.定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. (1)递归就是在过程或函数里调用自身: (2)在使用递归策略时,必须有一个明确的递归结束条件 ...

  7. Py修行路 python基础 (十六)面向对象编程的 继承 多态与多态性 封装

    一.继承顺序: 多继承情况下,有两种方式:深度优先和广度优先 1.py3/py2 新式类的继承:在查找属性时遵循:广度优先 继承顺序是多条分支,按照从左往右的顺序,进行一步一步查找,一个分支走完会走另 ...

  8. Py修行路 python基础 (十八) 反射 内置attr 包装

    一.isinstance 和 issubclass1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象.2.issubclass(sub, super)检查sub类是否是 ...

  9. Py修行路 python基础 (十九)面向对象进阶(下)

    item系列 __slots__方法 __next__ 和 __iter__实现迭代器  析构函数 上下文管理协议 元类一.item系列 把对象操作属性模拟成字典的格式.  例如:对象名['key'] ...

随机推荐

  1. 5.6 WebDriver API实例讲解(41-50)

    41.操作Web页面的滚动条 (1)滑动页面的滚动条到页面的最下面. (2)滑动页面的滚动条到页面的某个元素. (3)滑动页面的滚动条向下移动某个数量的像素. package apiSample; i ...

  2. tracecaller.cs

    #region Utility #if TRACE private const string Traceformat = "\"{0}\",\"{1:yyyy- ...

  3. 51nod 1406 位运算/dp

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 1406 与查询 题目来源: CodeForces 基准时间限制: ...

  4. DCGAN、WGAN、WGAN-GP、LSGAN、BEGAN原理总结及对比

    DCGAN.WGAN.WGAN-GP.LSGAN.BEGAN原理总结及对比 from:https://blog.csdn.net/qq_25737169/article/details/7885778 ...

  5. 【scala】IO

    1.读文件 可以使用Scala的Source类及其对象来读取文件. Source 类 需要导入 scala.io.Source 然后调用fromFile()方法来读取文件内容 import scala ...

  6. 【河南第十届省赛-D】年终奖金

    题目描述 ***公司承接了N个项目需要年底完成,每个项目有一定的难度系数.由于项目太多了,需要招聘大量的技术人员.要求每个技术人员至少完成K个项目. 考虑到有些项目之间相似性以及项目的难易程度,为了避 ...

  7. 实验二. 使用LoadRunner进行压力测试

    实验二. 使用LoadRunner进行压力测试 一. LoadRunner 概要介绍   1.1简介   LoadRunner 是一种预测系统行为和性能的工业标准级负载测试工具.通过以模拟上千万用户实 ...

  8. LeetCode OJ:Linked List Cycle II(循环链表II)

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...

  9. inline,block,inline-block解析

    display:block就是将元素显示为块级元素. block元素的特点是: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度 <div& ...

  10. Apk大瘦身

    Android的apk文件越来越大了这已经是一个不争的事实.在Android 还是最初版本的时候,一个app的apk文件大小也还只有2 MB左右,到了现在,一个app的apk文件大小已经升级到10MB ...