国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Python > 正文

Python編程中運(yùn)用閉包時(shí)所需要注意的一些地方

2019-11-25 17:34:03
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

寫(xiě)下這篇博客,起源于Tornado郵件群組的這個(gè)問(wèn)題how to use outer variable in inner method,這里面老外的回答很有參考價(jià)值,關(guān)鍵點(diǎn)基本都說(shuō)到了。我在這里用一些有趣的例子來(lái)做些解析,簡(jiǎn)要的闡述下Python的閉包規(guī)則,首先看一個(gè)經(jīng)典的例子:

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上運(yùn)行這個(gè)函數(shù)會(huì)報(bào)UnboundLocalError: local variable 'a' referenced before assignment即本地變量在引用前未定義,如何來(lái)理解這個(gè)錯(cuò)誤呢?PEP 227里面介紹到,Python解析器在搜索一個(gè)變量的定義時(shí)是根據(jù)如下三級(jí)規(guī)則來(lái)查找的:

    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實(shí)際上可能還有多級(jí),上面的代碼就是一個(gè)例子,下面通過(guò)對(duì)代碼做些簡(jiǎn)單的修改來(lái)一步步理解這里面的規(guī)律:

  •     如果將a = a + 1這句換成print a + 1或者b = a + 1,是不會(huì)有問(wèn)題的,即在內(nèi)部函數(shù)bar內(nèi),外部函數(shù)foo里的a實(shí)際是可見(jiàn)的,可以引用。
  •     將a = a + 1換成 a = 1也是沒(méi)有問(wèn)題的,但是如果你將兩處出現(xiàn)的a的id打印出來(lái)你會(huì)發(fā)現(xiàn),其實(shí)這兩個(gè)a不是一回事,在內(nèi)部函數(shù)bar里面,本地的a = 1定義了在bar函數(shù)范圍內(nèi)的新的一個(gè)局部變量,因?yàn)槊趾屯獠亢瘮?shù)foo里面的變量a名字相同,導(dǎo)致外部函數(shù)foo里的a在內(nèi)部函數(shù)bar里實(shí)際已不可見(jiàn)。
  •     再來(lái)說(shuō)a = a + 1出錯(cuò)是怎么回事,首先a = xxx這種形式,Python解析器認(rèn)為要在內(nèi)部函數(shù)bar內(nèi)創(chuàng)建一個(gè)新的局部變量a,同時(shí)外部函數(shù)foo里的a在bar里已不可見(jiàn),而解析器對(duì)接下來(lái)對(duì)右邊的a + 1的解析就是用本地的變量a加1,而這時(shí)左邊的a即本地的變量a還沒(méi)有創(chuàng)建(等右邊賦值呢),因此就這就產(chǎn)生了一個(gè)是雞生蛋還是蛋生雞的問(wèn)題,導(dǎo)致了上面說(shuō)的UnboundLocalError的錯(cuò)誤。

要解決這個(gè)問(wèn)題,在Python2.x里主要有兩個(gè)方案:

    用別名替代比如b = a + 1,內(nèi)部函數(shù)bar內(nèi)只引用外部函數(shù)foo里的a。
    將foo里的a設(shè)成一個(gè)容器,如list

  

 def foo():  a = [1, ]  def bar():   a[0] = a[0] + 1    bar()  print a[0]

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

在搜索Python閉包相關(guān)的材料中,我在StackOverflow上發(fā)現(xiàn)一個(gè)有趣的有關(guān)Python閉包的問(wèn)題,有興趣的可以思考思考做做看,結(jié)果應(yīng)該是什么?你預(yù)期的結(jié)果是什么,若不一致,如果要得到你預(yù)期的結(jié)果應(yīng)該怎么改?

flist = [] for i in xrange(3): def func(x): return x * i flist.append(func) for f in flist: print f(2)

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 马尔康县| 桂林市| 乌鲁木齐市| 错那县| 靖宇县| 丽江市| 红河县| 绥宁县| 鹿邑县| 墨江| 鄯善县| 静乐县| 垣曲县| 香港 | 凤凰县| 讷河市| 湘潭市| 通山县| 砀山县| 和平区| 阳春市| 莒南县| 余江县| 都安| 新津县| 栾川县| 崇信县| 镶黄旗| 眉山市| 和静县| 通渭县| 外汇| 梁河县| 囊谦县| 敦化市| 永善县| 嘉兴市| 武隆县| 台南县| 南平市| 永善县|