#统计函数运行时间
import time
#装饰器
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
func()
stop_time =time.time()
print("the func time is %s"%(stop_time-start_time)) #函数
@timmer
def test1():
time.sleep(3)
print('in the test1') test1()

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

函数调用时出错;
'NoneType' object is not callable
此时将调用函数语句去掉后面的括号,改为 test1即可。
装饰器:本质是函数(装饰其他函数)就是为其他函数添加附加功能 
高阶函数+嵌套函数==》装饰器
原则:不能修改被装饰函数的原代码
         不能修改被装饰函数的调用方式
实现装饰器:
1.函数即‘’变量‘’
2.高阶函数: 满足两个条件之一
a:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数的源代码的情况下,为其添加功能)。
b:返回值中包含函数名。(不修改函数的调用方式)
实现高阶函数a

 import time
def bar():
time.sleep(3)
print('in the bar')
#装饰器,
def test1(func):
print(func)
start_time=time.time()
func() #run bar
stop_time = time.time()
print('the func runtime is %s'%(stop_time-start_time)) test1(bar) #改变了函数原本的调用方式
 #装饰器中,使用函数作为变量,通过变量也能调用该函数。

 func=bar()

 func()

 #此处和bar()的执行结果是一样的

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

经过断点调试和查阅,理解如下:
原函数没有传参,bar()得到的是bar这个函数的执行结果,即等待三秒后执行输出。但是使用装饰器后,高阶函数test1(bar)函数的为原函数附加了一个功能,即输出函数的运行时间,但函数的调用变成将bar的内存地址赋给func,此处使用func()就是执行bar这个函数。
严格意义来说,上面的代码并不符合装饰器的原则。
实现高阶函数b:返回值是函数名。没有改变函数的调用方式。

 import time
#函数的调用方式没有改变
def bar():
time.sleep(3)
print('in the bar')
#装饰器
def test2(func):
print(func)
return func
print('--->',test2(bar))#t=test2(bar) print(t) 二者实现的效果是一样的
t=test2(bar)
t()#等同于bar() bar=test2(bar)
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.局部作用域和全局作用域的访问顺序

 #局部作用域和全局作用域的访问顺序
x=0
def test1():
x=1
print(x)
def test2():
x=2
print(x)
def test3():
x=3
print(x)
test3()
test2()
test1()
print(x)

通过上面实现可以看出:

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

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

python 装饰器问题及解决方式的更多相关文章

  1. python装饰器执行顺序

    . python 装饰器 1) 2层装饰器 def decorator(func): # TODO def wrapper(*args, **kwargs): # TODO func(*args, * ...

  2. python 装饰器的缺点以及解决方法

    1.python装饰器的缺点 装饰器可以允许我们在不改变函数或犯方法的调用方式的情况下,添加额外的功能; 如下所示,我们要在中的方法之前增加装饰器check_is_admin,用来判断执行类的方法的用 ...

  3. python 装饰器、递归原理、模块导入方式

    1.装饰器原理 def f1(arg): print '验证' arg() def func(): print ' #.将被调用函数封装到另外一个函数 func = f1(func) #.对原函数重新 ...

  4. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  5. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  6. 一篇关于Python装饰器的博文

    这是一篇关于python装饰器的博文 在学习python的过程中处处受阻,之前的学习中Python的装饰器学习了好几遍也没能真正的弄懂.这一次抓住视频猛啃了一波,就连python大佬讲解装饰器起来也需 ...

  7. python 装饰器 一篇就能讲清楚

    装饰器一直是我们学习python难以理解并且纠结的问题,想要弄明白装饰器,必须理解一下函数式编程概念,并且对python中函数调用语法中的特性有所了解,使用装饰器非常简单,但是写装饰器却很复杂.为了讲 ...

  8. 利用世界杯,读懂 Python 装饰器

    Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...

  9. 理解 Python 装饰器看这一篇就够了

    讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切. 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它 ...

随机推荐

  1. Pocket Gems面经prepare: Diamond and Ruby

    说我有一个背包,有n个格子,一个格子可以放5个钻石,一个钻石10块钱,一个格子可以放5个ruby,一个ruby 5块钱, 一个格子可以放一个装备,一个装备25块钱. 然后给你n个钻石n个ruby n个 ...

  2. Docker 共有 13 个管理命令和 41 个通用命令,以下是常用 Docker 命令列表

    开发人员一直在努力提高 Docker 的使用率和性能,命令也在不停变化.Docker 命令经常被弃用,或被替换为更新且更有效的命令,本文总结了近年来资深专家最常用的命令列表并给出部分使用方法. 目前, ...

  3. linux配制DNS服务器基本能功能

    1.环境 Centos 6.5 bind 关闭防火墙和SELINUX 2.安装bind服务软件 yum -y install bind 3.配制主配制文件/etc/name.conf options ...

  4. 在sql中case子句的两种形式

    case子句,在select后面可以进行逻辑判断. 两种形式:判断相等.判断不等 一.判断相等的语法: case 列名 when ...  then ... when ...  then ... el ...

  5. Java类型信息之RTTI

    软件工程的一个核心问题就是软件的复用和扩展.面向对象思想通过封装,继承,派生等机制有效地解决了这个问题.但需求总是变幻莫测,不可琢磨,在面向对象这栋恢宏的大厦旁,还漂浮着一朵乌云,从而导致了RTTI的 ...

  6. jq+bootstrap响应式系统管理页面

    用bootstrap搭建的一个系统管理页面基于经典的HTML+Css 弊端:代码量太大,用vue组件化开发的思想更加便捷且方便!不过如果是做纯展示的系统页面,只需要一些简单的数据交互,用jq配合boo ...

  7. C#-----线程安全的ConcurrentQueue<T>队列

     ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据 ...

  8. Angular4 响应式编程

  9. c++算法实现(一) - 递归和初始化

    递归 写递归函数经常出错,提醒自己两个规则: 1. 一般来说递归函数中不应该出现for.while之类的循环语句, 因为递归就是循环的另外一种实现: 2. 注意基线条件,具体参考<算法图解> ...

  10. Ant构建原理及build.xml文档描述

    最近在改写jmeter,用到ant构建,记录一下. Ant的概念Make命令是一个项目管理工具,而Ant所实现功能与此类似.像make,gnumake和nmake这些编译工具都有一定的缺陷,但是Ant ...