函數嵌套、名稱空間及做用域

一、函數的嵌套

函數內嵌套函數,讓內層函數封閉起來,不讓外部直接調用python

def index():
    print("hello world")
def fun():
    index()
fun()

將複雜而且小的功能在函數內部調用,解決代碼結構不清晰問題app

def index():
    register()
    login()
    ...
index()

二、名稱空間

什麼是名稱空間?

存放名字與對象綁定關係的地方,若是想訪問一個變量值,須要先訪問對應的名稱空間,拿到名字與對應的內存地址綁定關係函數

名稱空間的分類

一、內置名稱空間

python提早定義好的名字,就是存放在內置名稱空間ui

生命週期:python解釋器啓動的時候生效,關閉python解釋器失效code

<built-in function print>###內建功能print

二、全局名稱空間

python文件級別的名字,伴隨着.py文件執行打開,執行結束關閉,if 、while、for內部定義的名字只要執行就會存放在全局名稱空間對象

生命週期:啓動執行py文件生效,執行完整個py文件才失效blog

x = 1  # 存在全局名稱空間
if x == 1:
    x = 2   # 存在全局名稱空間
print(x)
while x == 1: 
    x = 3 # 此步未執行,若是條件成立執行到則存放在全局名稱空間內
print(x)

三、局部名稱空間

函數內部定義的名字都是存放在局部名稱空間內生命週期

生命週期:當調用函數時生效,函數體代碼執行完當即失效內存

x = 3  # 存在全局名稱空間
def index():
    x = 1  # 存在局部名稱空間
    print(x) # 同函數體內x能夠更改
index()
print(x)  # 打印是全局名稱空間中x,由於函數執行結束,局部名稱空間內x關閉

名稱空間查找順序:

若是從局部名稱空間執行查找:局部 > 全局 > 內置,內置找不到就報錯作用域

若是從全局名稱空間執行查找: 全局 > 內置,內置找不到就報錯

名稱空間加載順序:

內置 > 全局 > 局部

x=1 # 第四步查找
def index():
    # x = 2 # 第三步查找
    def fun1():
        # x=3 # 第二步查找
        def fun2():
            # x=4 # 第一步查找
            print(x)
        fun2()
    fun1()
index()

函數內使用的名字在定義階段已經規定死了,與你的調用位置無關,在另外一個局部空間沒法修改

x=1
def index():
    x = 2
    print(x) # 查找同級局部,若是沒有再查找全局,不會被另外一個局部名稱空間修改
def fun():
    x = 3
    index()
fun()
>>> 2
x = 1
def inner():
    x = 2
    def wrapper():
        print(x)
    wrapper()
inner()
>>>
2
x = 1
def index(arg=x):  # 定義階段默認參數已經傳入參數1
    print(x)
    print(arg)
x = 2
index()
>>>
# 2
# 1

做用域

名稱空間的做用範圍

一、全局做用域

位於全局名稱空間+內置名稱空間中的名字屬於全局範圍,該範圍內的名字全局能夠調用

二、局部做用域

位於局部名稱空間中的名字屬於局部範圍,該範圍內的名字只能在函數內使用,函數調用結束失效

global:聲明全局變量,在局部做用域內修改全局名稱空間內的變量

x = 1
def index():
    # global x # 聲明全局變量,將x=1修改成x=2
    x = 2
    def fun():
        print(x) # 先從局部做用域內查找,若是沒有則查找全局做用域
index()
print(x)

nonlocal:在局部名稱空間聲明局部變量,修改外層能找到的局部名稱空間內的變量,會從當前函數的外層一層一層查找變量x,若一直到最外層函數,都找不到,則拋出異常

x= 1
def index():
    x=2
    def fun1():
        global x
        x=3
        def fun2():
            x=4
            def fun3():
                nonlocal x
                x = 5
            print(f"1,{x}")
            fun3()
            print(f"2,{x}")
        fun2()
        print(f"3,{x}")
    fun1()
    print(f"4,{x}")
index()
print(x)
>>>
# 1,4
# 2,5
# 3,3
# 4,2
# 3

若是沒有global或nonlocal,正常在局部修改外部的值不能修改,只有可變類型能夠在局部名稱空間修改外部的值

l1 =[1,2,3]
def index(a):
    l1.append(a)
    print(l1)
index(5)
print(l1)
index(6)
>>>
# [1, 2, 3, 5]
# [1, 2, 3, 5]
# [1, 2, 3, 5, 6]
x=1
def index():
    x = 2  # 只能修改一層,此層不能被修改
    def fun1():
        x=3  # 被修改
        def fun2():
            nonlocal x
            x=4
        fun2()
        print(x)
    fun1()
    print(x)
index()
>>>
4
2
相關文章
相關標籤/搜索