博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 装饰器问题及解决方式
阅读量:5167 次
发布时间:2019-06-13

本文共 2211 字,大约阅读时间需要 7 分钟。

1 #统计函数运行时间 2 import time 3 #装饰器 4 def timmer(func): 5     def wrapper(*args,**kwargs): 6         start_time=time.time() 7         func() 8         stop_time =time.time() 9         print("the func time is %s"%(stop_time-start_time))10 11 #函数12 @timmer13 def test1():14     time.sleep(3)15     print('in the test1')16     17 test1()

上面函数运行会出现报错:

函数调用时出错;
'NoneType' object is not callable
此时将调用函数语句去掉后面的括号,改为 test1即可。
装饰器:本质是函数(装饰其他函数)就是为其他函数添加附加功能 
高阶函数+嵌套函数==》装饰器
原则:不能修改被装饰函数的原代码
         不能修改被装饰函数的调用方式
实现装饰器:
1.函数即‘’变量‘’
2.高阶函数: 满足两个条件之一
a:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数的源代码的情况下,为其添加功能)。
b:返回值中包含函数名。(不修改函数的调用方式)
实现高阶函数a
1 import time 2 def bar(): 3     time.sleep(3) 4     print('in the bar') 5 #装饰器, 6 def test1(func): 7     print(func) 8     start_time=time.time() 9     func()   #run bar10     stop_time = time.time()11     print('the func runtime is %s'%(stop_time-start_time))12     13 test1(bar)  #改变了函数原本的调用方式
1 #装饰器中,使用函数作为变量,通过变量也能调用该函数。2 3 func=bar()4 5 func()6 7 #此处和bar()的执行结果是一样的

刚开始写装饰器时,对函数调用方式有疑惑。上面代码最后的语句:test(bar)改变函数原本调用方式很不理解。

经过断点调试和查阅,理解如下:
原函数没有传参,bar()得到的是bar这个函数的执行结果,即等待三秒后执行输出。但是使用装饰器后,高阶函数test1(bar)函数的为原函数附加了一个功能,即输出函数的运行时间,但函数的调用变成将bar的内存地址赋给func,此处使用func()就是执行bar这个函数。
严格意义来说,上面的代码并不符合装饰器的原则。
实现高阶函数b:返回值是函数名。没有改变函数的调用方式。
1 import time 2 #函数的调用方式没有改变 3 def bar(): 4     time.sleep(3) 5     print('in the bar') 6 #装饰器 7 def test2(func): 8     print(func) 9     return func10 print('--->',test2(bar))#t=test2(bar)   print(t)  二者实现的效果是一样的11 t=test2(bar)12 t()#等同于bar()13 14 bar=test2(bar)15 bar()#等同于 run bar

    上面内容:把函数bar传给func,print(func),实质是打印下来bar的内存地址,return func 的返回值就是test2(bar)的运行结果。          print('--->',test2(bar))就是将test2(bar)的运行结果(即return func)的运行结果打印下来

第11行中:test2(bar())和test2(bar)的区别?

前者是将bar的运行结果传给test2,(即字符串类型),不符合高阶函数中返回值是函数名这一原则。

后者将bar的内存地址返回给test2,之后执行。

 

3.函数嵌套
定义:在一个函数体内,用def声明一个新的函数。(注意与函数调用的区别)

 

4.局部作用域和全局作用域的访问顺序

1 #局部作用域和全局作用域的访问顺序 2 x=0 3 def test1(): 4     x=1 5     print(x) 6     def test2(): 7         x=2 8         print(x) 9         def test3():10             x=311             print(x)12         test3()13     test2()14 test1()15 print(x)

通过上面实现可以看出:

若将test2()注释掉,则将不能访问进入test3()。函数外层输出的x的结果仍旧是0,因为它是全局变量。

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

转载于:https://www.cnblogs.com/bocaimao/p/10336819.html

你可能感兴趣的文章
安卓数据库操作
查看>>
MySql中的变量定义
查看>>
spoj2798 QTREE3 Query on a tree again!
查看>>
Python acos() 函数
查看>>
top coder password题解
查看>>
Myeclipse 安装所有插件
查看>>
4-1
查看>>
POJ - 2796 Feel Good 单调递增栈+前缀和
查看>>
redis面试题
查看>>
三、activiti designer 的安装
查看>>
Python自省
查看>>
How to Choose the Best Way to Pass Multiple Models in ASP.NET MVC
查看>>
【算法】求二叉树各路径结点之和并找出最大值的路径
查看>>
getLayoutParams()和setLayoutParams()方法源码
查看>>
用R创建Word和PowerPoint文档--转载
查看>>
(转)Java 的swing.GroupLayout布局管理器的使用方法和实例
查看>>
Roman to Integer
查看>>
Excel Sheet Column Number
查看>>
7个超棒的Bootstrap3主题builder帮助加速Bootstrap3主题开发
查看>>
学习进度表
查看>>