首页 > 编程语言 > 详细

python装饰器

时间:2019-04-03 22:09:41      阅读:142      评论:0      收藏:0      [点我收藏+]

python装饰器

 


一 什么是装饰器

器指函数
装饰即修饰,意指为其他函数添加新功能
装饰器定义:本质就是函数,功能是为其他函数添加新功能

 

 

二 装饰器需要遵循的原则

1.不能修改被修饰函数的源代码
2.不能修改被修饰函数的调用方式

 

现在有下面一个函数,如果我们要为这个函数添加一个功能:测试程序的运行时间。

import time
list=[1,2,3,4,5]
def cal(list):
    for i in list:
        time.sleep(0.5)
        print(i)
cal(list)

 

import time
list=[1,2,3,4,5]
def cal(list):
    start_time=time.time()
    for i in list:
        time.sleep(0.5)
        print(i)
    stop_time=time.time()
    print("运行时间:%s" %(stop_time-start_time))

cal(list)
技术分享图片
1
2
3
4
5
运行时间:2.502134323120117
运行结果

总结:我们虽然实现了功能,但是我们要知道两大原则,现在我们直接修改函数的源代码,这样做是不行的。

 

三 实现装饰器知识储备

装饰器=高阶函数+函数嵌套+闭包

 

四 高阶函数

高阶函数定义:
1.函数接收的参数是一个函数名

2.函数的返回值是一个函数名

3.满足上述条件任意一个,都可称之为高阶函数

技术分享图片
def foo():
    print(我的函数名作为参数传给高阶函数)
def gao_jie1(func):
    print(我就是高阶函数1,我接收的参数名是%s %func)
    func()

def gao_jie2(func):
    print(我就是高阶函数2,我的返回值是%s %func)
    return func

gao_jie1(foo)
gao_jie2(foo)
高阶函数示例

只满足一个条件:函数接收的参数是一个函数名

技术分享图片
import time
def foo():
    print(from the foo)

def timmer(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print(函数%s 运行时间是%s %(func,stop_time-start_time))
timmer(foo)
#总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
View Code

满足两个条件

1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名

技术分享图片
import time
def foo():
    print(from the foo)

def timmer(func):
    start_time=time.time()
    return func
    stop_time=time.time()
    print(函数%s 运行时间是%s %(func,stop_time-start_time))
foo=timmer(foo)
foo()
#总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
View Code

高阶函数总结
1.函数接收的参数是一个函数名
  作用:在不修改函数源代码的前提下,为函数添加新功能,
  不足:会改变函数的调用方式
2.函数的返回值是一个函数名
  作用:不修改函数的调用方式
  不足:不能添加新功能

 

 

五 函数嵌套

def father(name):
    print(from father %s %name)
    def son():
        print(from son)
        def grandson():
            print(from grandson)
        grandson()
    son()

father(‘aaa)

 

 

六 闭包

闭包:闭包是指内部函数调用外部函数的变量
包是指嵌套,闭是指封装
def test1():
	a=1
	def test2():
		print(a)
	test2()
test1()

  

七 无参装饰器

无参装饰器=高级函数+函数嵌套

基本框架

1 #这就是一个实现一个装饰器最基本的架子
2 def timer(func):
3     def wrapper():
4         func()
5     return wrapper

 

加上参数

解决被修饰的函数是有参数的。

 

1 def timer(func):
2     def wrapper(*args,**kwargs):
3         func(*args,**kwargs)
4     return wrapper
技术分享图片
import time
def timmer(func):#func=test
    def wrapper(name,age):
        start_time = time.time()
        res=func(name,age)  # 就是在运行test()
        stop_time = time.time()
        print("函数运行时间的是%s" % (stop_time - start_time))
        return res
    return wrapper
# @timmer 等效于 test=timmer(test)
@timmer
def test(name,age):
    time.sleep(3)
    print(test函数运行完毕)
    return "这是test的返回值"
res=test("lingling",20)
print(res)


@timmer
# @timmer 等效于 test1=timmer(test1)
def test1(name,age,gender):
    time.sleep(3)
    print(test函数运行完毕)
    return "这是test1的返回值"
res=test1("lingling",20)
print(res)
#@timmer 等效于 test=timmer(test),#在这里一定要注意,我们首先把test函数传入到timmer装饰器,我们下一步返回了wrapper函数的地址(return wrapper)。
#test变量接收到wrapper函数的地址
#test("lingling",20)传入参数,执行wrapper函数,这里test函数有参数,为name,age,所以wrapper函数也应该有两个变量name,age,而执行wrapper函数,实际是要执行test函数,此处也需要两个参数,name,age
#res变量接收到test函数执行的结果



# 1.将test函数传入timmer:timmer(test)
# 2.执行timmer函数,返回wrapper函数地址(return wrapper)
# 3.执行wrapper函数(执行wrapper函数实则是执行test函数),并接收test函数返回值:res=test("lingling",20)
参数个数不同
技术分享图片
import time
def timmer(func):#func=test
    def wrapper(*wargs,**kwargs):
        start_time = time.time()
        res=func(*wargs,**kwargs)  # 就是在运行test()
        stop_time = time.time()
        print("函数运行时间的是%s" % (stop_time - start_time))
        return res
    return wrapper

@timmer
def test(name,age):
    time.sleep(3)
    print(test函数运行完毕)
    return "这是test的返回值"
res=test("lingling",age=20)
print(res)


@timmer
def test1(name,age,gender):
    time.sleep(3)
    print(test1函数运行完毕)
    return "这是test1的返回值"
res=test1("lingling",20,male)
print(res)

#解决wrapper不固定接收参数的问题
#如果细心可能会想,这里我们把wrapper参数写死了,你只能传入两个参数,如果有不同的函数需要这个装饰器,那我们不得重新修改装饰器,这真是一个大问题,我们来解决这个问题
#所以我们在wrapper函数中应该接收到test函数的所有参数:*wargs,**kwargs
# *wargs:接收所有位置参数
# **kwargs:接收键值对类型的参数
#我们将wrapper函数与内部func函数的参数设置*wargs,**kwargs就可以接收所有传进来的参数

#第二个问题,func接收参数

# 使用*wargs,**kwargs怎么接收参数
# 就使用*wargs,**kwargs怎么传递参数
# 我们可以把*wargs,**kwargs看成一个整体,接收所有的参数
解决接收不同个数的参数
技术分享图片
def test2(name,age,gender): #test2(*(‘alex‘,18,‘male‘),**{})
    print(name)
    print(age)
    print(gender)
    
def test1(*args,**kwargs):
    test2(*args,**kwargs) #args=(‘alex‘,18,‘male‘)  kwargs={}
test1(alex,18,male)


def test3(*args,**kwargs):
    print(args)
    print(kwargs)
#
test3(1,2,3,4,name="linlin")
test3(*(1,2,3,4),**{name:linlin})
args与kwargs的补充

 

加上功能

在装饰器的框架基础上添加被测试函数所需要的功能。
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print(函数[%s],运行时间是[%s] %(func,stop_time-start_time))
    return wrapper
import time
def timmer(func):#func=test
    def wrapper():
        start_time = time.time()
        func()  # 就是在运行test()
        stop_time = time.time()
        print("函数运行时间的是%s" % (stop_time - start_time))
    return wrapper
# @timmer 等效于 test=timmer(test)
@timmer
def test():
    time.sleep(3)
    print(test函数运行完毕)
test()
技术分享图片
import time
def timmer(func):#func=test
    def wrapper():
        start_time = time.time()
        func()  # 就是在运行test()
        stop_time = time.time()
        print("函数运行时间的是%s" % (stop_time - start_time))
    return wrapper


def test():
    time.sleep(3)
    print(test函数运行完毕)
test=timmer(test)#返回的是wrapper的地址
test()#执行的是wrapper()
原型

 

加上返回值

解决在测试程序里有返回值的情况。
import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(函数[%s],运行时间是[%s] %(func,stop_time-start_time))
        return res
    return wrapper
import time
def timmer(func):#func=test
    def wrapper():
        start_time = time.time()
        res=func()  # 就是在运行test()
        stop_time = time.time()
        print("函数运行时间的是%s" % (stop_time - start_time))
        return res
    return wrapper
# @timmer 等效于 test=timmer(test)
@timmer
def test():
    time.sleep(3)
    print(test函数运行完毕)
    return "这是test的返回值"
res=test()
print(res)

 

语法糖@

如果我们需要使用装饰器,只需要在被测试的函数前加上@装饰器函数名
@timmer 等效于 test=timmer(test)
@timer  #@timer就等同于cal=timer(cal)
def cal(array):
    res=0
    for i in array:
        res+=i
    return res

cal(range(10))

 

博文:https://www.cnblogs.com/linhaifeng/articles/6140395.html

python装饰器

原文:https://www.cnblogs.com/-wenli/p/10651819.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!