閉包:
在函數A中又定義了函數B,并且,内部函數B可以引用外部函數A的參數和局部變量,當A傳回函數B時,相關參數和變量都儲存在傳回的函數中,這種稱為“閉包(Closure)”的程式結構擁有極大的威力。
利用閉包傳回一個計數器函數,每次調用它傳回遞增整數:
第一種方法:
# -*- coding: utf-8 -*-
def createCounter():
n=0
def counter():
nonlocal n #必須加nonlocal
n=n+1
return n
return counter
# 測試:
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = createCounter()
if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:
print('測試通過!')
else:
print('測試失敗!'
總結:
這段代碼如果不加nonlocal,會報錯,這是因為對于createCounter函數,n是局部變量,對于counter函數,n是非全局的外部變量。當在counter中對n進行修改時,會将n視為counter的局部變量,屏蔽掉createCounter中對n的定義;如果僅僅在counter中對n進行讀取,則不會出現這個錯誤。
而寫成清單則不會報錯了, 改變清單L中第一個元素的值,但并沒有改變清單L的記憶體位址。
第二種方法:
def createCounter():
L=[0] # 清單L的記憶體位址在初次調用時已經給定,且L[0]即第一個元素指向整數0
def counter():
L[0]+=1 #改變清單L中第一個元素的值,但并沒有改變清單L的記憶體位址
return L[0]
return counter