跟同事又聊起了闭包,闭包算是个设计模型,但发现周边的人python闭包用的很少…. 我自己时不时会用。 python的闭包除了装饰器之外,有时候懒得写类class。 我就直接用闭包。。
闭包(closure)是函数式编程的重要的语法结构。函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式)。在面向过程编程中,我们见到过函数(function);在面向对象编程中,我们见过对象(object)。函数和对象的根本目的是以某种逻辑方式组织代码,并提高代码的可重复使用性(reusability)。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包这一语法结构提供支持的 (我们在特殊方法与多范式中,已经多次看到Python使用对象来实现一些特殊的语法)。Python一切皆对象,函数这一语法结构也是一个对象。在函数对象中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。
简单说,就是套嵌的def,第二层的def函数逻辑是可以直接访问上层的局部作用域的变量 !
class foo: def __init__(self, x = 0): self.x = x def update(self,y): self.x += y print self.x #xiaorui.cc f = foo(5) g = foo(10) f.update(5) g.update(5) print 'end'
我一般是这么用,就是因为懒得写类,然后又觉得在一些变量可继承的情况下,用闭包真的是很方便。
def makeInc(x): inc(1) def inc(y): return y + x return inc inc5 = makeInc(5) inc10 = makeInc(10) print inc5(5) # returns 10 print inc10(5) # returns 15
既然都说到闭包,那么简单用装饰器遇到的问题。 下面的代码是用来计数,原本的代码有些复杂,我精简了下, 以前主要是用来做函数调用的统计。
既然是函数的调用次数的统计,那么大多还会涉及到同类的函数。比如有三个函数都是同一种类型的,我想让她们的计数是累加的,而不是自己算自己的…
我可能有些说不明白,大家自己跑下代码,就能体会到。 test和test_other是同一组的函数。
因为这装饰器看起来只是个 @counter ,其实后面运行的是 nima = counter;nima(),每次的变量环境都是唯一的。
解决这方法也很简单,global num 最好加一个锁,不然数字累加不安全。如果是分布式系统那么就直接用redis,不用每次都操作redis,可以用取模的方式,间隔性的incr
filename: c.py def counter(func): def incr(): incr.count +=1 print incr.count func() incr.count = 0 print "count ++" return incr filename: run.py from c import counter #from other import test_other @counter def test(): pass @counter def test_other(): pass for i in range(1,5): test() test_other()
话说回来,闭包也不是很高级的应用,也不用非要用这闭包。 除了装饰器之外,以前我还用过闭包做mongodb的连接管理,后来我有用过with,再后来老老实实用类。。。 嘚瑟半天老实了 。