Python編程中運用閉包時所需要注意的一些地方

來源:互聯網
上載者:User

Python編程中運用閉包時所需要注意的一些地方

   這篇文章主要介紹了Python編程中運用閉包時所需要注意的一些地方,文章來自國內知名的Python開發人員felinx的部落格,需要的朋友可以參考下

  寫下這篇部落格,起源於Tornado郵件群組的這個問題how to use outer variable in inner method,這裡面老外的回答很有參考價值,關鍵點基本都說到了。我在這裡用一些有趣的例子來做些解析,簡要的闡述下Python的閉包規則,首先看一個經典的例子:

  ?

1

2

3

4

5

6

7

8

9

10

11

def foo():

a = 1

def bar():

a = a + 1

# print a + 1

# b = a + 1

# a = 1

print id(a)

 

bar()

print a, id(a)

  在Python2.x上運行這個函數會報UnboundLocalError: local variable 'a' referenced before assignment即本地變數在引用前未定義,如何來理解這個錯誤呢?PEP 227裡面介紹到,Python解析器在搜尋一個變數的定義時是根據如下三級規則來尋找的:

  The Python 2.0 definition specifies exactly three namespaces to check for each name — the local namespace, the global namespace, and the builtin namespace.

  這裡的local實際上可能還有多級,上面的代碼就是一個例子,下面通過對代碼做些簡單的修改來一步步理解這裡面的規律:

  如果將a = a + 1這句換成print a + 1或者b = a + 1,是不會有問題的,即在內建函式bar內,外部函數foo裡的a實際是可見的,可以引用。

  將a = a + 1換成 a = 1也是沒有問題的,但是如果你將兩處出現的a的id列印出來你會發現,其實這兩個a不是一回事,在內建函式bar裡面,本地的a = 1定義了在bar函數範圍內的新的一個局部變數,因為名字和外部函數foo裡面的變數a名字相同,導致外部函數foo裡的a在內建函式bar裡實際已不可見。

  再來說a = a + 1出錯是怎麼回事,首先a = xxx這種形式,Python解析器認為要在內建函式bar內建立一個新的局部變數a,同時外部函數foo裡的a在bar裡已不可見,而解析器對接下來對右邊的a + 1的解析就是用本地的變數a加1,而這時左邊的a即本地的變數a還沒有建立(等右邊賦值呢),因此就這就產生了一個是雞生蛋還是蛋生雞的問題,導致了上面說的UnboundLocalError的錯誤。

  要解決這個問題,在Python2.x裡主要有兩個方案:

  用別名替代比如b = a + 1,內建函式bar內只引用外部函數foo裡的a。

  將foo裡的a設成一個容器,如list

  ?

1

2

3

4

5

6

7

def foo():

a = [1, ]

def bar():

a[0] = a[0] + 1

 

bar()

print a[0]

  當然這有些時候還是很不方便,因此在Python3.x中引入了一個nonloacal的關鍵字來解決這個問題,只要在a = a + 1前加一句nonloacal a即可,即顯式的指定a不是內建函式bar內的本地變數,這樣就可以在bar內正常的使用和再賦值外部函數foo內的變數a了。

  在搜尋Python閉包相關的材料中,我在StackOverflow上發現一個有趣的有關Python閉包的問題,有興趣的可以思考思考做做看,結果應該是什麼?你預期的結果是什麼,若不一致,如果要得到你預期的結果應該怎麼改?

  ?

1

2

3

4

5

6

7

8

flist = []

 

for i in xrange(3):

def func(x): return x * i

flist.append(func)

 

for f in flist:

print f(2)

        注< >:更多精彩教程請關注幫客之家編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.