日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python函數命名空間,作用域LEGB及Global詳析_python

作者:測試工程師Jane ? 更新時間: 2022-11-02 編程語言

一、命名空間和作用域

當出現了函數,變量聲明的位置就發生了變化,不同位置聲明的變量,能訪問這個變量的范圍也出現了限制

1.1 定義

**命名空間:**聲明定義了變量,變量存在的范圍,主要是通過命名空間,來區分不同范圍中聲明的變量。作用域: 一個數據能夠作用的范圍

命名空間根據范圍的不同,分為以下幾種類型:

1.2 內建命名空間和內建作用域

Python程序中最大的一個命名空間,通常在解釋器運行目標代碼的時候(也就是點RUN的時候),由解釋器創建的一個命名空間,負責初始化(即第一次賦值、第一次創建)系統環境變量。如:int/type()等

  • 內建命名空間加載時間:運行代碼之前,通過解釋器加載好系統的命名空間。包含了int/float/str/type()等等各種數據類型或者函數,所以我們在代碼中才可以直接使用這些數據類型或者函數
  • 作用:初始化系統環境變量
  • 作用域:內建作用域(Builtin),此空間內的數據作用范圍是整個內建空間,包括子空間
  • 查看方式:dir()

1.3 全局命名空間和全局作用域

定義: 編寫Python代碼時,創建一個python文件,其中聲明在函數外部的變量,稱為:全局變量(global)。當前可以聲明全局變量的所有位置稱為全局命名空間

加載時間:解釋器運行目標代碼時,加載全局命名空間,初始化該命名空間中的所有全局變量作用:聲明、定義全局變量的范圍作用域:全局作用(Global)查看方式:globals()查看當前全局命名空間中的所有全局變量,本質上globals()就是一個存儲了數據的字典,

例如:

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文件中聲明函數時,獨立出來了一個小的作用范圍(函數內部),通常情況下我們將函數內部的空間稱為:局部命名空間

加載時間:解釋器運行目標代碼時,加載完全局命名空間之后,加載局部命名空間,初始化局部命名空間中的局部變量

注意:如果是嵌套函數,嵌套函數是沒有命名空間的,嵌套函數的空間存于父函數內,但嵌套函數是有其自己的作用域的,叫嵌套作用域(內部作用域)

作用:聲明、定義局部變量作用域:局部作用域(嵌套作用域)查看方式:Locals()查看當前命名空間中的所有數據

Locals(): 查看當前命名空間中的數據

編寫在函數內部:查看局部命名空間中的數據編寫在函數外部:和globals()一樣的意義

示例:

name = "張三"
age = 12
grade = ["1",2,"3"]
def outer():
    a = "a"
    print(f"outer局部的數據:{locals()}")
    def inner():
        a = "b"
        print(f"inner局部的數據:{locals()}")
    return inner

fun = outer()
fun()
print(f"全局變量字典為:{globals()}")
print(f"全局部的數據:{locals()}")

運行結果:

1.4 總結

  • 命名空間是一個名詞, 表示了一個可以聲明變量的范圍
  • 用作域是一個動詞,表示一個變量起作用的范圍
  • 解釋器運行時,命名空間的加載順序:內建命名空間–>全局命名空間–>局部命名空間
  • 查詢使用變量,查詢使用順序:內部作用域–>嵌套作用域–>全局作用域–>內建作用域,也就是Python常說的LEGB原則。查找順序通俗的說就是:就近原則,一直找到內建作用域,找不到報:“name is not defined”

1.5 擴展LEGB

  • Local,本地作用域,局部作用域的local命名空間。函數調用時創建,調用結束消亡
  • Enclosing,Python2.2時引入嵌套函數,實現了閉包,這個就是嵌套函數的外部函數的命名空間
  • Global,全局作用域,即一個模塊的命名空間。模塊被import時創建 ,解釋器退出時消亡
  • Build-in,內置模塊的命名空間,生命周期從python解釋器啟動時創建到解釋器退出時消亡,例如:print(open),print和open都是的變量

二、Global關鍵字的使用說明

在講述什么是Global之前,讓我們先來看一個例子,以下例子兩條print語句分別打印什么:

x = 100
def fn1():
    x +=1
    print(f"函數內的{x}")
fn1()
print(f"變更后的{x}")

運行結果:

為什么會運行報錯:X在使用前需要先分配變量值,明明我們在全局已經定義了一個X=100
原因:在python動態語言內,== 賦值即定義== ,在inner內部

  • x += 1其實是一個x = x+1的賦值語句,那這個x就會函數運行在初始化進行加載,變成局部的一個變量
  • 而=運算時,從左往右執行,在x=的時候已經默許了x是local variable,因此外部作用域的x=100是被屏蔽的。所以x+1中的x相當于一個沒有賦值的變量,從而報錯。

那么怎么解決這個問題?解決的辦法一:使用global關建字將x定義為全局變量,這時在函數局部就會將x指向全局的變量x

讓我們來看看具體的應用,下面的代碼運行結果如何:

x = 100
def fn1():
    x = 10
    global x
    x +=1
    print(f"函數內的{x}")
fn1()
print(f"變更后的{x}")

運行結果:

為什么還是報錯,我們不是已經使用了global嗎?那是因為我們前面聲明前加了一句:x = 10
x = 10 時會將其置為局部變量,但程序執行到global x時,發現x已經在局部定義過了,所以報錯,所以我們要先聲明再調用

所以我們將程序調整為:

那么問題又來了,下面的例子,global x在inner函數內可以調用嗎?

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關鍵字是一種破壞函數封裝的方式,變量未經過傳參即可在函數內部作用域內使用。所以在日常使用中,**不要使用,那我們要實現這種調用,可以用什么方式呢?python給我提供了一個關鍵字:Nolocal,后續我的筆記中會詳細提到

原文鏈接:https://blog.csdn.net/totorobig/article/details/126687921

欄目分類
最近更新