函數內部的函數只能在函數內部調用,不能在函數外部調用?!
緣由: 名稱空間問題!!!python
名稱空間(name spaces):在內存管理那一章節時,咱們曾說到變量的建立其實就是在內存中開闢了一個新的空間。可是咱們一直在迴避變量名的存儲,其實在內存中有一塊內存存儲變量名與變量間的綁定關係的空間,而這個空間稱爲名稱空間。app
內置名稱空間:存放Pyhton解釋器自帶的名字,如int、float、len函數
生命週期:在解釋器啓動時生效,在解釋器關閉時失效spa
全局名稱空間:除了內置和局部的名字以外,其他都存放在全局名稱空間,以下面代碼中的
x、func、l、z
生命週期:在文件執行時生效,在文件執行結束後失效code
x = 1 def func(): pass l = [1, 2] if 3 > 2: if 4 > 3: z = 3
局部名稱空間:用於存放函數調用期間函數體產生的名字,以下面代碼的f2對象
生命週期:在文件執行時函數調用期間時生效,在函數執行結束後失效生命週期
def f1(): def f2(): print('from f2') f2() f1()
因爲.py文件是由Python解釋器打開的,所以必定是在Python解釋器中的內置名稱空間加載結束後,文件纔開始打開,這個時候纔會產生全局名稱空間,但文件內有某一個函數被調用的時候,纔會開始產生局部名稱空間,所以名稱空間的加載順序爲:內置--》全局--》局部。內存
因爲名稱空間是用來存放變量名與值之間的綁定關係的,因此但凡要查找名字,必定是從三者之一找到,查找順序爲:
從當前的所在位置開始查找,若是當前所在的位置爲局部名稱空間,則查找順序爲:局部--》全局--》內置。作用域
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()
域指的是區域,做用域即做用的區域。
全局做用域:全局有效,全局存活,包含內置名稱空間和全局名稱空間。
# 全局做用域 x = 1 def bar(): print(x) bar()
1
局部做用域:局部有小,臨時存儲,只包含局部名稱空間。
# 局部做用域 def f1(): def f2(): def f3(): print(x) x = 2 f3() f2() f1()
2
須要注意的是:做用域關係在函數定義階段就固定死了,與函數的調用無關。
# 做用域注意點 x = 1 def f1(): # 定義階段x=1 print(x) def f2(): x = 2 f1() f2()
1
# 做用域應用 def f1(): def inner(): print('from inner') return inner f = f1() # 把局部定義的函數放在全局之中 def bar(): f() bar()
from inner
修改全局做用域中的變量.
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
修改局部做用域中的變量。
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
1.在局部想要修改全局的可變類型,不須要任何聲明,能夠直接修改。
2.在局部若是想要修改全局的不可變類型,須要藉助global聲明,聲明爲全局的變量,便可直接修改。
lis = [] def f1(): lis.append(1) print(f"調用函數前: {lis}") f1() print(f"調用函數後: {lis}")
調用函數前: [] 調用函數後: [1]