Python函數(shù)命名空間,作用域LEGB及Global詳析
一、命名空間和作用域
當出現(xiàn)了函數(shù),變量聲明的位置就發(fā)生了變化,不同位置聲明的變量,能訪問這個變量的范圍也出現(xiàn)了限制
1.1 定義
**命名空間:**聲明定義了變量,變量存在的范圍,主要是通過命名空間,來區(qū)分不同范圍中聲明的變量。作用域: 一個數(shù)據(jù)能夠作用的范圍
命名空間根據(jù)范圍的不同,分為以下幾種類型:
1.2 內建命名空間和內建作用域
Python程序中最大的一個命名空間,通常在解釋器運行目標代碼的時候(也就是點RUN的時候),由解釋器創(chuàng)建的一個命名空間,負責初始化(即第一次賦值、第一次創(chuàng)建)系統(tǒng)環(huán)境變量。如:int/type()等
- 內建命名空間加載時間:運行代碼之前,通過解釋器加載好系統(tǒng)的命名空間。包含了int/float/str/type()等等各種數(shù)據(jù)類型或者函數(shù),所以我們在代碼中才可以直接使用這些數(shù)據(jù)類型或者函數(shù)
- 作用:初始化系統(tǒng)環(huán)境變量
- 作用域:內建作用域(Builtin),此空間內的數(shù)據(jù)作用范圍是整個內建空間,包括子空間
- 查看方式:dir()
1.3 全局命名空間和全局作用域
定義: 編寫Python代碼時,創(chuàng)建一個python文件,其中聲明在函數(shù)外部的變量,稱為:全局變量(global)。當前可以聲明全局變量的所有位置稱為全局命名空間
加載時間:解釋器運行目標代碼時,加載全局命名空間,初始化該命名空間中的所有全局變量作用:聲明、定義全局變量的范圍作用域:全局作用(Global)查看方式:globals()查看當前全局命名空間中的所有全局變量,本質上globals()就是一個存儲了數(shù)據(jù)的字典,
例如:
name = "張三" age = 12 grade = ["1",2,"3"] def outer(): a = "a" def inner(): a = "b" return inner fun = outer() fun() print(f"全局變量字典為:{globals()}")
運行結果:
1.3 局部命名空間和局部作用域
定義:當Python文件中聲明函數(shù)時,獨立出來了一個小的作用范圍(函數(shù)內部),通常情況下我們將函數(shù)內部的空間稱為:局部命名空間
加載時間:解釋器運行目標代碼時,加載完全局命名空間之后,加載局部命名空間,初始化局部命名空間中的局部變量
注意:如果是嵌套函數(shù),嵌套函數(shù)是沒有命名空間的,嵌套函數(shù)的空間存于父函數(shù)內,但嵌套函數(shù)是有其自己的作用域的,叫嵌套作用域(內部作用域)
作用:聲明、定義局部變量作用域:局部作用域(嵌套作用域)查看方式:Locals()查看當前命名空間中的所有數(shù)據(jù)
Locals(): 查看當前命名空間中的數(shù)據(jù)
編寫在函數(shù)內部:查看局部命名空間中的數(shù)據(jù)編寫在函數(shù)外部:和globals()一樣的意義
示例:
name = "張三" age = 12 grade = ["1",2,"3"] def outer(): a = "a" print(f"outer局部的數(shù)據(jù):{locals()}") def inner(): a = "b" print(f"inner局部的數(shù)據(jù):{locals()}") return inner fun = outer() fun() print(f"全局變量字典為:{globals()}") print(f"全局部的數(shù)據(jù):{locals()}")
運行結果:
1.4 總結
- 命名空間是一個名詞, 表示了一個可以聲明變量的范圍
- 用作域是一個動詞,表示一個變量起作用的范圍
- 解釋器運行時,命名空間的加載順序:內建命名空間–>全局命名空間–>局部命名空間
- 查詢使用變量,查詢使用順序:內部作用域–>嵌套作用域–>全局作用域–>內建作用域,也就是Python常說的LEGB原則。查找順序通俗的說就是:就近原則,一直找到內建作用域,找不到報:“name is not defined”
1.5 擴展LEGB
- Local,本地作用域,局部作用域的local命名空間。函數(shù)調用時創(chuàng)建,調用結束消亡
- Enclosing,Python2.2時引入嵌套函數(shù),實現(xiàn)了閉包,這個就是嵌套函數(shù)的外部函數(shù)的命名空間
- Global,全局作用域,即一個模塊的命名空間。模塊被import時創(chuàng)建 ,解釋器退出時消亡
- Build-in,內置模塊的命名空間,生命周期從python解釋器啟動時創(chuàng)建到解釋器退出時消亡,例如:print(open),print和open都是的變量
二、Global關鍵字的使用說明
在講述什么是Global之前,讓我們先來看一個例子,以下例子兩條print語句分別打印什么:
x = 100 def fn1(): x +=1 print(f"函數(shù)內的{x}") fn1() print(f"變更后的{x}")
運行結果:
為什么會運行報錯:X在使用前需要先分配變量值,明明我們在全局已經定義了一個X=100
原因:在python動態(tài)語言內,== 賦值即定義== ,在inner內部
- x += 1其實是一個x = x+1的賦值語句,那這個x就會函數(shù)運行在初始化進行加載,變成局部的一個變量
- 而=運算時,從左往右執(zhí)行,在x=的時候已經默許了x是local variable,因此外部作用域的x=100是被屏蔽的。所以x+1中的x相當于一個沒有賦值的變量,從而報錯。
那么怎么解決這個問題?解決的辦法一:使用global關建字將x定義為全局變量,這時在函數(shù)局部就會將x指向全局的變量x
讓我們來看看具體的應用,下面的代碼運行結果如何:
x = 100 def fn1(): x = 10 global x x +=1 print(f"函數(shù)內的{x}") fn1() print(f"變更后的{x}")
運行結果:
為什么還是報錯,我們不是已經使用了global嗎?那是因為我們前面聲明前加了一句:x = 10
x = 10 時會將其置為局部變量,但程序執(zhí)行到global x時,發(fā)現(xiàn)x已經在局部定義過了,所以報錯,所以我們要先聲明再調用
所以我們將程序調整為:
那么問題又來了,下面的例子,global x在inner函數(shù)內可以調用嗎?
x = 100 def outer(): global x x +=1 print(f"ouer的x調用結果{x}") def inner(): x +=1 print(f"inner的x調用結果{x}") return inner a = outer() a()
運行結果:
為什么報錯,不是已經定義了global全局變量,同時也是局部作用域內先定義了嗎?
原因:Global 定義只在全局和定義的當前作用域內起作用,所以上面的例子,global x只在全局作用域和嵌套作用域內可用,如果inner內部想調用,需要做以下調整
特別說明:
global關鍵字是一種破壞函數(shù)封裝的方式,變量未經過傳參即可在函數(shù)內部作用域內使用。所以在日常使用中,**不要使用,那我們要實現(xiàn)這種調用,可以用什么方式呢?python給我提供了一個關鍵字:Nolocal,后續(xù)我的筆記中會詳細提到
到此這篇關于Python函數(shù)命名空間,作用域LEGB及Global詳析的文章就介紹到這了,更多相關Python LEGB與Global內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
深度學習TextRNN的tensorflow1.14實現(xiàn)示例
這篇文章主要介紹了深度學習TextRNN的tensorflow1.14實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01Django 后臺帶有字典的列表數(shù)據(jù)與頁面js交互實例
這篇文章主要介紹了Django 后臺帶有字典的列表數(shù)據(jù)與頁面js交互實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04