日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python嵌套函數與nonlocal使用詳細介紹_python

作者:weixin_42576837 ? 更新時間: 2022-11-02 編程語言

理解閉包之前,我們首先需要理解什么是嵌套函數(nested functions)以及非局部(nonloca)關鍵字

嵌套函數

  • 在另一個函數中定義的函數稱為嵌套函數。
  • 嵌套函數可以訪問 這個封閉范圍域內的 變量。
  • 在python中,這些非局部變量只可以在他們的作用域范圍內訪問。

嵌套函數的例子:

#Python program to illustrate
#nested functions
def outerFunction(text):
    text = text
    #該函數定義在函數之內,作為一個內部函數
    def innerFunction():
        print(text)
    #out函數中,調用這個內部函數
    innerFunction()
if __name__ == '__main__':
    outerFunction('Hey !')

嵌套函數中變量的范圍

在一個函數中訪問全局變量之前已經說過了,但是怎么在一個內部函數中訪問外部函數的變量?

def f1():
    #f1的變量
    s = 'hello'
    def f2():
        #f2()內部使用f1的變量
        print(s)
    f2()
f1()

這種訪問方式和 函數內訪問全局變量很類似。

現在我想要在內部函數改變外部函數的變量要怎么做?

def f1():
    #f1的變量
    s = 'hello'
    def f2():
        #f2()內部試圖改變f1的變量
        s = 'hi hi hi'
        print(s)
    f2()
    print(s)
#調用f1()
f1()

f2()內部通過s = 'hi hi hi' 試圖將外部函數的變量值s改變。

但是其實是在f2()內部重新創建了一個新的變量也叫s,所以完全不會對外部的s有影響。

這和函數內部改變全局變量是類似的,不加global,只是創建了一個同名變量。

那么同樣使用global行不行?

def f1():
    #f1的變量
    s = 'hello'
    def f2():
        #f2()內部試圖使用global改變f1的變量
        global s
        s = 'hi hi hi'	#實際是在f2()中創建了一個全局變量
        print(s)
    f2()
    print(s)
#調用f1()
f1()

結果是完全沒有變化的,

global s實際上是在f2()內部聲明s是一個全局變量,是整個程序都可以使用的,它和f1()中的s不是同一個。我們可以在函數外輸出它:

那么如何通過內部函數改變外部函數的變量值呢?其中一種方法是使用nonlocal關鍵字:

def f1():
    #f1的變量
    s = 'hello'
    def f2():
        #f2()使用nonlocal改變f1的變量
        nonlocal s
        s = 'hi hi hi'
        print(s)
    f2()
    print(s)
#調用f1()
f1()

在f2()函數內部成功的修改了f1()函數中的變量s的值

nonlocal

nonlocal 關鍵字被用來在最近的范圍域中引用變量, 在局部變量和全局變量上使用不起作用,用于在全局范圍和本地局部范圍之外的另一個范圍內引用變量。nonlocal關鍵字常常被用在嵌套函數中引用 父函數中的變量。

使用nonlocal的優點

  • 幫助我們訪問上層作用域中的變量
  • 引用的變量被重復使用,因此該變量的內存地址也被重復適使用,所以可以將局部變量保存在內存中

缺點

  • nonloca關鍵字不可以用來引用全局變量和局部變量
  • nonloca關鍵字只能用在嵌套結構中

舉例

使用nonlocal關鍵字修改父函數中的變量

def foo():
    name = 'hello'
    def  bar():
        nonlocal name #修改父函數的變量
        name = 'hi hi'
        print(name)
    #調用bar()
    bar()
    #父函數foo()內輸出name
    print(name)
#調用foo()
foo()

如果使用nonlocal 修改全局變量會怎么樣?

#全局變量
global_name = 'hello'
#外部函數
def f1():
    #內部函數
    def f2():
        #使用nonlocal 聲明,嘗試使用nonlocal 引用全局變量
        nonlocal global_name
        global_name = 'hi hi'#嘗試 修改 
        print(global_name)
    
    #掉用f2()
    f2()
f1()
print(global_name)

報錯信息顯示:沒有叫做global_namenonlocal變量,這是因為:

nonlocal是用在嵌套結構中,用來引用父函數中的局部變量的,但是父函數f1()中沒有叫做global_name的局部變量,對于函數外部的全局變量global_name來說,使用nonlocal是無法引用的,所以python解釋器找不到global_name,自然出錯。

多層嵌套中的nonlocal

def f1():
    name = 'f1'
    def f2():
        name = 'f2'
        def f3():
            #nonlocal 修改父函數的變量,即f2()的name
            nonlocal name
            print(name)  #輸出f2  使用的是f2中的name
            name = 'f3' #對f2中的name修改
            print(name) #輸出f3 修改成功
        f3()
        print(name)#輸出f3,雖然是f2中的name,但是在f3中修改了
    f2()
    print(name)#輸出f1,f1的name,沒有被使用
f1()

所以在多層嵌套的結構成,nonlocal關鍵字會尋找最近的上層,也就是父函數,而不是更上層的爺爺函數。

嵌套函數中局部變量的重用

def counter():
    #c是局部變量
    c = 0
    def count():
        #使用上層函數中的c
        nonlocal c
        c += 1
        return c
    return count

調用外部counter()函數,正常來說,函數調用結束后,內部的局部變量會被銷毀,但是由于counter()內部嵌套的count()使用了nonlocal來使用父函數的局部變量c,所以c是被重用了,即使外層函數調用結束了,c并沒有被銷毀。

參考:

Python Inner Functions

Python nonlocal Keyword

原文鏈接:https://blog.csdn.net/weixin_42576837/article/details/125530032

欄目分類
最近更新