【@】符號(hào)在python中是裝飾器的意思。
目前創(chuàng)新互聯(lián)建站已為上千的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、鄂城網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
裝飾器對(duì)一個(gè)可調(diào)用對(duì)象(函數(shù)、方法、類等等)進(jìn)行裝飾,它返回的也是一個(gè)可調(diào)用對(duì)象。
一般情況下,裝飾器是對(duì)被裝飾對(duì)象的修飾與增強(qiáng)。用現(xiàn)實(shí)事物類比的話,可以類比為中間商:中間商不生產(chǎn)產(chǎn)品,它將工廠生產(chǎn)的產(chǎn)品進(jìn)行包裝、運(yùn)輸后再銷售給顧客。裝飾器不實(shí)現(xiàn)核心功能,它提供對(duì)目標(biāo)函數(shù)調(diào)用的封裝與強(qiáng)。
它裝飾的方法返回值是一個(gè)對(duì)象(BillList、Bill、List[BillDetail]等),而裝飾器【enabled_cache】的作用如它的名稱一樣:使用緩存??梢钥吹剑@個(gè)裝飾器函數(shù)中定義了一個(gè)函數(shù)【wrapper】然后將這個(gè)wrapper作為返回值。這樣,原本調(diào)用ProductionBos.bill_with_last_week的代碼就不需要做任何改變就能享受到ProductionBos.bill_with_last_week原有的功能(得到一個(gè)BillList對(duì)象)和enabled_cache提供的附加功能(如果該對(duì)象有緩存,就不再?gòu)臄?shù)據(jù)庫查詢)。
循環(huán)是一種常用的程序控制結(jié)構(gòu)。我們常說,機(jī)器相比人類的最大優(yōu)點(diǎn)之一,就是機(jī)器可以不眠不休的重復(fù)做某件事情,但人卻不行。而“循環(huán)”,則是實(shí)現(xiàn)讓機(jī)器不斷重復(fù)工作的關(guān)鍵概念。
在循環(huán)語法方面,Python 表現(xiàn)的即傳統(tǒng)又不傳統(tǒng)。它雖然拋棄了常見的 for(init;condition;incrment) 三段式結(jié)構(gòu),但還是選擇了 for 和 while 這兩個(gè)經(jīng)典的關(guān)鍵字來表達(dá)循環(huán)。絕大多數(shù)情況下,我們的循環(huán)需求都可以用 forin來滿足, while相比之下用的則更少些。
雖然循環(huán)的語法很簡(jiǎn)單,但是要寫好它確并不容易。在這篇文章里,我們將探討什么是“地道”的循環(huán)代碼,以及如何編寫它們。
什么是“地道”的循環(huán)?
“地道”這個(gè)詞,通常被用來形容某人做某件事情時(shí),非常符合當(dāng)?shù)貍鹘y(tǒng),做的非常好。打個(gè)比方,你去參加一個(gè)朋友聚會(huì),同桌的有一位廣東人,對(duì)方一開口,句句都是標(biāo)準(zhǔn)京腔、完美兒化音。那你可以對(duì)她說:“您的北京話說的真地道”。
既然“地道”這個(gè)詞形容的經(jīng)常是口音、做菜的口味這類實(shí)實(shí)在在的東西,那“地道”的循環(huán)代碼又是什么意思呢?讓我拿一個(gè)經(jīng)典的例子來解釋一下。
如果你去問一位剛學(xué)習(xí) Python 一個(gè)月的人:“如何在遍歷一個(gè)列表的同時(shí)獲取當(dāng)前下標(biāo)?”。他可能會(huì)交出這樣的代碼:
?
上面的循環(huán)雖然沒錯(cuò),但它確一點(diǎn)都不“地道”。一個(gè)擁有三年 Python 開發(fā)經(jīng)驗(yàn)的人會(huì)說,代碼應(yīng)該這么寫:
enumerate() 是 Python 的一個(gè)內(nèi)置函數(shù),它接收一個(gè)“可迭代”對(duì)象作為參數(shù),然后返回一個(gè)不斷生成 (當(dāng)前下標(biāo),當(dāng)前元素) 的新可迭代對(duì)象。這個(gè)場(chǎng)景使用它最適合不過。
所以,在上面的例子里,我們會(huì)認(rèn)為第二段循環(huán)代碼比第一段更“地道”。因?yàn)樗酶庇^的代碼,更聰明的完成了工作。
enumerate() 所代表的編程思路
不過,判斷某段循環(huán)代碼是否地道,并不僅僅是以知道或不知道某個(gè)內(nèi)置方法作為標(biāo)準(zhǔn)。我們可以從上面的例子挖掘出更深層的東西。
如你所見,Python 的 for 循環(huán)只有 forin這一種結(jié)構(gòu),而結(jié)構(gòu)里的前半部分 - 賦值給 item- 沒有太多花樣可玩。所以后半部分的 可迭代對(duì)象 是我們唯一能夠大做文章的東西。而以 enumerate() 函數(shù)為代表的“修飾函數(shù)”,剛好提供了一種思路:通過修飾可迭代對(duì)象來優(yōu)化循環(huán)本身。
這就引出了我的第一個(gè)建議。
建議1:使用函數(shù)修飾被迭代對(duì)象來優(yōu)化循環(huán)
使用修飾函數(shù)處理可迭代對(duì)象,可以在各種方面影響循環(huán)代碼。而要找到合適的例子來演示這個(gè)方法,并不用去太遠(yuǎn),內(nèi)置模塊 itertools 就是一個(gè)絕佳的例子。
簡(jiǎn)單來說,itertools 是一個(gè)包含很多面向可迭代對(duì)象的工具函數(shù)集。我在之前的系列文章《容器的門道》里提到過它。
如果要學(xué)習(xí) itertools,那么 Python 官方文檔 是你的首選,里面有非常詳細(xì)的模塊相關(guān)資料。但在這篇文章里,側(cè)重點(diǎn)將和官方文檔稍有不同。我會(huì)通過一些常見的代碼場(chǎng)景,來詳細(xì)解釋它是如何改善循環(huán)代碼的。
1. 使用 product 扁平化多層嵌套循環(huán)
雖然我們都知道“扁平的代碼比嵌套的好”。但有時(shí)針對(duì)某類需求,似乎一定得寫多層嵌套循環(huán)才行。比如下面這段:
?
對(duì)于這種需要嵌套遍歷多個(gè)對(duì)象的多層循環(huán)代碼,我們可以使用 product() 函數(shù)來優(yōu)化它。product() 可以接收多個(gè)可迭代對(duì)象,然后根據(jù)它們的笛卡爾積不斷生成結(jié)果。
?
相比之前的代碼,使用 product() 的函數(shù)只用了一層 for 循環(huán)就完成了任務(wù),代碼變得更精煉了。
2. 使用 islice 實(shí)現(xiàn)循環(huán)內(nèi)隔行處理
有一份包含 Reddit 帖子標(biāo)題的外部數(shù)據(jù)文件,里面的內(nèi)容格式是這樣的:
?
可能是為了美觀,在這份文件里的每?jī)蓚€(gè)標(biāo)題之間,都有一個(gè) "---" 分隔符?,F(xiàn)在,我們需要獲取文件里所有的標(biāo)題列表,所以在遍歷文件內(nèi)容的過程中,必須跳過這些無意義的分隔符。
參考之前對(duì) enumerate() 函數(shù)的了解,我們可以通過在循環(huán)內(nèi)加一段基于當(dāng)前循環(huán)序號(hào)的 if 判斷來做到這一點(diǎn):
?
但對(duì)于這類在循環(huán)內(nèi)進(jìn)行隔行處理的需求來說,如果使用 itertools 里的 islice() 函數(shù)修飾被循環(huán)對(duì)象,可以讓循環(huán)體代碼變得更簡(jiǎn)單直接。
islice(seq,start,end,step) 函數(shù)和數(shù)組切片操作( list[start:stop:step] )有著幾乎一模一樣的參數(shù)。如果需要在循環(huán)內(nèi)部進(jìn)行隔行處理的話,只要設(shè)置第三個(gè)遞進(jìn)步長(zhǎng)參數(shù) step 值為 2 即可(默認(rèn)為 1)。
?
3. 使用 takewhile 替代 break 語句
有時(shí),我們需要在每次循環(huán)開始時(shí),判斷循環(huán)是否需要提前結(jié)束。比如下面這樣:
?
對(duì)于這類需要提前中斷的循環(huán),我們可以使用 takewhile() 函數(shù)來簡(jiǎn)化它。takewhile(predicate,iterable)會(huì)在迭代 iterable 的過程中不斷使用當(dāng)前對(duì)象作為參數(shù)調(diào)用 predicate 函數(shù)并測(cè)試返回結(jié)果,如果函數(shù)返回值為真,則生成當(dāng)前對(duì)象,循環(huán)繼續(xù)。否則立即中斷當(dāng)前循環(huán)。
使用 takewhile 的代碼樣例:
?
itertools 里面還有一些其他有意思的工具函數(shù),他們都可以用來和循環(huán)搭配使用,比如使用 chain 函數(shù)扁平化雙層嵌套循環(huán)、使用 zip_longest 函數(shù)一次同時(shí)循環(huán)多個(gè)對(duì)象等等。
篇幅有限,我在這里不再一一介紹。如果有興趣,可以自行去官方文檔詳細(xì)了解。
4. 使用生成器編寫自己的修飾函數(shù)
除了 itertools 提供的那些函數(shù)外,我們還可以非常方便的使用生成器來定義自己的循環(huán)修飾函數(shù)。
讓我們拿一個(gè)簡(jiǎn)單的函數(shù)舉例:
?
在上面的函數(shù)里,循環(huán)體內(nèi)為了過濾掉所有奇數(shù),引入了一條額外的 if 判斷語句。如果要簡(jiǎn)化循環(huán)體內(nèi)容,我們可以定義一個(gè)生成器函數(shù)來專門進(jìn)行偶數(shù)過濾:
?
將 numbers 變量使用 even_only 函數(shù)裝飾后, sum_even_only_v2 函數(shù)內(nèi)部便不用繼續(xù)關(guān)注“偶數(shù)過濾”邏輯了,只需要簡(jiǎn)單完成求和即可。
Hint:當(dāng)然,上面的這個(gè)函數(shù)其實(shí)并不實(shí)用。在現(xiàn)實(shí)世界里,這種簡(jiǎn)單需求最適合直接用生成器/列表表達(dá)式搞定:sum(numfornuminnumbersifnum%2==0)
建議2:按職責(zé)拆解循環(huán)體內(nèi)復(fù)雜代碼塊
我一直覺得循環(huán)是一個(gè)比較神奇的東西,每當(dāng)你寫下一個(gè)新的循環(huán)代碼塊,就好像開辟了一片黑魔法陣,陣內(nèi)的所有內(nèi)容都會(huì)開始無休止的重復(fù)執(zhí)行。
但我同時(shí)發(fā)現(xiàn),這片黑魔法陣除了能帶來好處,它還會(huì)引誘你不斷往陣內(nèi)塞入越來越多的代碼,包括過濾掉無效元素、預(yù)處理數(shù)據(jù)、打印日志等等。甚至一些原本不屬于同一抽象的內(nèi)容,也會(huì)被塞入到同一片黑魔法陣內(nèi)。
修飾符,比如說
class A:
@staticmethod
def m(self):
pass
就相當(dāng)于
class A:
def m(self):
pass
m = staticmethod(m)
其實(shí)就是一調(diào)用一個(gè)函數(shù)參數(shù)為下行的變量,并且替換它
擴(kuò)展資料:
函數(shù)修飾符
@用做函數(shù)的修飾符,可以在模塊或者類的定義層內(nèi)對(duì)函數(shù)進(jìn)行修飾,出現(xiàn)在函數(shù)定義的前一行,不允許和函數(shù)定義在同一行。
一個(gè)修飾符就是一個(gè)函數(shù),它將被修飾的函數(shù)作為參數(shù),并返回修飾后的同名函數(shù)或其他可調(diào)用的東西。
在Python的函數(shù)中偶爾會(huì)看到函數(shù)定義的上一行有@functionName的修飾,當(dāng)解釋器讀到@這樣的修飾符的時(shí)候會(huì)優(yōu)先解除@后的內(nèi)容,直接就把@的下一行的函數(shù)或者類作為@后邊函數(shù)的參數(shù),然后將返回值賦給下一個(gè)修飾的函數(shù)對(duì)象。
參考資料來源:百度百科-Python (計(jì)算機(jī)程序設(shè)計(jì)語言)
新聞名稱:python的函數(shù)修飾的簡(jiǎn)單介紹
轉(zhuǎn)載來源:http://vcdvsql.cn/article48/dopgcep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、虛擬主機(jī)、搜索引擎優(yōu)化、面包屑導(dǎo)航、外貿(mào)網(wǎng)站建設(shè)、營(yíng)銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容