内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

根據(jù)Python常見面試題來談談Python閉包

這里根據(jù)我們平常見到的一些Python常見面試題來跟大家說一下關于Python閉包的相關問題!

創(chuàng)新互聯(lián)主要從事成都網(wǎng)站設計、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務沙依巴克,十多年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:028-86922220

題目:

1.什么是閉包?閉包的定義?

2.手寫一個簡單的閉包

3.變量作用域規(guī)則與 nonlocal 關鍵字?

4.閉包的應用

根據(jù)Python常見面試題來談談 Python 閉包

答案要點:

1.首先,我們要了解變量作用域

# 示例一
def test1(a):
 print(a)
 print(b) # 當函數(shù)執(zhí)行到這一步時會報錯。
 # NameError: global name 'b' is not defined
test1(1) 
# 示例二
b = 6
def test2(a):
 print(a)
 print(b) 
test2(1) # 1 6
# 示例三
b = 6
def test3(a):
 print(a)
 print(b) # 當函數(shù)執(zhí)行到這一步仍然會報錯
 # UnboundLocalError: local variable 'b' referenced before assignment
 b = 9 # 比示例二多了一行賦值
test3(1)

學過其他語言,比如 Java ,對示例三的結(jié)果會比較驚訝,在 Java 中類似的情況,不會報錯,會引用外部的全局變量,而如果在內(nèi)部重新賦值后,再次使用則會用局部變量的值。而在 Python 中情況則不一樣,它在編譯函數(shù)時,發(fā)現(xiàn)對 b 有賦值的操作,它判定 b 是一個局部變量,所以在打印 b 時,它會去查詢局部變量b,發(fā)現(xiàn)并沒有賦值,所以會拋出異常。

引用《流暢的Python》中對此的解釋:

這不是缺陷,而是設計選擇:Python 不要求聲明變量,但是假定在函數(shù)定義體中賦值的變量是局部變量。這比 JavaScript 的行為要好多了,JavaScript 也不要求聲明變量,但是如果忘記把變量聲明為局部變量(使用var),可能會在不知情的情況下獲取全局部變量。

上段話第一次看可能會有點不明白,其實簡單來說,Python 就是這樣設計的,它認為在函數(shù)體中,如果對變量有賦值操作,則證明這個變量是一個局部變量,并且它只會從局部變量中去讀取數(shù)據(jù)。這樣設計可以避免我們在不知道的情況下,獲取到全局變量的值,從而導致一些錯誤數(shù)據(jù)的出現(xiàn)。

至于解決方法,就是使用 global 關鍵字,來說明我們使用的是 全局變量 。示例如下:

b = 6
def test4(a):
 print(a)
 global b # 1
 print(b) # 6
 b = 9 
 print(b) # 9 
test4(1)

2.閉包的定義: 簡單來說,閉包的概念就是當我們在函數(shù)內(nèi)定義一個函數(shù)時,這個內(nèi)部函數(shù)使用了外部函數(shù)的臨時變量,且外部函數(shù)的返回值是內(nèi)部函數(shù)的引用時,我們稱之為閉包。有點繞

代碼如下:

# 一個簡單的實現(xiàn)計算平均值的代碼
 
def get_avg():
 scores = [] # 外部臨時變量
 
 def inner_count_avg(val): # 內(nèi)部函數(shù),用于計算平均值
 scores.append(val) # 使用外部函數(shù)的臨時變量
 return sum(scores) / len(scores) # 返回計算出的平均值
 
 return inner_count_avg # 外部函數(shù)返回內(nèi)部函數(shù)引用
 
avg = get_avg()
print(avg(10)) # 10
print(avg(11)) # 10.5
...

3.nonlocal 關鍵字 。上面的代碼,有一個小缺陷,有很多重復的計算,當我們傳入一個新的值想要得到新的平均值時,其他前一次的總和是可以通過外部臨時變量存儲的。于是我們很自然的想到下面的代碼:

# 一個簡單的實現(xiàn)計算平均值的代碼改進版一
def get_avg():
 scores = 0 # 將外部臨時變量由 list 改為一個 整型數(shù)值
 count = 0 # 同時新增一個變量,記錄個數(shù)
 def inner_count_avg(val): # 內(nèi)部函數(shù),用于計算平均值
 scores += val # 使用外部函數(shù)的臨時變量
 count += 1
 return scores / count # 返回計算出的平均值
 return inner_count_avg # 外部函數(shù)返回內(nèi)部函數(shù)引用
avg = get_avg()
print(avg(10)) # 報錯
...

這里報錯的原因,請看第 1 點:變量的作用規(guī)則。因為 scores += val ,其實就是 scores = scores + val,有了賦值操作,則認為 scores 是局部變量了。而我們也沒辦法使用 global 關鍵字,因為此時 scores 和 count 是定義在 get_ave 函數(shù)內(nèi)的,它們倆也是一個局部變量。而為什么我們使用 list 時,沒有出現(xiàn)這個問題呢?也是很好理解的,因為我們使用的是 list.append() 方法,它沒有賦值操作。你可以簡單認為,可變對象(即我們可以通過調(diào)用自身一些方法去做增刪改操作且變量地址值不變)不存在此問題,而不可變對象則會有。

在 Python 3 中引入了一個關鍵詞 nonlocal 解決了這一個問題:

# 一個簡單的實現(xiàn)計算平均值的代碼改進版二
def get_avg():
 scores = 0 # 將外部臨時變量由 list 改為一個 整型數(shù)值
 count = 0 # 同時新增一個變量,記錄個數(shù)
 def inner_count_avg(val): # 內(nèi)部函數(shù),用于計算平均值
 nonlocal count, scores
 scores += val # 使用外部函數(shù)的臨時變量
 count += 1
 return scores / count # 返回計算出的平均值
 return inner_count_avg # 外部函數(shù)返回內(nèi)部函數(shù)引用
avg = get_avg()
print(avg(10)) # 報錯

你也許會說,那在 Python 2 的環(huán)境下應該怎么解決呢?emm~其實呢 也是有辦法的,思路就是將不可變對象變?yōu)榭勺儗ο蠹纯伞>唧w代碼如下:

# -*- coding:utf-8 -*-
class Score:
 pass
def get_avg():
 s = Score() # 使用類對象
 s.scores = 0.0 # 注意 Python 2 中整數(shù)除法是舍棄小數(shù)的,所以要定義為浮點數(shù)
 s.count = 0
 def inner_get_avg(val):
 s.count += 1
 s.scores += val
 return s.scores / s.count
 return inner_get_avg
avg = get_avg()
print(avg(10)) # 10.0
print(avg(11)) # 10.5

4.閉包的應用:首先是裝飾器,裝飾器就是通過修改被裝飾函數(shù),來達到增加新功能的作用。當我們在內(nèi)部函數(shù)去修改被裝飾函數(shù)時,大部分情況都會使用到閉包。簡單示例:

def decorator(func): # 外部函數(shù)的局部變量 func
 def wrapper(*args, **kwargs): # 接受被包裝函數(shù)傳入過來的參數(shù)
 return func(*args, **kwargs) # 使用外部函數(shù)的局部變量 func
 return wrapper
@decorator
def basic_func(name):
 print 'my name is', name
# 等價于
decorator_func(func)

另外一個應用由之前求平均值的示例也可以看出來,可以在重復計算時提高效率。其次還有一個比較重要的應用場景,就是利用“惰性求值”這一特性,這一點在 Django 的 QuerySet 里有體現(xiàn)。當我們利用 ORM 去做 SQL 查詢時,很多時候會根據(jù)不同的判斷條件,去加 filter,加 filter 的時候并沒有真正做查詢,在最終獲取結(jié)果的時候才真正執(zhí)行了查詢。

這里也是根據(jù)我們平常見到的一些Python常見面試題來跟大家講的Python閉包,有補充的伙伴非常歡迎留言補充哈!也希望大家能夠互相學習,取長補短,進步呀!

網(wǎng)站題目:根據(jù)Python常見面試題來談談Python閉包
本文地址:http://www.rwnh.cn/article32/jsddpc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供建站公司、網(wǎng)站建設域名注冊、網(wǎng)頁設計公司、品牌網(wǎng)站建設移動網(wǎng)站建設

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設
抚顺市| 青铜峡市| 江城| 灵寿县| 渝中区| 开原市| 福清市| 武陟县| 通海县| 克东县| 灵丘县| 扎兰屯市| 沈丘县| 晋中市| 芷江| 大化| 托克逊县| 商丘市| 金乡县| 德阳市| 万源市| 冷水江市| 睢宁县| 临洮县| 丹江口市| 新余市| 沈丘县| 昌都县| 烟台市| 易门县| 安阳市| 张家港市| 桂林市| 上林县| 台山市| 丽水市| 彰化市| 克拉玛依市| 紫阳县| 河北省| 旬邑县|