大同推广型网站建设,一站式做网站系统,网站色彩代码,长春企业建站系统模板这几天翻看python语法#xff0c;看到装饰器这里着实卡了一阵#xff0c;最初认为也就是个函数指针的用法#xff0c;但仔细研究后发现#xff0c;不止这么简单。 首先很多资料将装饰器定义为AOP的范畴#xff0c;也就是Aspect Oriented Programming面向切面编程的概念看到装饰器这里着实卡了一阵最初认为也就是个函数指针的用法但仔细研究后发现不止这么简单。 首先很多资料将装饰器定义为AOP的范畴也就是Aspect Oriented Programming面向切面编程的概念不懂AOP不要紧只要有函数指针的概念又有嵌套函数的基础知识看懂此文一点压力都没有。 先说说为什么要有装饰器这么个东西存在吧这是一种设计模式较为经典的有插入日志、性能测试、事务处理等等。概括的讲装饰器的作用就是为已经存在的对象添加额外的功能。 关于嵌套函数C/C程序员可能会觉得一头雾水因为谭老爷子的书明确指出函数不可以嵌套定义在C primer也仅仅有嵌套类的讲解并不存在嵌套函数一说但是在一些高级语言中比如Object Cswift都存在嵌套函数主题感兴趣的同学可以去翻一下尤其是当下热门swift嵌套函数和闭包密不可分可以方便的实现很多逻辑比如返回一个函数给调用者。 书归正传所谓装饰器顾名思义就是用来装饰的神器你有一个函数A()觉得它不够漂亮但是又不想重写它咋办呢装饰器Decorator这时候就派上用场了。 为了方便大家的理解我先写一个简单的嵌套函数 def funcA():print(i am funcA()!)def funcB():print(i am funcB())return funcB
callSthfuncA()//调用funcA得到返回的funcB
callSth()//相当于调用funcB 值得说明一点在python里只要你不怕蛋疼你可以任意嵌套哪怕你嵌套个百十层直到栈溢出都没问题。 如下 def ppp():print(return vlaue)
def first():a10// a被嵌套内的函数捕获print(the first layer)def second():print(the second layer %d % a)def third():print(the third layer %d % a)def forth():print(the forth layer)return ppp()return forthreturn thirdreturn second aaafirst()()()//得到forth()
aaa()关于嵌套函数是这样执行的先执行最外层的first()返回second然后发现后面跟着()那继续返回third以此类推聪明如你肯定明白了。嵌套函数就这样简单到爆。如果到这里诸君理解了装饰器基本上也就理解了。 下面正式开始装饰器的概念开启摘抄模式 装饰器的定义很是抽象我们来看一个小例子。 def foo():print in foo()
foo()这是一个很无聊的函数没错。但是突然有一个更无聊的人我们称呼他为B君说我想看看执行这个函数用了多长时间好吧那么我们可以这样做 import time
def foo():start time.clock()print in foo()end time.clock()print used:, end - startfoo()很好功能看起来无懈可击。可是蛋疼的B君此刻突然不想看这个函数了他对另一个叫foo2的函数产生了更浓厚的兴趣。 怎么办呢如果把以上新增加的代码复制到foo2里这就犯了大忌了~复制什么的难道不是最讨厌了么而且如果B君继续看了其他的函数呢 以不变应万变还记得吗函数在Python中是一等公民那么我们可以考虑重新定义一个函数timeit将foo的引用传递给他然后在timeit中调用foo并进行计时这样我们就达到了不改动foo定义的目的而且不论B君看了多少个函数我们都不用去修改函数定义了 import timedef foo():print in foo()def timeit(func):start time.clock()func()end time.clock()print used:, end - starttimeit(foo)看起来逻辑上并没有问题一切都很美好并且运作正常……等等我们似乎修改了调用部分的代码。原本我们是这样调用的foo()修改以后变成了timeit(foo)。这样的话如果foo在N处都被调用了你就不得不去修改这N处的代码。或者更极端的考虑其中某处调用的代码无法修改这个情况比如这个函数是你交给别人使用的。 最大限度地少改动 既然如此我们就来想想办法不修改调用的代码如果不修改调用代码也就意味着调用foo()需要产生调用timeit(foo)的效果。我们可以想到将timeit赋值给foo但是timeit似乎带有一个参数……想办法把参数统一吧如果timeit(foo)不是直接产生调用效果而是返回一个与foo参数列表一致的函数的话……就很好办了将timeit(foo)的返回值赋值给foo然后调用foo()的代码完全不用修改 一个真正意义上的装饰器诞生了 #-*- coding: UTF-8 -*-
import timedef foo():print in foo()# 定义一个计时器传入一个并返回另一个附加了计时功能的方法
def timeit(func):# 定义一个内嵌的包装函数给传入的函数加上计时功能的包装def wrapper():start time.clock()func()end time.clock()print used:, end - start# 将包装后的函数返回return wrapperfoo timeit(foo)
foo()样一个简易的计时器就做好了我们只需要在定义foo以后调用foo之前加上foo timeit(foo)就可以达到计时的目的这也就是装饰器的概念看起来像是foo被timeit装饰了。在在这个例子中函数进入和退出时需要计时这被称为一个横切面(Aspect)这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。与传统编程习惯的从上往下执行方式相比较而言像是在函数执行的流程中横向地插入了一段逻辑。在特定的业务领域里能减少大量重复代码。面向切面编程还有相当多的术语这里就不多做介绍感兴趣的话可以去找找相关的资料。 语法糖 上面这段代码看起来似乎已经不能再精简了Python于是提供了一个语法糖来降低字符输入量。 import timedef timeit(func):def wrapper():start time.clock()func()end time.clock()print used:, end - startreturn wrappertimeit// syntax sugar 是也在定义上加上这一行与另外写foo timeit(foo)完全等价千万不要以为有另外的魔力。除了字符输入少了一些还有一个额外的好处这样看上去更有装饰器的感觉。
def foo():print in foo()foo()给出原文链接http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html 相关资料http://blog.csdn.net/thy38/article/details/4471421 http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 转载于:https://www.cnblogs.com/wangjunyan/p/5046223.html