Python里的闭包和AOP

习惯了写Java和JS代码,突然换成Python还真不习惯,最近在书上看到一段挺有意思的Python代码,才真心感觉到Python长盛不衰的价值。在很多语言里,如果在一个内部函数里,对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。闭包的词法变量不属于全局或者局部作用域,而属于一种“流量”的作用域。


先介绍一种语法,Python有种叫函数装饰器的东西,这是一种特殊的函数,因为它接受函数对象为参数,对其进行封装加工并返回。举个简单的例子:

@deco(deco_args)
def foo(): pass

#相当于:foo = deco(deco_args) (foo)

装饰器封装了foo,并返回新版本的foo。这其实就是一种闭包的用法,因为无论在deco函数中定义了那些变量,当调用新版本foo的时候都可以访问到它们,那些变量并不随着deco函数的执行结束返回而销毁,而是继续存活在“流量”空间里等待被激活。如果要问这有什么作用?最容易理解的就是对比Java里的AOP概念,在不改变源代码的情况下,织入切面,添加统一的逻辑:打日志、性能指标记录、统一事务管理等等。而在python里面,AOP居然如此之简单,通过函数装饰器和闭包的特性就可以轻易解决。下面这个例子,就是对闭包强大特性的一个体现:(给方法hello添加执行时间的分析,不改动原方法hello的代码)

#!usr/bin/env python

from time import time

def logged(when):
	def log(f, *args, **kargs):
		print '''Called:
function: %s
args: %r
kargs: %r''' % (f,args,kargs)

	def pre_logged(f):
		def wrapper(*args, **kargs):
			log(f, *args, **kargs)
			return f(*args, **kargs)
		return wrapper

	def post_logged(f):
		def wrapper(*args, **kargs):
			now = time()
			try:
				return f(*args, **kargs)
			finally:
				log(f, *args, **kargs)
				print "time delta: %s" % (time()-now)
		return wrapper

	try:
		return {"pre": pre_logged, "post": post_logged}[when]
	except:
		raise ValueError(e), 'must be "pre" or "post"'

@logged("post")
def hello(name):
	print "Hello, ", name

hello("World")

可以看到只是简单的在hello方法前添加了一个函数装饰器,就可以让hello的调用具有分析执行时间的特性,成功的织入切面!我这的执行结果是:

Hello,  World
Called:
function: <function hello at 0x10755aa28>
args: ('World',)
kargs: {}
time delta: 3.88622283936e-05




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值