13. 閉包
(1) global, nonlocal及local變數
以下是一個例子:
以下的程式透過呼叫outer_func()來產生inner_func()物件,每個inner_func()的呼叫次數存在cnt2中,所有inner_func()的呼叫次數存在cnt1中。
cnt1 = 0
def outer_func(name):
cnt2 = 0
def inner_func():
global cnt1
nonlocal cnt2
cnt1+=1
cnt2+=1
cnt3 = cnt1 - cnt2
print(f'函式:{name}, 所有函式呼叫次數:{cnt1}, 自己呼叫次數:{cnt2}, 其他函式呼叫次數:{cnt3}')
return inner_func
對於內層的inner_func()函式而言, 第1行的cnt1是global變數; 第4行的cnt2是nonlocal變數; 第12行的cnt3是local變數。
主程式:
a = outer_func('Tom')
b = outer_func('Mary')
a()
b()
a()
a()
執行結果:
函式:Tom, 所有函式呼叫次數:1, 自己呼叫次數:1, 其他函式呼叫次數:0 函式:Mary, 所有函式呼叫次數:2, 自己呼叫次數:1, 其他函式呼叫次數:1 函式:Tom, 所有函式呼叫次數:3, 自己呼叫次數:2, 其他函式呼叫次數:1 函式:Tom, 所有函式呼叫次數:4, 自己呼叫次數:3, 其他函式呼叫次數:1
說明

(2) 閉包, closure
建立閉包有下面3個步驟:
建立一個函式(外部函式)內建立一個內部函式(inner function);
讓內部函式使用外部函式的變數(對內部函式而言是nonlocal variable);
回傳內部函式。
因此,閉包包括了內部函式,也包括它使用的外在函式之變數及其內容。
以下是一個例子:
def gen_counter(cnt):
def counter():
nonlocal cnt
cnt+=1
return cnt
return counter
第2-5行,是一個內部函式counter(),它在第3行時引用了外部函式的變數cnt。 第7行,回傳內部函式。
主程式:
a = gen_counter(0) #從0開始累加
print(a())
print(a())
print(a())
print(a())
執行結果:
1 2 3 4
說明:

問題:
from urllib.request import urlopen
def index(url):
def get():
return urlopen(url).read().decode('utf8')
return get
#--------------------------------------
getNTUB = index("http://www.ntub.edu.tw")
print(getNTUB())
請修改以上程式,主程式部分改成以下,讀入的網頁將寫到"ntub.html"檔案中。
getNTUB = index("http://www.ntub.edu.tw", "ntub.html")
print(getNTUB())
Last updated