為什么要使用nonlocal


  Python3中加入了新的關鍵字nonlocal,當在一個嵌套的函數中對變量申明為nonlocal時,就明確表示這個變量是外部函數中定義的變量。也許會有這么一個問題:按照python的LEGB原則,在函數本地作用域找不到變量的情況下,解釋器會自動在外層函數尋找,nonlocal關鍵字豈不是顯得多余?   是的,當一個函數在本地作用域找不到變量申明時會向外層函數尋找,這在函數閉包中很常見。如下:

1 def test(num1):
2     def add(num2):
3         return num1 + num2
4     return add
5     
6 a = test(1)
7 b = test(2)
8 print(a(1))
9 print(b(1))

輸出為:

2
3

但是在本地作用域中使用的變量后,還想對此變量進行更改賦值就會報錯。如下:

def test():
    count = 1
    def add():
        print(count)
        count += 1
    return add

a = test()
a()

輸出為:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-6-24732f13d2b6> in <module>()
      7 
      8 a = test()
----> 9 a()

<ipython-input-6-24732f13d2b6> in add()
      2     count = 1
      3     def add():
----> 4         print(count)
      5         count += 1
      6     return add

UnboundLocalError: local variable 'count' referenced before assignment

在上面代碼中,如果在使用count前面加上關鍵字nonlocal申明就可解決這個問題:

def add():
    count = 1
    def fun():
        nonlocal count
        print(count)
        count += 1
    return fun

a = add()
a()
a()

輸出為:

1
2

  上面代碼完美地解決了函數嵌套調用外部變量的問題;另外,如果從另一個角度來看我們給此函數增加了記錄函數狀態的功能。當然,這也可以通過申明全局變量來實現增加函數狀態的功能。當這樣會出現以下問題:

  1. 每次調用函數時,都得在全局作用域申明變量。別人調用函數時還得查看函數內部代碼。

  2. 當函數在多個地方被調用並且同時記錄着很多狀態時,會造成非常地混亂。

  使用nonlocal的好處是,在為函數添加狀態時不用額外地添加全局變量,因此可以大量地調用此函數並同時記錄着多個函數狀態,每個函數都是獨立、獨特的。針對此項功能其實還個一個方法,就是使用類,通過定義__call__可實現在一個實例上直接像函數一樣調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM