摘要
函數(shù)的作用域是一個(gè)默認(rèn)的因素,寫程序時(shí)一定要清楚,閉包、lambda中對(duì)待作用域的方式,筆者遇到了函數(shù)式編程的作用域問題,于是進(jìn)行了初步解讀。
閉包
我們先看看John如何定義閉包
"An object is data with functions, A closure is a function with data" --John D. Cook
閉包中內(nèi)函數(shù)修改外函數(shù)局部變量
在基本的python語法中,一個(gè)函數(shù)可以隨意讀取全局變量,但是要修改全局?jǐn)?shù)據(jù)的時(shí)候有兩種辦法
- global聲明全局變量
- 全局變量是可變數(shù)據(jù)類型時(shí)可以修改
閉包內(nèi)函數(shù)也是類似的情況,在內(nèi)函數(shù)中想修改閉包外部變量,外函數(shù)綁定給內(nèi)函數(shù)的局部變量 的時(shí)候哦:
1 在python3中可以用nonlocal關(guān)鍵字聲明一個(gè)變量,表示這個(gè)變量不是局部變量空間的變量,需要到上一層變量空間棧找這個(gè)變量。
2 在python2中沒有nonlocal這個(gè)關(guān)鍵字,我們可以吧閉包變量改成可變數(shù)據(jù)類型數(shù)據(jù)進(jìn)行修改,比如列表。
作用域
python引用變量的順序
- 當(dāng)前作用域局部變量
- 外層作用域變量
- 當(dāng)前模塊中的全局變量
- python內(nèi)置變量
在調(diào)用時(shí)有幾個(gè)注意事項(xiàng): - 沒有塊級(jí)作用域: 代碼塊里的變量,外部可以調(diào)用
- 局部作用域: 例如函數(shù)內(nèi)部作用域
- 作用域鏈:變量會(huì)由內(nèi)到外,先去自己作用域去找,沒有的話再去上級(jí),直到找不到報(bào)錯(cuò)
- 記住在函數(shù)未執(zhí)行之前,作用域已經(jīng)形成了,作用鏈也生成了
- 聲明全局變量global,如果局部要對(duì)全局變量進(jìn)行修改,需要在局部聲明該全局變量
- nonlocal關(guān)鍵字用來在函數(shù)或其他作用域中使用外層(非全局)變量
name = "global"
def f1():
print(name)
def f2():
name="local"
f1()
def f3():
global name
name="global_edit"
f1()
f2()
f3()
lambda
lambda作為一個(gè)表達(dá)式,定義了一個(gè)匿名函數(shù),一般用來創(chuàng)建短小的匿名函數(shù)
lambda并不對(duì)帶來程序運(yùn)行效率的提升,只會(huì)增加代碼更簡(jiǎn)潔
lambda形式可以從外部作用域引用變量
lambda簡(jiǎn)化了函數(shù)定義的書寫形式,使得代碼更為簡(jiǎn)潔,對(duì)于不熟悉的人降低了代碼的可讀性
匿名函數(shù):沒有名稱的函數(shù),由編譯器指定名稱并分配空間,通常直接做參數(shù)傳遞
例子:
# 新浪面試題
li = [lambda :x for x in range(10)]
res = li[0]()
循環(huán)后x變成了9,li相當(dāng)于每個(gè)函數(shù)都輸入x即9的列表
對(duì)比上個(gè)例子
x = [(lambda x=x:x) for x in range(3)]
x[0]()
0