扯扯在开发中python闭包的应用

跟同事又聊起了闭包,闭包算是个设计模型,但发现周边的人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,再后来老老实实用类。。。   嘚瑟半天老实了 。    


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

发表评论

邮箱地址不会被公开。 必填项已用*标注