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'] ...
随机推荐
- python脚本1_给一个半径求圆的面积和周长
#给一个半径,求圆的面积和周长,圆周率3.14 r = int(input('r=')) print('area='+str(3.14*r*r)) print('circumference='+str ...
- react 总结
1.React 里直接修改 this.state 和调用 setState() 修改 state 的值有什么区别? 使用对this.state赋值并没有什么作用,官方提醒,应该把this.state当 ...
- 转: OLAP引擎——Kylin介绍
本文转自:http://blog.csdn.net/yu616568/article/details/48103415 ,如有侵犯,立刻删除. Kylin是ebay开发的一套OLAP系统,与Mond ...
- 【lightoj-1063】Ant Hills(求割点)
求割点模板题 #include <bits/stdc++.h> using namespace std; const int N = 10004; int dfn[N], low[N]; ...
- 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 ...
- 初识Linux(五)--VI/VIM编辑器
我们操作文件,终究离不开编辑文件,对文件内容的编辑,Linux系统下,我们通常使用VI/VIM来编辑文件.VI是每个Linux都会自带的文本编辑器,VIM是VI的增强版,可能有些发行版本没有自带,可以 ...
- Render QGraphicsItem on QPixmap: aggregate 'QWidget w' has incomplete type and cannot be defined
Render QGraphicsItem on QPixmap: aggregate 'QWidget w' has incomplete type and cannot be defined #in ...
- SpringMVC札集(01)——SpringMVC入门完整详细示例(上)
自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onL ...
- android自定义view系列:认识activity结构
标签: android 自定义view activity 开发中虽然我们调用Activity的setContentView(R.layout.activity_main)方法显示View视图,但是vi ...
- 人生苦短之我用Python篇(基础)
Python简介 Python,是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python是纯粹的自由软件, ...