命名空間:3種python
內置命名空間 —— python解釋器
就是python解釋器一啓動就能夠使用的名字(input、print ...)存儲在內置命名空間中
內置的名字在啓動解釋器的時候被加載進內存裏安全
全局命名空間 —— 咱們寫的代碼但不是函數中的代碼
是在程序從上到下被執行的過程當中依次加載進內存的
放置了咱們設置的全部變量名和函數名閉包
局部命名空間 —— 函數內寫的代碼
就是函數內部定義的名字
當調用函數的時候,纔會產生命名空間,隨着函數執行的結束,這個命名空間就又消失了函數
在局部:能夠使用全局、內置命名空間中的名字
在全局:能夠使用內置命名空間中的名字,不能夠用局部命名空間的名字
在內置:沒有局部和全局命名空間的名字spa
注意:當咱們在全局定義了和內置命名空間中同名的名字時,會使用全局的名字3d
print = "xx" print(print) Traceback (most recent call last): File "E:/LearnPython/review/test.py", line 4, in <module> print(print) TypeError: 'str' object is not callable
做用域:2種code
全局做用域:做用在全局 —— 內置和全局命名空間中的名字都屬於全局做用域 globals()
局部做用域:做用在局部 —— 函數(局部命名空間中的名字屬於局部做用域)locals()blog
對於不可變數據類型,在局部能夠查看全局做用域中的變量,可是不能直接修改。
若是想要修改,須要在程序的一開始添加global聲明(儘可能避免使用global,不安全,會對全局產生影響)
若是在一個局部(函數)內聲明瞭一個global變量,那麼這個變量在局部的全部操做將對全局的變量有效。內存
例如:作用域
a = 1 def func(): global a # 聲明 a += 1 # 對a進行操做 print(a) # 2 func() print(a) # 2
#報錯 UnboundLocalError: local variable 'a' referenced before assignment a = 1 def func(): a += 1 print(a) func()
globals() 與 locals()
globals() 永遠打印全局的名字
locals() 輸出什麼是根據locals所在的位置
a = 1 def func(): b = 2 print(locals()) print(globals()) func() print(globals()) print(locals())
函數的嵌套調用
def max1(a, b): return a if a > b else b def max2(x, y, z): ret1 = max1(x, y) # 函數調用,用ret1接收返回值 return max1(ret1, z) # 再次調用,用ret2接收返回值 ret2 = max2(1, 2, 3) print(ret2) # 3
nonlocal:只能用於聲明局部變量,找上層中離當前函數最近一層的局部變量
注意:聲明瞭nonlocal的內部函數的變量修改會影響到離當前函數最近一層的局部變量
a = 10 def outer(): a = 20 def inner1(): b = 30 def inner2(): nonlocal a a += 1 # 修改變量a,對局部(有關聯的最近一層)有影響,對全局沒影響 print("局部第三層:", a) inner2() print("局部第二層:", b) inner1() print("局部第一層", a) outer() print("全局 :", a)
做用域鏈:使用變量的時候,先從本身的名字空間找,找不到就向外一層一層地找,直到找到爲止,找不到就報錯。
函數名:
def func(): print(123) func() # 函數名就是內存地址 func_ = func # 函數名能夠賦值 func_() l = [func, func_] # 函數名能夠做爲容器類型的元素 print(l) for i in l: i()
def func1(): print(123) # 123 def func2(f): f() return f # 函數名能夠做爲函數的返回值 func3 = func2(func1) # 函數名能夠做爲另外一個函數的參數 func3() # 123
閉包:是一個嵌套函數,內部函數調用外部函數的變量
def outer(): name = "ppd" def inner(): print(name) # 內部inner函數調用了外部outer函數的變量name print(inner.__closure__)
outer()
打印一個函數的closure,有cell就證實是一個閉包。
閉包最多見的用法,在函數的外部去使用它內部的函數。
def outer(): name = "ppd" def inner(): print(name) return inner func = outer() func() # ppd print(func.__name__) # inner print(func.__closure__) # (<cell at 0x0000000000695D68: str object at 0x00000000010AB378>,)