命名空間、全局/局部做用域、做用域鏈、閉包

命名空間: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)

做用域鏈:使用變量的時候,先從本身的名字空間找,找不到就向外一層一層地找,直到找到爲止,找不到就報錯。

函數名:

  1. 函數名能夠賦值給一個變量
  2. 函數名能夠做爲容器類型的元素
  3. 函數名能夠做爲函數的返回值
  4. 函數名能夠做爲另外一個函數的參數
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>,)
相關文章
相關標籤/搜索