装饰器模式,重点在于装饰。装饰的核心仍旧是被装饰对象。
类比于Java编程的时候的包装模式,是同样的道理。虽然概念上稍有不同但是原理上还是比较相近的。下面我就来谈一谈我对Python的装饰器的学习的一点心得吧。
关于作用域
Python作用域 体现在LEGB中:
- L:local 函数内部
- E: enclosing 函数内部和内置函数之间
- G:global 全局性质,有命名空间的限制
- B:build-in 内置函数,由python解释器管理
学过编程的人一眼就可以看得出来大致是什么意思,所以这里不再叙述。
关于闭包
关键在于理解Python中闭包的概念。说白了,闭包就是函数里面又定义了函数,这就是闭包了。(呵呵,断章取义一下。可能说法不恰当)。如下:
def func1(): print 'func1 is running' def in_func1(): print 'in_func1 is running' return in_func1 print 'over'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
简单的一个闭包的实现,就差不多是这个样子的。我们需要注意的就是要将内部函数当成一个对象来返回(Python中函数其实就是一个对象,我们可以通过type来进行验证)。
这段代码执行的流程是先执行func1,然后执行func2,并且将func2作为一个属性返回给func1.这样我们可以再次的得到func2的内容。这就是闭包!
关于装饰器
类比Java中那么多的模式,比如ServletRequest被装饰成了HttpServletRequest。Python中也有很多这样被装饰的例子。如CookieJar被装饰成了MozillaCookieJar等等。实现的功能就是被装饰对象的功能得到了增强,完成的效果也大大大的比未装饰之前好了。这就是装饰的好处。
下面就来看一看Python中怎么来实现装饰器吧。
核心:借助于@符号,即可。
def bar(func): print 'Bar' return func@bardef foo(): print "foo"# 其等价于:def foo(): print "foo"foo = bar(foo)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
代码执行的流程:
先执行@对象,也就是一个函数。其返回值就是一个内置函数,只不过这个内置函数是得到了装饰的被装饰对象(这里是foo函数),我们可以理解为:
装饰器,其本身接收一个函数对象作为参数,然后做一些工作后,返回接收的参数,供外界调用。
下面看一个实例:
import timedef function_performance_statistics(trace_this=True): if trace_this: def performace_statistics_delegate(func): def counter(*args, **kwargs): start = time.clock() func(*args, **kwargs) end =time.clock() print 'used time: %d' % (end - start, ) return counter else: def performace_statistics_delegate(func): return func return performace_statistics_delegate@function_performance_statistics(True)def add(x, y): time.sleep(3) print 'add result: %d' % (x + y,)@function_performance_statistics(False)def mul(x, y=1): print 'mul result: %d' % (x * y,)add(1, 1)mul(10)上述代码想要实现一个性能分析器,并接收一个参数,来控制性能分析器是否生效,其运行效果如下所示:add result: 2used time: 0mul result: 10上述代码中装饰器的调用等价于:add = function_performance_statistics(True)(add(1, 1))mul = function_performance_statistics(False)(mul(10))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
写一个日志记录器
# 做一个loggerdef logging(filename="", level=0): def wrapper(func): def log(*args, **kwargs): with open(filename, "a") as file: line = "[LEVEL: {}] {}, {}\n".format(level, args, kwargs) file.write(line) file.close() # 需要有返回值就return,否则就不用return return func(*args, **kwargs) return log return wrapper@logging(filename="query.log", level=1)def query(msg): print(msg, " be carried.") return "`{}` has beed logged.".format(msg)print(query("select * from user where userid = 2614677"))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
总结
Python装饰器的核心就是装饰,实质就是被装饰函数性能的增强。
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow