1. 程式人生 > >Python-20-內嵌函式和閉包

Python-20-內嵌函式和閉包

1.內嵌函式和閉包

global關鍵字:把變數變為全域性變數

count=5

>>> def MyFun():

global count
count=10
print(count)

>>> print(count)

10

2.內嵌函式(在函式內部定義一個函式)內部函式的作用域都在外部函式之內,出了fun1就不能呼叫fun2了

>>> def fun1():
print('fun(1)正在被呼叫。。。')
def fun2():
print('fun2正在被呼叫。。。')
fun2()

>>> fun1()
fun(1)正在被呼叫。。。

fun2正在被呼叫。。。

3.閉包

在一個內部函式裡,Funy(y)在它外部的作用域引用到了外部的變數x就稱Funy()是Funx()的閉包

在內部函式中只能對外部函式的變數進行訪問,不能修該

>>> def Fun1():
x=5
def Fun2():
X*=X
return x
return Fun2()


>>> Fun1()
Traceback (most recent call last):
  File "<pyshell#55>", line 1, in <module>
    Fun1()
  File "<pyshell#54>", line 6, in Fun1
    return Fun2()
  File "<pyshell#54>", line 4, in Fun2
    X*=X

UnboundLocalError: local variable 'X' referenced before assignment

.利用容器

>>> def Fun1():

x=[5]
def Fun2():
x[0]*=x[0]
return x[0]
return Fun2()


>>> Fun1()

25

4.nonlocal可以用它把內部變數重新定義一下不是區域性變數

>>> def Fun1():
x=[5]
def Fun2():
nonlocal x
x[0]*=x[0]
return x[0]
return Fun2()


>>> Fun1()
25

課後練習:

如果希望在函式中修改全域性變數的值,應該使用什麼關鍵字?

答:global

在巢狀的函式中,如果希望在內部函式修改外部函式的區域性變數,應該使用什麼關鍵字?

答: nonlocal

Python的函式可以巢狀,但要注意訪問的作用域問題哦,請問以下程式碼存在什麼問題呢?

    def outside():  
        print('I am outside!')  
        def inside():  
            print('I am inside!')  
    inside()  

答:inside()是內部函式,不能在外部呼叫 
使用巢狀函式要注意一點就是作用域問題,inside()函式是內嵌在outside()函式中的,所以inside()是人妻,除了身為老公的outside()可以碰(呼叫),在外邊或者別的函式體裡是無法對其進行呼叫的。

請問為什麼程式碼A沒有報錯,但程式碼B卻報錯了?應該如何修改?

    def outside():  
        var = 5  
        def inside():  
            var = 3  
            print(var)  

        inside()  
    outside()  
    def outside():  
        var = 5  
        def inside():  
            print(var)  
            var = 3  

        inside()  
    outside()  

答:這裡outside()函式裡有一個var變數,但要注意的是,內嵌函式inside()也有一個同名的變數,Python為了保護變數的作用域,故將outside()的var變數遮蔽起來,因此此時是無法訪問到外層的var變數的。 
應該修改為:

def outside():  
    var = 5  
    def inside():  
        nonlocal var  
        print(var)  
        var = 8  

    inside()  
outside() 

請問如何訪問funIn()呢?

    def funOut():  
        def funIn():  
            print('賓果!你成功訪問到我啦!')  
        return funIn()  

以下是“閉包”的一個例子,請你目測下會列印什麼內容?

    def funX():  
        x = 5  
        def funY():  
            nonlocal x  
            x += 1  
            return x  
        return funY  
    a = funX()  
    print(a())  
    print(a())  
    print(a())  

答:6 


論壇的解釋: 
有些魚油可能會比較疑惑,這……怎麼跟全域性變數一樣了?區域性變數x不是應該在每次呼叫的時候都重新初始化了嗎?!

其實大家仔細看看就明白了,當a = funX()的時候,只要a變數沒有被重新賦值,funX()就沒有被釋放,也就是說區域性變數x就沒有被重新初始化。

所以當全域性變數不適用的時候,可以考慮使用閉包更穩定和安全,你還可以參考 -> 遊戲中的角色移動:閉包在實際開發中的作用