99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀Python基礎(chǔ)知識:什么是非局部語句?
Python基礎(chǔ)知識:什么是非局部語句?
2016-03-17
收藏
本文首發(fā)于微信公眾號號“編程派”。微信搜索“編程派”,獲取更多Python編程一手教程及優(yōu)質(zhì)資源吧。

有同學(xué)曾在微信中問小編什么是非局部語句(nonlocal statement),本文就是對此的回答,希望沒有發(fā)的太晚。

非局部語句是Python 3.x中新引入的特性。官方文檔中的說法是,非局部語句可以讓所列的標識符(identifier)指向最近的嵌套作用域(enclosing scope)中已經(jīng)綁定過的變量,全局變量除外。

如果沒有非局部語句

一般來說,嵌套函數(shù)對于其外層作用域中的變量是有訪問權(quán)限的。


>>> def outside():
        msg = "Outside!"

        def inside():
            print(msg)

        inside()
       print(msg)
>>> outside()
Outside!
Outside!

我們在outside函數(shù)中聲明了msg變量,并賦值為“Outside!”。然后,在inside函數(shù)中打印msg的值。結(jié)果證明,inside成功獲得了外層作用域中msg的值。

但是如果我們想給外層作用域中的變量賦值時,是不是按照平常的賦值操作就可以修改它的值呢?


>>> def outside():
        msg = "Outside!"
        def inside():
            msg = "Inside!"
            print(msg)
        inside()
       print(msg)
>>> outside()
Inside! # inside函數(shù)打印的msg
Outside! # outside函數(shù)打印的msg

在inside函數(shù)中,我們想給msg變量賦值為"Inside!"。運行outside時,inside函數(shù)中msg的值為"Inside!",但是在outside函數(shù)中卻保留了原先的值!

之所以出現(xiàn)這個情況,是因為在inside函數(shù)中,Python實際上并沒有為之前已經(jīng)創(chuàng)建的msg變量賦值,而是在inside函數(shù)的局部作用域(local scope)中創(chuàng)建了一個名叫msg的新變量,但是這樣就和外層作用域(outer scope)中的變量重名了。

這說明,嵌套函數(shù)對外層作用域中的變量其實只有只讀訪問權(quán)限。如果我們在這個示例中的inside函數(shù)的頂部再加一個print(msg)語句,那么就會出現(xiàn)UnboundLocalError: local variable 'msg' referenced before assignment這個錯誤。

非局部語句的引入,就是要盡量減少這種變量名沖突情況的出現(xiàn),同時也讓嵌套函數(shù)更加方便的操作外層函數(shù)中的變量。更加詳細的原因,請看參考資料部分的PEP-3104。

使用非局部語句之后

接下來,我們引入nonlocal語句。


>>> def outside():
        msg = "Outside!"
        def inside():
            nonlocal msg
            msg = "Inside!"
            print(msg)
        inside()
       print(msg)
>>> outside()
Inside!
Inside!

現(xiàn)在,我們在inside函數(shù)的頂部添加了nonlocal msg語句。這個語句的作用,就是告訴Python解釋器在碰到為msg賦值的語句時,應(yīng)該向外層作用域的變量賦值,而不是聲明一個重名的新變量。這樣,兩個函數(shù)的打印結(jié)果就一致了。

nonlocal的用法和global非常類似,只是前者針對的是外層函數(shù)作用域的變量,后者針對的則是全局作用域的變量。

什么時候該使用非局部語句

有時候,你可能會疑惑什么時候才應(yīng)該使用nonlocal。以下面的函數(shù)為例:


>>> def outside():
       d = {"outside": 1} 
       def inside():
            d["inside"] = 2
            print(d)
        inside()
       print(d)
>>> outside()
{'inside': 2, 'outside': 1}
{'inside': 2, 'outside': 1}

你可能會想,因為沒有使用nonlocal,inside函數(shù)中往字典d中插入的"inside": 2鍵值對(key-value pair)不會體現(xiàn)在outside函數(shù)中。你這么想挺合理,但卻是錯的。因為字典插入并不是賦值操作,而是方法調(diào)用(method call)。事實上,往字典中插入一個鍵值對相當于調(diào)用字典對象中的__setitem__方法。


>>> d = {}
>>> d.__setitem__("inside", 2)
>>> d
{'inside': 2}

所以,這個示例中我們可以不使用nonlocal,就能直接操作外層作用域中的變量。

小結(jié)

其實在許多Python程序中,很少用到非局部語句。但是,有了這種語句之后,我們就可以減少不同作用域之間變量名的沖突。非局部語句,也讓我們更加容易地訪問、操作外層作用域中的變量。不過,這在一定程度上也讓語法變得更加復(fù)雜。

有關(guān)變量、語句等術(shù)語的基礎(chǔ)知識,還可以參考《Think Python 2e》的第二章:量、表達式和語句。

參考資料

請點擊閱讀原文,查看相關(guān)鏈接。

Simple Statements
PEP-3104
Global-Nonlocal
PyTips 0x04
A Quick Guide to nonlocal in Python 3

數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗證碼對象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗服務(wù)器是否宕機 new_captcha: data.new_captcha, // 用于宕機時表示是新驗證碼的宕機 product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計時完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }