日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python基础 F-03 函数-命名空间与作用域

發布時間:2024/1/8 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python基础 F-03 函数-命名空间与作用域 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

函數-命名空間與作用域

文章目錄

  • 函數-命名空間與作用域
    • 一、命名空間
      • 1.1、定義與作用
      • 1.2、分類
      • 1.4、生命周期
        • 命名空間創建周期
        • 命名空間結束周期
    • 二、作用域
      • 2.1、定義與作用
      • 2.2、分類
      • 2.3、查找順序
      • 2.4、相關示例
        • a、局部訪問局部作用域成功示例
        • b、全局訪問正常函數局部作用域失敗示例
        • c、全局方法特殊函數的局部作用域失敗示例
        • d、全局訪問定義在if、for中的全局作用域成功示例
        • e、全局方法導入局部作用域失敗示例
        • f、局部訪問全局作用域成功示例
        • g、局部訪問局部&全局作用域失敗示例
        • h、作用域的靜態特性
        • i、作用域類與類方法同級特性
    • 三、global 和 nonlocal關鍵字
      • 3.1、global關鍵字
      • 3.1、enclosing關鍵字

一、命名空間

1.1、定義與作用

我們在編寫Python程序的過程中,如果要使用變量和函數,都需要先對變量和函數命名后才能使用。這個時候,Python就會把命名后的變量和函數分配到不同的命名空間,并通過名稱來識別它們。

命名空間是什么?

  • 命名空間(Namespace) 是從名稱到對象的映射,大部分的命名空間都是通過 Python 字典來實現的。

命名空間作用是什么?

  • 一是防止命名沖突。比如,在同一.py文件的全局中,不能定義兩個一樣名稱的函數。
  • 二是不同的命名空間對應不同的作用域。比如,在兩個.py文件中,可以分別定義都叫func的函數。

1.2、分類

python程序執行期間會有2個或3個活動的命名空間(函數調用時有3個,函數調用結束后2個)。總結有三種命名空間:

  • 內置命名空間(built-in namespace), Python 語言內置的名稱,比如函數名 abs、char 和異常名稱 BaseException、Exception 等等。任何模塊均可以訪問。
  • 全局命名空間(global namespace),模塊中定義的名稱,記錄了模塊的變量,包括函數、類、其它導入的模塊、模塊級的變量和常量。
  • 局部命名空間(local namespace),每個函數所擁有的命名空間,記錄了函數的變量,包括函數的參數和局部定義的變量。(類中定義的也是)

補充說明:
局部命名空間,這里要區分函數以及類定義。函數的局部命名空間,在函數調用時創建,函數返回結果或拋出異常時被銷毀(每一個遞歸函數都擁有自己的命名空間);類定義的命名空間,在解釋器讀到類定義(class關鍵字)時創建,類定義結束后銷毀。

1.4、生命周期

命名空間創建周期

python解釋器啟動 ->創建內建命名空間 -> 加載模塊 -> 創建全局命名空間 ->函數被調用 ->創建局部命名空間

python解釋器啟動 創建內建命名空間 加載模塊 創建全局命名空間 函數被調用 創建局部命名空間

命名空間結束周期

函數調用結束 -> 銷毀函數對應的局部命名空間 -> python虛擬機(解釋器)退出 ->銷毀全局命名空間 ->銷毀內建命名空間

函數調用結束 銷毀函數對應的局部命名空間 python虛擬機 解釋器 退出 銷毀全局命名空間 銷毀內建命名空間

二、作用域

2.1、定義與作用

作用域是針對命名空間而言,指命名空間在程序里的可應用范圍,或者說是Python程序(文本)的某一段或某幾段,在這些地方,某個命名空間中的名字可以被直接引用。這部分程序就是這個命名空間的作用域。

特別說明
只有函數、類、模塊會產生新的作用域,代碼塊(例如if、for代碼塊)不會產生新的作用域。

2.2、分類

作用域決定了在哪一部分程序可以訪問哪個特定的變量名稱。Python的作用域一共有4種,分別是:

  • L(Local):最內層,包含局部變量,比如一個函數/方法內部。
  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的變量。比如兩個嵌套函數,一個函數(或類) A 里面又包含了一個函數 B ,那么對于 B 中的名稱來說 A 中的作用域就為 nonlocal。
  • G(Global):當前腳本的最外層,比如當前模塊的全局變量。
  • B(Built-in): 包含了內建的變量/關鍵字等。

2.3、查找順序

在一個 python 程序中,直接訪問一個變量,會從內到外依次訪問所有的作用域直到找到,否則會報未定義的錯誤。

  • 規則順序: L –> E –> G –> B。在局部找不到,便會去局部外的局部找(例如閉包),再找不到就會去全局找,再者去內置中找。

  • 查找失敗,它將放棄查找并引發一個 NameError 異常,比如:
NameError: name 'runoob' is not defined。

2.4、相關示例

a、局部訪問局部作用域成功示例

value = '全局的'def print_l():value = '局部的'def print_e():value = '閉包的'print(value)print_e()print(value)print_l() print(value)

上述運行結果:

閉包的 局部的 全局的

b、全局訪問正常函數局部作用域失敗示例

def print_l():value = '局部的'print_l() print(value)

輸出結果:

NameError: name 'value' is not defined

分析:print(value)訪問的是全局的,但代碼中只定義了局部的,故訪問失敗,拋了異常

c、全局方法特殊函數的局部作用域失敗示例

list_1 = [i for i in range(5)]print(i)

輸出結果:

NameError: name 'i' is not defined

分析:lambda、生成器表達式、列表解析式也是函數,都會引入新局部作用域。故全局無法訪問。

d、全局訪問定義在if、for中的全局作用域成功示例

if True:value = '全局的'print(value)for i in range(0, 4):value2 = '全局的'print(value2, i)

輸出結果:

全局的 全局的 3

分析:if、for代碼塊不會產生新的作用域。故if代碼塊中的value, for代碼塊中的value2,i為全局的,故print能夠訪問到。

e、全局方法導入局部作用域失敗示例

def import_sys():import sysimport_sys()print(sys.path)

輸出結果:

NameError: name 'sys' is not defined

分析:在函數內部進行模塊導入時,導入的模塊只在函數內部作用域生效。這個算非正常程序員的寫法了,import語句在函數import_sys中將名字sys和對應模塊綁定,那sys這個名字還是定義在局部作用域,跟上面的例子沒有任務區別。要時刻切記Python的名字,對象,這個其他編程語言不一樣。

f、局部訪問全局作用域成功示例

def test():print(i)# 可正常輸出0i = 0 test()

在局部作用域中可以引用全局作用域中的命名空間。可不要認為i=0這行必須寫在def test()前面,事實上只需要在test()函數調用前寫i=0即可,因為函數的命名空間是在函數被調用時創建的。

g、局部訪問局部&全局作用域失敗示例

def test():print(i)i= 2i = 0 test()

輸出結果:

UnboundLocalError: local variable 'i' referenced before assignment

Python對局部作用域情有獨鐘,解釋器執行到print(i),i在局部作用域沒有。解釋器嘗試繼續執行后面定義了名字i,解釋器就認為代碼在定義之前就是用了名字,所以拋出了這個異常。

總結:

  • 如果局部訪問的變量,在局部沒有定義,按照LEGB原則向上找。一直沒有找到就包NameError異常。
  • 如果局部訪問的變量,在局部沒有定義,按照LEGB原則向上找,也找到了,就會使用正常。
  • 如果局部訪問的變量,在局部有定義,按照LEGB原則向上找,也找到了。就會拋賦值在引用之前的異常。

h、作用域的靜態特性

i = 1def f1():print(i)def f2():i = 2f1()f2() print(i)

輸出結果:

1 1

函數的作用域是靜態的,由函數聲明的位置決定,在哪里聲明,就決定了它的上層作用域是誰,這與調用函數的位置無關。無論在哪里調用,它都會去函數本身的作用域中的命名空間找,找不到在去上一層的命名空間找,切記未必是在調用該函數的作用域的命名空間找。

i、作用域類與類方法同級特性

class A(object):a = 2def fun(self):print(a)new_class = A()new_class.fun()

輸出結果:

NameError: name 'a' is not defined

上文中說過,Python類成員變量與成員函數都有自己的作用域,且各作用域平級。故是平級關系,無法訪問到。需要注意

三、global 和 nonlocal關鍵字

當內部作用域想修改外部作用域的變量時,就要用到global和nonlocal關鍵字了。

3.1、global關鍵字

以下實例修改全局變量 num:

num = 1 def fun1():global num # 需要使用 global 關鍵字聲明print(num) num = 123 # 修改全局的num,局部沒有定義numprint(num) fun1() print(num)

輸出結果:

1 123 123

3.1、enclosing關鍵字

如果要修改嵌套作用域(enclosing 作用域,外層非全局作用域)中的變量則需要 nonlocal 關鍵字了,如下實例

def outer():num = 10def inner():nonlocal num # nonlocal關鍵字聲明num = 100 # 局部沒定義num,修改的是嵌套的num的值print(num)inner()print(num) # 打印局部的num outer()

輸出結果:

100 100

總結

以上是生活随笔為你收集整理的Python基础 F-03 函数-命名空间与作用域的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。