名稱空間和作用域


函數內部的函數只能在函數內部調用,不能在函數外部調用,通過接下來的學習你將會知道為什么會出現這種情況。

def f1():
    def f2():
        print('from f2')
    f2()

f2()  # NameError: name 'f2' is not defined

一、名稱空間

名稱空間(name spaces):在內存管理那一章節時,我們曾說到變量的創建其實就是在內存中開辟了一個新的空間。但是我們一直在回避變量名的存儲,其實在內存中有一塊內存存儲變量名與變量間的綁定關系的空間,而這個空間稱為名稱空間。

1.1 內置名稱空間

內置名稱空間:存放Pyhton解釋器自帶的名字,如int、float、len

生命周期:在解釋器啟動時生效,在解釋器關閉時失效

1.2 全局名稱空間

全局名稱空間:除了內置和局部的名字之外,其余都存放在全局名稱空間,如下面代碼中的x、func、l、z

生命周期:在文件執行時生效,在文件執行結束后失效

x = 1


def func():
    pass


l = [1, 2]

if 3 > 2:
    if 4 > 3:
        z = 3

1.3 局部名稱空間

局部名稱空間:用於存放函數調用期間函數體產生的名字,如下面代碼的f2

生命周期:在文件執行時函數調用期間時生效,在函數執行結束后失效

def f1():
    def f2():
        print('from f2')
    f2()

f1() 

46名稱空間與作用域-簡單.png?x-oss-process=style/watermark

1.4 加載順序

由於.py文件是由Python解釋器打開的,因此一定是在Python解釋器中的內置名稱空間加載結束后,文件才開始打開,這個時候才會產生全局名稱空間,但文件內有某一個函數被調用的時候,才會開始產生局部名稱空間,因此名稱空間的加載順序為:內置--》全局--》局部。

1.5 查找順序

由於名稱空間是用來存放變量名與值之間的綁定關系的,所以但凡要查找名字,一定是從三者之一找到,查找順序為:
從當前的所在位置開始查找,如果當前所在的位置為局部名稱空間,則查找順序為:局部--》全局--》內置。

x = 1
y = 2
len = 100


def func():
    y = 3
    len = 1000
    print(f"y: {y}")
    print(f"len: {len}")
    # print(a)  # NameError: name 'a' is not defined


func()
y: 3
len: 1000
x = 1


def func():
    print(x)


x = 10
func()
10

二、作用域

域指的是區域,作用域即作用的區域。

46名稱空間和作用域-地圖.jpg?x-oss-process=style/watermark

2.1 全局作用域

全局作用域:全局有效,全局存活,包含內置名稱空間和全局名稱空間。

# 全局作用域
x = 1


def bar():
    print(x)


bar()
1

2.2 局部作用域

局部作用域:局部有小,臨時存儲,只包含局部名稱空間。

# 局部作用域
def f1():
    def f2():
        def f3():
            print(x)
        x = 2
        f3()
    f2()


f1()
2

2.3 注意點

需要注意的是:作用域關系在函數定義階段就固定死了,與函數的調用無關。

# 作用域注意點
x = 1


def f1():  # 定義階段x=1
    print(x)


def f2():
    x = 2
    f1()


f2()
1

2.4 函數對象+作用域應用

# 作用域應用
def f1():
    def inner():
        print('from inner')
    return inner


f = f1()  # 把局部定義的函數放在全局之中


def bar():
    f()


bar()
from inner

三、補充知識點

3.1 global關鍵字

修改全局作用域中的變量。

x = 1


def f1():
    x = 2

    def f2():
        #         global x  # 修改全局
        x = 3
    f2()


f1()
print(x)
1
x = 1


def f1():
    x = 2

    def f2():
        global x  # 修改全局
        x = 3
    f2()


f1()
print(x)
3

3.2 nonlocal關鍵字

修改局部作用域中的變量。

x = 1


def f1():
    x = 2

    def f2():
        #         nonlocal x
        x = 3

    f2()
    print(x)


f1()
2
x = 1


def f1():
    x = 2

    def f2():
        nonlocal x
        x = 3

    f2()
    print(x)


f1()
3

3.3 注意點

  1. 在局部想要修改全局的可變類型,不需要任何聲明,可以直接修改。
  2. 在局部如果想要修改全局的不可變類型,需要借助global聲明,聲明為全局的變量,即可直接修改。
lis = []


def f1():
    lis.append(1)


print(f"調用函數前: {lis}")
f1()
print(f"調用函數后: {lis}")
調用函數前: []
調用函數后: [1]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM