python閉包與裝飾器
閉包
函數(shù)和對(duì)其周圍狀態(tài)(lexical environment,詞法環(huán)境)的引用捆綁在一起構(gòu)成閉包(closure)。也就是說(shuō),閉包可以讓你從內(nèi)部函數(shù)訪問(wèn)外部函數(shù)作用域。
常用語(yǔ)言基本都實(shí)現(xiàn)了閉包。
閉包中最重要的是,我們返回了一個(gè)內(nèi)部函數(shù)。
def power(n):
def func(m):
return m**n
return func
在power函數(shù)中,我們定義了一個(gè)func函數(shù),func函數(shù)接收底數(shù)m,從外部power函數(shù)中拿到指數(shù)n,返回冪m**n。
這個(gè)簡(jiǎn)單的定義可以使我們獲得能夠進(jìn)行任何指數(shù)操作的函數(shù)。
power2 = power(2)
power5 = power(5)
power10 = power(10)
print(power2(4))
print(power5(4))
print(power5(10))
out:
16
1024
100000
閉包使我們能夠通過(guò)函數(shù)創(chuàng)造各種各樣的類似函數(shù),是不是很神奇?
今天我也寫了一個(gè)閉包。它能夠接收gtf文件返回某個(gè)染色體位置的基因。
def get_gene(file="Homo_sapiens_GRCh37_87_geneonly.gtf"):
gtf = pd.read_csv(file, header=None, sep='\t')
gtf['gene_name'] = gtf[8].apply(lambda x: re.search(r'gene_name \"(.*?)\"', x).group(1))
def fetch(chrom, start):
start = int(start)
value = gtf[(gtf[0] == chrom) & (gtf[3] <= start) & (gtf[4] >= start)]['gene_name'].tolist()
if value:
return value[0]
else:
return None
return fetch
創(chuàng)建具體的fetch。
fetch = get_gene()
fetch(10,103454465)
out:
'FBXW4'
這樣就可以避免重復(fù)操作文件,變量值也不會(huì)暴露在環(huán)境中。
裝飾器
裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能。
其實(shí)裝飾器也是一個(gè)閉包,但是我們一般不用裝飾器修改函數(shù)功能。
def square(n):
print(f'square {n}')
return n**2
square(2)
out:
square 2
4
寫一個(gè)裝飾器,能夠在函數(shù)執(zhí)行前打印執(zhí)行時(shí)間。
import time
def decorator(func):
def wrapper(*args,**kwargs):
print(time.time())
return func(*args,**kwargs)
return wrapper
@decorator
def square(n):
print(f'square {n}')
return n**2
out:
1597498618.3460186
square 2
4
其實(shí)@decorator實(shí)現(xiàn)的就是square = decorator(square),這樣就用返回的函數(shù)替換了原來(lái)的square,但是decorator會(huì)在打印時(shí)間后繼續(xù)執(zhí)行原函數(shù),原函數(shù)在裝飾器內(nèi)部以外部函數(shù)變量存在(閉包,不是嗎),這樣就為函數(shù)添加了額外的功能。
學(xué)會(huì),點(diǎn)贊!