python~装饰器

1、函数即变量,调用f() ,也可以写a = f,a() = f()

  函数也可以作为参数,也可以作为返回值

2、高阶函数  

  以函数作为参数,或者返回值是参数的函数

3、函数嵌套

函数里面定义函数

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

 

1、python装饰器~高阶函数

 1 import  time
 2 def bar():
 3     time.sleep(3)
 4     print('in the bar')
 5 def test1(func):
 6     print(func)   #打印这个func的内存地址
 7     return  func  #把函数的返回值返回 
 8 #test1(bar)  #把bar传给func 相当于func = bar,把上面的bar函数传进来
 9 print(test1(bar)) #打印一下才能看到它的返回值 调用test1函数,bar这个函数传进来了,bar传给func了, 然后func函数里打印(func) 就出来第一个内存地址 完了结束后retuan返回,相当于返回了test1(bar)的运行结果
10 test1(bar)#output bar的内存地址

 



进一步说明调用规则

 1 import  time
 2 def bar():
 3     time.sleep(3)
 4     print('in the bar')
 5 def test1(func):
 6     print(func)   #打印这个func的内存地址
 7     return  func  #把函数的返回值返回
 8 t =(test1(bar))
 9 #print (t)  #test1(bar)传进来,立马打印bar的函数地址,又return就把bar内存地址返回回来给t,又把t输出出来
10 #t() #run bar
11 bar = test1((bar)) #把之前的bar覆盖掉  这个换个写法
12 bar()  #run bar 

 

 

2、python嵌套函数

 

3、装饰器案例详解

 1 import time
 2 def deco(func):
 3     start_time=time.time()
 4     func() #相当于执行一次func函数,意思是执行test1和test2函数,然后打印相应函数里print出来的数值
 5     stop_time=time.time()
 6     print("the func run time is %s"%(start_time-stop_time))
 7 def test1():
 8     time.sleep(3)
 9     print('in the test1')
10 def test2():
11     time.sleep(3)
12     print('in the test2')
13 deco(test1) #如果加括号是把test1运行结果和返回值传递给deco函数,
14 deco(test2)
统计两个函数中间花费的时间

改进; 引入@ 好难懂

 1 import  time
 2 def timer(func):  #timer(test1 ) 内存地址传给,test1没加括号,所以是内存地址
 3     def deco():
 4         start_time=time.time()
 5         func()  #这样就直接返回内存地址 但,return后的不会继续运行
 6         stop_time =time.time()
 7         print("the func run time is %s"%(start_time - stop_time))
 8     return deco #返回函数的内存地址 所以把这个内存地址打印出来
 9 @timer  # 相当于 test1 = timer(test1)
10 def test1():
11     time.sleep(3)
12     print('in the test1')
13 test1() #执行这个实际是执行deco


有一些函数,如test1不需要 arg参数,而test2就需要args(不输入args 会报错) 
1
import time 2 def timer(func): #timer(test1 ) 内存地址传给,test1没加括号,所以是内存地址 3 def deco(arg1): 4 start_time=time.time() 5 func(arg1) #这样就直接返回内存地址 但,return后的不会继续运行 6 stop_time =time.time() 7 print("the func run time is %s"%(start_time - stop_time)) 8 return deco #返回函数的内存地址 所以把这个内存地址打印出来 9 #@timer # 相当于 test1 = timer(test1) 10 def test1(): 11 time.sleep(3) 12 print('in the test1') 13 14 @timer # = test2 = timer(test2) = deco test2() = deco() 15 def test2(name): 16 print("test2:",name) 17 18 #test1() #执行这个实际是执行deco 19 test2("li")
引用
 1 import  time
 2 def timer(func):  #timer(test1 ) 内存地址传给,test1没加括号,所以是内存地址
 3     def deco(*args,**kwargs): #所以就引用了非固定参数
 4         start_time=time.time()
 5         func(*args,**kwargs)  #这样就直接返回内存地址 但,return后的不会继续运行
 6         stop_time =time.time()
 7         print("the func run time is %s"%(start_time - stop_time))
 8     return deco #返回函数的内存地址 所以把这个内存地址打印出来
 9 #@timer  # 相当于 test1 = timer(test1)
10 def test1():
11     time.sleep(3)
12     print('in the test1')
13 
14 @timer   # = test2 = timer(test2) = deco test2() = deco()
15 def test2(name):
16     print("test2:",name)
17 
18 test1() #执行这个实际是执行deco
19 test2("li")

 装饰器小调用

 1 import time
 2 def timer(func):#5
 3     def deco():
 4         start = time.time()
 5         func()
 6         stop = time.time()
 7         print(stop-start)
 8     return deco     #这样会返回一个deco函数,但不会执行,因为没调用      
 9 def test():
10     time.sleep(2)
11     print("test is running!")
12 test = timer(test) #6    
13 test() #7   

首先,在#6处,把test作为参数传递给了timer(),此时,在timer()内部,func = test,接下来,定义了一个deco()函数,但并未调用,只是在内存中保存了,并且标签为deco。在timer()函数的最后返回deco()的地址deco。

然后再把deco赋值给了test,那么此时test已经不是原来的test了,也就是test原来的那些函数体的标签换掉了,换成了deco。那么在#7处调用的实际上是deco()。

那么这段代码在本质上是修改了调用函数,但在表面上并未修改调用方式,而且实现了附加功能。

意思就是不能改变调用方式,就把调用的函数体标签换掉,让test() = timer(test)

这样做的原因是

我们要保留test(),还要统计时间,而test()只能调用一次(调用两次运行结果会改变,不满足),再根据函数即“变量”,那么就可以通过函数的方式来回闭包。于是乎,就想到了,把test传递到某个函数,而这个函数内恰巧内嵌了一个内函数,再根据内嵌函数的作用域(可以访问同级及以上,内嵌函数可以访问外部参数),把test包在这个内函数当中,一起返回,最后调用这个返回的函数。而test传递进入之后,再被包裹出来,显然test函数没有弄丢(在包裹里),那么外面剩下的这个test标签正好可以替代这个包裹(内含test())。

 

 

 

 

 

 

 

 

 

 

 

 

4、真正的装饰器

Python提供了一种语法糖,即用@timer 来代替 test= timer(test)

这两句是等价的,只要在函数前加上这句,就可以实现装饰作用。

 

5、装饰有参函数

对于一个实际问题,往往是有参数的,如果要在#8处,给被修饰函数加上参数,显然这段程序会报错的。错误原因是test()在调用的时候缺少了一个位置参数的。而我们知道test = func = deco,因此test()=func()=deco() 

,那么当test(parameter)有参数时,就必须给func()和deco()也加上参数,为了使程序更加有扩展性,因此在装饰器中的deco()和func(),加如了可变参数*agrs和 **kwargs。

improt time

def timer(func)
    def deco(*args, **kwargs):   #加上被修饰函数的参数才会被调用
        start = time.time()
        func(*args, **kwargs)
        stop = time.time()
        print(stop-start)
    return deco

@timer
def test(parameter): #8
    time.sleep(2)
    print("test is running!")   
test() 

 

转载于:https://www.cnblogs.com/ilovelh/p/10234872.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值