一個對Python初學者難以理解的作用域代碼
但追求上進的朋友,一定要查明真相,是好事,聽黃哥下面的分解。
# coding:utf-8nnndef make_actions():n acts = []n for i in range(5):n acts.append(lambda x: i ** x)n return actsnnfoo = make_actions()nprint(foo[0](2))nprint(foo[1](2))nprint(foo[3](2))nprint(foo[3](2))nn# 16n# 16n# 16n# 16n
結果都是16,書上說,循環後,最後調用foo這個列表中的函數時,都是調用的最後的i的值為
4,所以結果都為16。
這個問題進一步探討,這個是一個典型的閉包問題。請看下面的代碼。
# coding:utf-8nnndef make_actions():n """黃哥說明,這個是Python2,如果是3 func_closuren 需要修改為__closure__n """"n acts = []n for i in range(5):n acts.append(lambda x: i ** x)n return actsnnfoo = make_actions()nprint(foo[0].func_closure[0].cell_contents)nprint(foo[1].func_closure[0].cell_contents)nprint(foo[2].func_closure[0].cell_contents)nprint(foo[3].func_closure[0].cell_contents)n# 4n# 4n# 4n# 4n
Python2 中func_closure 返回閉包引用外部函數的變數,這個匿名函數lambda x: i ** x
引用了make_actions函數的i值,當函數調用時foo[0].func_closure[0].cell_contents 這個表示i值為4 所以結果為16.
如果想得到make_actions()里函數每次循環的i值,代碼修改如下。
# coding:utf-8nnndef make_actions():n acts = []n for i in range(5):n acts.append(lambda x, i=i: i ** x)n return actsnnfoo = make_actions()nprint(foo[0](2))nprint(foo[1](2))nprint(foo[3](2))nprint(foo[4](2))n# 0n# 1n# 9n# 16n
忠言:學習中,有的時候需要適當不求甚解一下,千萬不要「太鑽牛角尖」。
推薦閱讀:
※GlumPy 中文文檔翻譯:上手簡介
※樹莓派Raspberry區域網視頻小車教程
※Kivy中文編程指南:輸入管理
※Python語法速覽與機器學習開發環境搭建
TAG:Python |