python基础—函数装饰器

1、什么是装饰器

装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。

装饰器的返回值是也是一个函数对象。

装饰器经常用于有切面需求的场景,比如:插入日志,性能测试,事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

为什么要用装饰器及开放封闭原则

函数的源代码和调用方式一般不修改,但是还需要扩展功能的话就需要在需要扩展的函数的开始使用装饰器。举例:带眼镜

装饰器是任意可调用的对象,本质就是函数

装饰器在python中使用如此方便归因于python的函数能像普通的对象一样能作为参数传递给其他函数,可以被复制给其他变量,可以作为返回值,可以被定义在另一个函数内。

2、 简单的装饰器

import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print("run time is %s "%(stop_time-start_time))
return wrapper
@timmer #等同于 index=timmer(index) , 此后index等同于 wrapper
def index():
time.sleep(1)
print("welcom ! wen")
index()

输出结果:

welcom ! wen
run time is 1.0001096725463867

函数timmer就是装饰器,它把执行真正业务方法的func包裹在函数里面,看起来像index被timmer装饰了。

在这个例子中,函数进入和退出时,被称为一个横切面(Aspet),这种编程方式被称为面向切面的编程(Aspet-Oriented Programming)

@符号是装饰器的语法糖,在定义函数的时候,避免再一次赋值操作。

3、装饰器的语法

@timmer

timmer就是一个装饰器

@timmer等同于 被装饰函数名=timmer(被装饰函数名)   被装饰器函数就是紧接@timmer下面的函数

4、无参装饰器

如果多个函数拥有不同的参数形式,怎么共用同样的装饰器?

在Python中,函数可以支持(*args, **kwargs)可变参数,所以装饰器可以通过可变参数形式来实现内嵌函数的签名。

无参装饰器,被装饰函数带参,无返回值

import time
def timmer(func):
def wrapper(*args,**kwargs):
print(func)
return wrapper
@timmer
def index():
time.sleep(1)
print("welcom ! wen")
index()

输出结果:

<function index at 0x000000D132F5AF28>

多个函数共用一个装饰器:

import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs)
stop_time=time.time()
print("run time is: %s" %(stop_time-start_time))
return wrapper
@timmer
def home(name):
time.sleep(1)
print(" %s home"%name)
@timmer
def auth(name,password):
time.sleep(1)
print(name,password)
@timmer
def tell():
time.sleep(1)
print("------------------")
home("wenyanjie")
auth("wen","1234")
tell()
输出结果为:
wenyanjie home
run time is: 1.0002663135528564
wen 1234
run time is: 1.0000183582305908
------------------
run time is: 1.0009756088256836

  

无参装饰器,被装饰函数带参,且有返回值

import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print("run time is: %s" %(stop_time-start_time))
return res
return wrapper @timmer
def home(name):
time.sleep(1)
print(" %s home"%name)
@timmer
def auth(name,password):
time.sleep(1)
print(name,password)
@timmer
def tell():
time.sleep(1)
print("------------------")
@timmer
def my_max(x,y):
return x if x > y else y home("wenyanjie")
auth("wen","1234")
tell()
res=my_max(1,2)
print("----->",res)

输出结果:

 wenyanjie  home
run time is: 1.0004072189331055
wen 1234
run time is: 1.0009665489196777
------------------
run time is: 1.0001206398010254
run time is: 0.0
-----> 2

  

5、有参装饰器 

装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@timmer,该装饰器唯一的参数是执行业务的函数。装饰器的语法允许我们在调用时,提供其他参数。

def auth2(auth_type):
def auth(func):
def wrapper(*args,**kwargs):
if auth_type == "file":
name=input("username:")
password=input("password")
if name=="wen" and password =="123":
print("login successful!")
res=func(*args,**kwargs)
return res
else:
print("auth error")
elif auth_type == "sql":
print("sql no learn.....")
return wrapper
return auth @auth2(auth_type="file")
def login(name):
print("this is %s index page"%name)
return 1
flag=login("wenyanjie")
print(flag)

输出结果:

username:wen
password123
login successful!
this is wenyanjie index page
1

上面例子中的auth2是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将他理解为一个含有参数的闭包。当我们使用@auth2(auth_type=”file”)调用的时候,python能够发现这一层的封装,并把参数传递到装饰器的环境中。

上面有参装饰器的执行步骤分解:

6、多个装饰器

装饰器是可以叠加的,那么这就涉及装饰器调用顺序。对于python中的“@”语法糖,装饰器的调用顺序与使用@语法糖的顺序相反。

多个无参装饰器

@ccc
@bbb
@aaa
def func():
pass

#相当与

func=aaa(func)
func=bbb(func)
func=ccc(func)

#相当与

func=ccc(bbb(aaa(func)))

有参装饰器多个

@ccc('c')
@bbb('b')
@aaa('c')
def func():
pass

#相当与

func=aaa('a')(func)
func=bbb('b')(func)
func=ccc('c')(func)

#相当与

func=ccc('c')(bbb('b')(aaa('a')(func)))

  

案例:

import time
current_login={'name':None,'login':False}
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print("run time is %s"%(stop_time-start_time))
return res
return wrapper
def auth2(auth_type):
def auth(func):
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=="wen" and password =="123":
print("login successful!")
current_login['name']=name
current_login['login']=password
res=func(*args,**kwargs)
return res
else:
print("auth error")
elif auth_type == "sql":
print("sql no learn.....")
return wrapper
return auth
@timmer
@auth2(auth_type="file")
def login(name):
print("this is %s index page"%name)
login("wenyanjie")
login("wenyanjie")

输出结果:

username:wen
Password:123
login successful!
this is wenyanjie index page
run time is 3.228583812713623
this is wenyanjie index page
run time is 0.0

 

7  eval方法:往文件中放有结构的数据 

 

 

8 被装饰函数将所有注释等自己的定义都传给装饰器 

import time
from functools import wraps
def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs):
"wrapper function"
print(func)
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print("run time is %s "%(stop_time-start_time))
return res
return wrapper
@timmer
def my_max(x,y):
"my_max function"
a=x if x>y else y
return a
print(help(my_max))

输出结果:

my_max(x, y)
my_max function

python基础—函数装饰器的更多相关文章

  1. python基础-----函数/装饰器

    函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...

  2. 十. Python基础(10)--装饰器

    十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...

  3. Day11 Python基础之装饰器(高级函数)(九)

    在python中,装饰器.生成器和迭代器是特别重要的高级函数   https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...

  4. python语法基础-函数-装饰器-长期维护

    ######################################################### # 装饰器 # 装饰器非常重要,面试Python的公司必问, # 原则:开放封闭原则 ...

  5. [python基础]关于装饰器

    在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...

  6. python 复习函数 装饰器

    # 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...

  7. Decorator——Python初级函数装饰器

    最近想整一整数据分析,在看一本关于数据分析的书中提到了(1)if __name__ == '__main__' (2)列表解析式 (3)装饰器. 先简单描述一下前两点,再详细解说Python初级的函数 ...

  8. 1.16 Python基础知识 - 装饰器初识

    Python中的装饰器就是函数,作用就是包装其他函数,为他们起到修饰作用.在不修改源代码的情况下,为这些函数额外添加一些功能,像日志记录,性能测试等.一个函数可以使用多个装饰器,产生的结果与装饰器的位 ...

  9. python基础之 装饰器,内置函数

    1.闭包回顾 在学习装饰器之前,可以先复习一下什么是闭包? 在嵌套函数内部的函数可以使用外部变量(非全局变量)叫做闭包! def wrapper(): money =10 def inner(num) ...

随机推荐

  1. python全栈开发-Day7 文件处理

    python全栈开发-Day7   文件处理 一 .文件操作 一 .介绍 计算机系统分为:计算机硬件,操作系统,应用程序三部分. 我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必 ...

  2. MySql (MariaDB)的varchar字段的存储的是字符还是字节

    关于varchar字段: 在version4之前,按字节: version5之后,按字符. 现在普遍都按字符算:无论中文英文,都算一个字符 既: varchar(10) == '123456789a' ...

  3. 面试题中遇到的算法与js技巧

    近一周在忙着面试,本月第一次更博,甚是想念. 基本上大公司都会要求一些算法或者数据结构类的东西,这方面自己还不是很精通,只能一步一个脚印来积累了. 1.查询字符串获取对象数据,可自行根据需求选择格式, ...

  4. SpringBoot03 项目热部署

    1 问题 在编写springBoot项目时,经常需要修改代码:但是每次修改代码后都需重新启动,修改的代码才会生效 2 这么实现IDEA能够像Eclipse那样保存过后就可以自动进行刷新呢 将sprin ...

  5. python 面向对象的程序设计

    一:什么是编程范式? 编程是程序员用特定的语法 + 数据结构 + 算法组成的代码来告诉计算机如何执行任务的过程. 如果把编程的过程比喻为练习武功,那么编程范式指的就是武林中的各种流派,而在编程的世界里 ...

  6. python全栈开发-Day12 三元表达式、函数递归、匿名函数、内置函数

    一. 三元表达式 一 .三元表达式 仅应用于: 1.条件成立返回,一个值 2.条件不成立返回 ,一个值 def max2(x,y): #普通函数定义 if x > y: return x els ...

  7. 通过运行一个tomcat容器来记录下初学docker常用的几个命令---容器篇

    1.查看容器列表 显示正在运行的容器: [root@localhost HMK]# docker ps 显示所有容器,包括未运行的: [root@localhost HMK]# docker ps - ...

  8. 如何查看与更改python的工作目录?

    在编写<机器学习实战>第二章kNN代码时遇到问题,即在自己编写好模块后,使用ipython进行import时,出现以下错误: 可知若想找到该模块,需将工作目录改变到当前文件(模块py文件) ...

  9. Python 实现双端队列 Deque

    操作 Deque() 创建一个空的双端队列 add_front(item) 从队头加入一个item元素 add_rear(item) 从队尾加入一个item元素 remove_front() 从队头删 ...

  10. Session的过期时间如何计算?

    在生成session的时候,会设置一个session过期时间.session的过期时间并不是从生成session对象开始计算,超过过期时间,session就失效了. 而是每当一个浏览器请求,sessi ...