成人视屏在线观看-国产99精品-国产精品1区2区-欧美一级在线观看-国产一区二区日韩-色九九九

您的位置:首頁技術(shù)文章
文章詳情頁

關(guān)于python變量的作用域問題

瀏覽:129日期:2022-07-14 17:41:36

問題描述

有這樣一個(gè)函數(shù):

def outside(): x=[] print(id(x)) def inside():print(id(x))x[:]=[1,2,3]print(id(x)) inside() print(id(x)) print(x)

調(diào)用后沒出現(xiàn)問題,輸出:140560473157960140560473157960140560473157960140560473157960[1, 2, 3]

但是將里面的x換成一個(gè)字符串,如下:

def outside(): x=’outside’ print(id(x)) def inside():print(id(x))x=’inside’print(id(x)) inside() print(id(x)) print(x)

再來進(jìn)行調(diào)用的時(shí)候就變成了:

140560473762872Traceback (most recent call last): File '<stdin>', line 1, in <module> File '<stdin>', line 8, in outside File '<stdin>', line 5, in insideUnboundLocalError: local variable ’x’ referenced before assignment

按照規(guī)則,此時(shí)進(jìn)入inside函數(shù)里,為什么x不指向原來的’outside’字符串了呢?

未定義的變量不是應(yīng)該產(chǎn)生NameError嗎,為什么此處不是?

我原來以為字符串和list都是類似于C中的指針,但現(xiàn)在看來不是這樣,如果可以的話希望能對(duì)這一點(diǎn)進(jìn)行一些介紹,謝謝。

問題解答

回答1:

從易到難一個(gè)個(gè)回答, 因?yàn)槭莻€(gè)人愚見, 所以如果有大神看到說得不正確, 希望能夠指出類似C中的指針: 這個(gè)是正確的, 因?yàn)樵趐y里面, 幾乎所有的事物都是對(duì)象, 就連變量賦值, 也是先生成對(duì)象, 再讓變量指向這個(gè)對(duì)象,而對(duì)象還分可變對(duì)象和不可變對(duì)象, 在對(duì)可變對(duì)象操作時(shí), 是會(huì)影響到其他指向這個(gè)對(duì)象的變量, 例如:

o = [1, 2, 3, 4]b = oprint id(o)print id(b)b[1] = 123123print bprint o輸出:3994637639946376[1, 123123, 3, 4][1, 123123, 3, 4] # o指向的列表也被改變

而對(duì)于不可變對(duì)象, 是直接就放棄舊的對(duì)象, 而指向新的對(duì)象, 例如:

s = ’123123’print id(s)s = ’32131’print id(s)# 輸出:4139276841392808

所以你在操作python對(duì)象時(shí), 需要謹(jǐn)記該對(duì)象是屬于哪種類型, 你的操作又會(huì)不會(huì)因?yàn)檫@些特性而失敗或者沒達(dá)到自己想要的效果.

未定義的變量: python在查找變量時(shí), 將遵循LEGB的順序, 只有都查找完畢還是沒找到的情況下, 才會(huì)觸發(fā)NameError異常, 這個(gè)可以參考我的一篇博文: Python: 作用域(scope) 和 LEGB

UnboundLocalError: 這個(gè)問題是最常見, 也是最難解釋的, 因?yàn)槲覀兛偸窍喈?dāng)然地覺得, 它必定就會(huì)根據(jù)ELGB的順序去查到變量;其實(shí)我們的理解并沒錯(cuò)誤, 只是我們忽略了一點(diǎn):賦值語句,如果函數(shù)代碼段沒有賦值語句, 那么這個(gè)問題是不會(huì)出現(xiàn), 但為什么出現(xiàn)賦值語句就會(huì)報(bào)錯(cuò)呢? 這和python的作用域有關(guān), 在上面那篇文章提到, python作用域并不是動(dòng)態(tài)的,而是靜態(tài)的, 從腳本文件的縮進(jìn), 就能看出來的, 所以在代碼:

x=’outside’ print(id(x)) def inside():print(id(x))x=’inside’print(id(x))

在inside中, 已經(jīng)有了賦值語句, 所以對(duì)于x,他已經(jīng)不會(huì)從enclosing 或者global甚至bulitin里面去查找, 它已經(jīng)被認(rèn)定在local域了, 只是這個(gè)值并沒有和真正的對(duì)象’inside’建立起綁定關(guān)系, 因?yàn)榇a沒有運(yùn)行到真正的賦值語句, 所以, 會(huì)觸發(fā)這個(gè)UnboundLocalError. 而為什么那個(gè)列表會(huì)可以那樣做, 因?yàn)樗麄儍蓚€(gè)是完全不同的操作, 同樣都是print(id(x))list的操作字節(jié)碼是LOAD_DEREF, 而字符串的操作字節(jié)碼是LOAD_FAST, 而x[:]=[1,2,3]/x=’inside’分別對(duì)應(yīng)的字節(jié)碼又是STORE_SLICE+3 和 STORE_FAST, 前者是在原來的基礎(chǔ)上修改, 而后者是重新指向新的對(duì)象, 而這兩種方式的區(qū)別, 決定了,它們?cè)跇?gòu)建函數(shù)時(shí), 以怎樣的形式存放x, 這個(gè)就涉及到python函數(shù)構(gòu)建的原理了, 有興趣可以看看源碼中的object/ceval.c源碼, 這是虛擬機(jī)運(yùn)行的原理, 關(guān)于這個(gè)問題可以簡(jiǎn)單看我另一篇文章, 比較簡(jiǎn)單將UnboundLocalError: 說下那神奇的 UnboundLocalError: local variable x referenced before assignment

回答2:

你在inside函數(shù)里面重新賦值了新的變量x,兩個(gè)x的作用域是不相同的。而導(dǎo)致UnboundLocalError,是因?yàn)槟阍趇nside的作用域里面,打印了一個(gè)沒有初始化的變量。具體看這個(gè)解釋:https://docs.python.org/2/faq...

回答3:

基本上Lin_R已經(jīng)說的很清楚了。outside函數(shù)與inside函數(shù),他們的域是不同的。由于你在inside函數(shù)中對(duì)x進(jìn)行了賦值,當(dāng)在inside函數(shù)中使用變量x時(shí),此時(shí)x就被認(rèn)定是在inside的local域中。此時(shí)的x是不會(huì)使用其他域中的值的。所以在print(x)時(shí),由于x沒有初始化的值,因此出錯(cuò)。雖然在c中可以使用已定義而未賦值的變量,但是python不允許這種情況。

在python3中,有一個(gè)nonlocal語句可以解決這個(gè)問題。

def outside(): x=’outside’ print(id(x)) def inside():nonlocal xprint(id(x))x=’inside’print(id(x)) inside() print(id(x)) print(x)

注意,此時(shí)使用global語句是不行的,因?yàn)樵趃lobal域內(nèi)沒有x這個(gè)變量。

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: a级国产乱理伦片在线 | www.亚洲在线| 亚洲成a人片在线v观看 | 免费高清欧美一区二区视频 | 99精品在线 | 亚洲综合精品一二三区在线 | 精品久久久久久久久久中文字幕 | 嫩草影院成人 | 国产大臿蕉香蕉大视频女 | 在线不卡国产 | 国产午夜精品免费一二区 | 蜜桃88av | 一区二区三区在线免费观看视频 | 国产深夜福利视频网站在线观看 | 国产精品国产三级国产a | 国产美女作爱视频 | 成人免费视频一区二区三区 | avtt天堂网永久资源手机版 | 精品外国呦系列在线观看 | 亚洲乱码一区二区三区国产精品 | 成年女人免费毛片视频永久 | 日韩久操 | 国产成人精品男人免费 | 日韩亚洲欧美综合一区二区三区 | 欧美整片在线观看 | 一个人的视频日本免费 | 国产亚洲精品久久久久久 | a毛片毛费观看 | 国产成人刺激视频在线观看 | 国产成年人在线观看 | 亚洲第一免费视频 | 成人软件网18免费视频 | 一级片aaaa | 亚洲欧美日韩高清在线看 | 韩国女主播青草在线观看 | 在线看毛片网站 | 欧美日韩在线视频 | 欧美性猛片xxxxⅹ免费 | 成人黄色免费网址 | 国产精品视频免费播放 | 孩交啪啪网址 |