python名稱空間和作用域

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

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

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

一、名稱空間

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

1 內置名稱空間

內置名稱空間:存放Pyhton解釋器自帶的名字,如int、float、len
生命週期:在解釋器啓動時生效,在解釋器關閉時失效

2 全局名稱空間

全局名稱空間:除了內置和局部的名字之外,其餘都存放在全局名稱空間,如下面代碼中的x、func、l、z
生命週期:在文件執行時生效,在文件執行結束後失效

x = 1

def func():
    pass

l = [1, 2]

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

3 局部名稱空間

局部名稱空間:用於存放函數調用期間函數體產生的名字,如下面代碼的f2
生命週期:在文件執行時函數調用期間時生效,在函數執行結束後失效

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

f1() 

4 加載順序

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

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

二、作用域

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

1 全局作用域

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

# 全局作用域
x = 1


def bar():
    print(x)


bar()

輸出

1

2 局部作用域

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

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


f1()

輸出

2

3 注意點

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

# 作用域注意點
x = 1


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


def f2():
    x = 2
    f1()


f2()

輸出

1

4 函數對象+作用域應用

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


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


def bar():
    f()


bar()

輸出

from inner

三、補充知識點

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

2 nonlocal關鍵字

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

x = 1


def f1():
    x = 2

    def f2():
        #         nonlocal x
        x = 3

    f2()
    print(x)

#學習中遇到問題沒人解答?小編創建了一個Python學習交流羣:711312441
f1()

輸出

2
x = 1


def f1():
    x = 2

    def f2():
        nonlocal x
        x = 3

    f2()
    print(x)


f1()

輸出

3

3 注意點

在局部想要修改全局的可變類型,不需要任何聲明,可以直接修改。
在局部如果想要修改全局的不可變類型,需要藉助global聲明,聲明爲全局的變量,即可直接修改。

lis = []


def f1():
    lis.append(1)


print(f"調用函數前: {lis}")
f1()
print(f"調用函數後: {lis}")

輸出

調用函數前: []
調用函數後: [1]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章