文章轉載來自http://blog.csdn.net/marty_fu/article/details/7679297
閉包這個概念在很多語言中都有涉及,本文主要談談python中的閉包。Python中使用閉包主要是在進行函數式開發時使用。
一,定義
- >>>def addx(x):
- >>> def adder(y): return x + y
- >>> return adder
- >>> c = addx(8)
- >>> type(c)
- <type 'function'>
- >>> c.__name__
- 'adder'
- >>> c(10)
- 18
- >>> def foo():
- ... m = 0
- ... def foo1():
- ... m = 1
- ... print m
- ...
- ... print m
- ... foo1()
- ... print m
- ...
- >>> foo()
- 0
- 1
- 0
2,以下這段代碼是在python中使用閉包時一段經典的錯誤代碼
- def foo():
- a = 1
- def bar():
- a = a + 1
- return a
- return bar
- >>> c = foo()
- >>> print c()
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- File "<stdin>", line 4, in bar
- UnboundLocalError: local variable 'a' referenced before assignment
- def foo():
- a = [1]
- def bar():
- a[0] = a[0] + 1
- return a[0]
- return bar
3,還有一個容易產生錯誤的事例也經常被人在介紹python閉包時提起,我一直都沒覺得這個錯誤和閉包有什麼太大的關係,但是它倒是的確是在python函數式編程是容易犯的一個錯誤,我在這裏也不妨介紹一下。先看下面這段代碼
- for i in range(3):
- print i
- flist = []
- for i in range(3):
- def foo(x): print x + i
- flist.append(foo)
- for f in flist:
- f(2)
- for i in range(3):
- def foo(x,y=i): print x + y
- flist.append(foo)
- origin = [0, 0] # 座標系統原點
- legal_x = [0, 50] # x軸方向的合法座標
- legal_y = [0, 50] # y軸方向的合法座標
- def create(pos=origin):
- def player(direction,step):
- # 這裏應該首先判斷參數direction,step的合法性,比如direction不能斜着走,step不能爲負等
- # 然後還要對新生成的x,y座標的合法性進行判斷處理,這裏主要是想介紹閉包,就不詳細寫了。
- new_x = pos[0] + direction[0]*step
- new_y = pos[1] + direction[1]*step
- pos[0] = new_x
- pos[1] = new_y
- #注意!此處不能寫成 pos = [new_x, new_y],原因在上文有說過
- return pos
- return player
- player = create() # 創建棋子player,起點爲原點
- print player([1,0],10) # 向x軸正方向移動10步
- print player([0,1],20) # 向y軸正方向移動20步
- print player([-1,0],10) # 向x軸負方向移動10步
- [10, 0]
- [10, 20]
- [0, 20]
用途2,閉包可以根據外部作用域的局部變量來得到不同的結果,這有點像一種類似配置功能的作用,我們可以修改外部的變量,閉包根據這個變量展現出不同的功能。比如有時我們需要對某些文件的特殊行進行分析,先要提取出這些特殊行。
- def make_filter(keep):
- def the_filter(file_name):
- file = open(file_name)
- lines = file.readlines()
- file.close()
- filter_doc = [i for i in lines if keep in i]
- return filter_doc
- return the_filter
- filter = make_filter("pass")
- filter_result = filter("result.txt")