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