什么是Python變量作用域
在程序中定義一個(gè)變量時(shí),這個(gè)變量是有作用范圍的,變量的作用范圍被稱為它的作用域。
根據(jù)定義變量的位置,變量分為兩種:
- 局部變量:在函數(shù)中定義的變量,包括參數(shù),都被稱為局部變量。
- 全局變量:在函數(shù)外面、全局范圍內(nèi)定義的變量,被稱為全局變量。
每個(gè)函數(shù)在執(zhí)行時(shí),系統(tǒng)都會(huì)為該函數(shù)分配一塊“臨時(shí)內(nèi)存空間”,所有的局部變量都被保存在這塊臨時(shí)內(nèi)存空間內(nèi)。當(dāng)函數(shù)執(zhí)行完成后,這塊內(nèi)存空間就被釋放了,這些局部變量也就失效了,因此離開函數(shù)之后就不能再訪問局部變量了。
全局變量意味著它們可以在所有函數(shù)內(nèi)被訪問。
不管是在函數(shù)的局部范圍內(nèi)還是在全局范圍內(nèi),都可能存在多個(gè)變量,每個(gè)變量“持有”該變量的值。從這個(gè)角度來看,不管是局部范圍還是全局范圍,這些變量和它們的值就像一個(gè)“看不見”的字典,其中變量名就是字典的 key,變量值就是字典的 value。
實(shí)際上,Python 提供了如下三個(gè)工具函數(shù)來獲取指定范圍內(nèi)的“變量字典”:
globals():該函數(shù)返回全局范圍內(nèi)所有變量組成的“變量字典”。
locals():該函數(shù)返回當(dāng)前局部范圍內(nèi)所有變量組成的“變量字典”。
vars(object):獲取在指定對(duì)象范圍內(nèi)所有變量組成的“變量字典”。如果不傳入object 參數(shù),vars() 和 locals() 的作用完全相同。
globals() 和 locals() 看似完全不同,但它們實(shí)際上也是有聯(lián)系的,關(guān)于這兩個(gè)函數(shù)的區(qū)別和聯(lián)系大致有以下兩點(diǎn):
locals() 總是獲取當(dāng)前局部范圍內(nèi)所有變量組成的“變量字典”,因此,如果在全局范圍內(nèi)(在函數(shù)之外)調(diào)用 locals() 函數(shù),同樣會(huì)獲取全局范圍內(nèi)所有變量組成的“變量字典”;而 globals() 無論在哪里執(zhí)行,總是獲取全局范圍內(nèi)所有變量組成的“變量字典”。
一般來說,使用 locals() 和 globals() 獲取的“變量字典”只應(yīng)該被訪問,不應(yīng)該被修改。但實(shí)際上,不管是使用 globals() 還是使用 locals() 獲取的全局范圍內(nèi)的“變量字典”,都可以被修改,而這種修改會(huì)真正改變?nèi)肿兞勘旧恚旱ㄟ^ locals() 獲取的局部范圍內(nèi)的“變量字典”,即使對(duì)它修改也不會(huì)影響局部變量。
下面程序示范了如何使用 locals()、globals() 函數(shù)訪問局部范圍和全局范圍內(nèi)的“變量字典”:
def test (): age = 20 # 直接訪問age局部變量 print(age) # 輸出20 # 訪問函數(shù)局部范圍的“變量數(shù)組” print(locals()) # {'age': 20} # 通過函數(shù)局部范圍的“變量數(shù)組”訪問age變量 print(locals()['age']) # 20 # 通過locals函數(shù)局部范圍的“變量數(shù)組”改變age變量的值 locals()['age'] = 12 # 再次訪問age變量的值 print('xxx', age) # 依然輸出20 # 通過globals函數(shù)修改x全局變量 globals()['x'] = 19 x = 5 y = 20 print(globals()) # {..., 'x': 5, 'y': 20} # 在全局訪問內(nèi)使用locals函數(shù),訪問的是全局變量的“變量數(shù)組” print(locals()) # {..., 'x': 5, 'y': 20} # 直接訪問x全局變量 print(x) # 5 # 通過全局變量的“變量數(shù)組”訪問x全局變量 print(globals()['x']) # 5 # 通過全局變量的“變量數(shù)組”對(duì)x全局變量賦值 globals()['x'] = 39 print(x) # 輸出39 # 在全局范圍內(nèi)使用locals函數(shù)對(duì)x全局變量賦值 locals()['x'] = 99 print(x) # 輸出99
從上面程序可以清楚地看出,locals() 函數(shù)用于訪問特定范圍內(nèi)的所有變量組成的“變量字典”,而 globals() 函數(shù)則用于訪問全局范圍內(nèi)的全局變量組成的“變量字典”。
全局變量默認(rèn)可以在所有函數(shù)內(nèi)被訪問,但如果在函數(shù)中定義了與全局變量同名的變量,此時(shí)就會(huì)發(fā)生局部變量遮蔽(hide)全局變量的情形。例如如下程序:
name = 'Charlie' def test (): # 直接訪問name全局變量 print(name) # Charlie test() print(name)
上面程序中,第 4 行直接訪問 name 變量,這是允許的,此時(shí)程序?qū)?huì)輸出 Charlie。如果在此之后增加如下一行代碼:
name = '孫悟空'
再次運(yùn)行該程序,將會(huì)看到如下錯(cuò)誤:
UnboundLocalError : local variable ‘name' referenced before assignment
該錯(cuò)誤提示粗體字代碼所訪問的 name 變量還未定義。這是什么原因呢?這正是由于程序在 test() 函數(shù)中增加了“name='孫悟空'”一行代碼造成的。
Python 語法規(guī)定,在函數(shù)內(nèi)部對(duì)不存在的變量賦值時(shí),默認(rèn)就是重新定義新的局部變量。因此這行代碼相當(dāng)于重新定義了 name 局部變量,這樣 name 全局變量就被遮蔽了,所以程序會(huì)報(bào)錯(cuò)。
為了避免這個(gè)問題,可以通過以下兩種方式來修改上面程序:
訪問被遮蔽的全局變量。如果希望程序依然能訪問 name 全局變量,且在函數(shù)中可重新定義 name 局部變量,也就是在函數(shù)中可以訪問被遮蔽的全局變量,此時(shí)可通過 globals() 函數(shù)來實(shí)現(xiàn),將上面程序改為如下形式即可:
name = 'Charlie' def test (): # 直接訪問name全局變量 print(globals()['name']) # Charlie name = '孫悟空' test() print(name) # Charlie
在函數(shù)中聲明全局變量。為了避免在函數(shù)中對(duì)全局變量賦值(不是重新定義局部變量),可使用 global 語句來聲明全局變量。因此,可將程序改為如下形式:
name = 'Charlie' def test (): # 聲明name是全局變量,后面的賦值語句不會(huì)重新定義局部變量 global name # 直接訪問name全局變量 print(name) # Charlie name = '孫悟空' test() print(name) # 孫悟空
增加了“global name”聲明之后,程序會(huì)把 name 變量當(dāng)成全局變量,這意味著 test() 函數(shù)后面對(duì) name 賦值的語句只是對(duì)全局變量賦值,而不是重新定義局部變量。
知識(shí)點(diǎn)擴(kuò)展:
python3 之 變量作用域
作用域: 指命名空間可直接訪問的python程序的文本區(qū)域,這里的 ‘可直接訪問' 意味著:對(duì)名稱的引用(非限定),會(huì)嘗試在命名空間中查找名稱;
- L:local,局部作用域,即函數(shù)中定義的變量;
- E:enclosing,嵌套的父級(jí)函數(shù)的局部作用域,即包含此函數(shù)的上級(jí)函數(shù)的局部作用域,但不是全局的;
- G:globa,全局變量,就是模塊級(jí)別定義的變量;
- B:built-in,內(nèi)建作用域,系統(tǒng)固定模塊里面的變量,比如:int,bytearray等
到此這篇關(guān)于什么是Python變量作用域的文章就介紹到這了,更多相關(guān)Python變量作用域詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用pipenv和pyenv管理多個(gè)相互獨(dú)立的Python虛擬開發(fā)環(huán)境
這篇文章主要介紹了利用pipenv和pyenv管理多個(gè)相互獨(dú)立的Python虛擬開發(fā)環(huán)境,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11利用Python實(shí)現(xiàn)一個(gè)下班倒計(jì)時(shí)程序
身為打工人,一定是想著下班的那一刻吧,這篇文章主要來和大家介紹一下如何利用Python實(shí)現(xiàn)一個(gè)下班倒計(jì)時(shí)程序,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12Python流程控制 while循環(huán)實(shí)現(xiàn)解析
這篇文章主要介紹了Python流程控制 while循環(huán)實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09使用Keras中的ImageDataGenerator進(jìn)行批次讀圖方式
這篇文章主要介紹了使用Keras中的ImageDataGenerator進(jìn)行批次讀圖方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06Python圖像運(yùn)算之圖像點(diǎn)運(yùn)算與灰度化處理詳解
這篇文章主要介紹了圖像點(diǎn)運(yùn)算的灰度化處理的相關(guān)知識(shí),包括各種灰度算法的實(shí)現(xiàn),以及灰度線性變換和灰度非線性變換。需要的可以參考一下2022-02-02tensorflow 固定部分參數(shù)訓(xùn)練,只訓(xùn)練部分參數(shù)的實(shí)例
今天小編就為大家分享一篇tensorflow 固定部分參數(shù)訓(xùn)練,只訓(xùn)練部分參數(shù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-01-01