Python高級(jí)用法總結(jié)
列表推導(dǎo)(list comprehensions)
場(chǎng)景1:將一個(gè)三維列表中所有一維數(shù)據(jù)為a的元素合并,組成新的二維列表。
最簡(jiǎn)單的方法:新建列表,遍歷原三維列表,判斷一維數(shù)據(jù)是否為a,若為a,則將該元素append至新列表中。
缺點(diǎn):代碼太繁瑣,對(duì)于Python而言,執(zhí)行速度會(huì)變慢很多。
針對(duì)場(chǎng)景1,我們首先應(yīng)該想到用列表解析式來(lái)解決處理,一行代碼即可解決:
lista = [item for item in array if item[0] == 'a']
那么,何為列表解析式?
官方解釋?zhuān)毫斜斫馕鍪绞荘ython內(nèi)置的非常簡(jiǎn)單卻強(qiáng)大的可以用來(lái)創(chuàng)建list的生成式。
強(qiáng)大具體如何體現(xiàn)?
可以看到,使用列表解析式的寫(xiě)法更加簡(jiǎn)短,除此之外,因?yàn)槭荘ython內(nèi)置的用法,底層使用C語(yǔ)言實(shí)現(xiàn),相較于編寫(xiě)Python代碼而言,運(yùn)行速度更快。
場(chǎng)景2: 對(duì)于一個(gè)列表,既要遍歷索引又要遍歷元素。
這里可以使用Python內(nèi)建函數(shù)enumerate,在循環(huán)中更好的獲取獲得索引。
array = ['I', 'love', 'Python'] for i, element in enumerate(array): array[i] = '%d: %s' % (i, seq[i])
可以使用列表推導(dǎo)式對(duì)其進(jìn)行重構(gòu):
def getitem(index, element): return '%d: %s' % (index, element) array = ['I', 'love', 'Python'] arrayIndex = [getitem(index, element) for index, element in enumerate(array)]
據(jù)說(shuō)這種寫(xiě)法更加的Pythonic。
總結(jié):如果要對(duì)現(xiàn)有的可迭代對(duì)象做一些處理,然后生成新的列表,使用列表推導(dǎo)式將是最便捷的方法。
迭代器和生成器
迭代器(Iterator)
這里的迭代可以指for循環(huán),在Python中,對(duì)于像list,dict和文件等而言,都可以使用for循環(huán),但是它們并不是迭代器,它們屬于可迭代對(duì)象。
什么可迭代對(duì)象
最簡(jiǎn)單的解釋?zhuān)嚎梢允褂胒or...in...語(yǔ)句進(jìn)行循環(huán)的對(duì)象,就是可迭代對(duì)象(Iterable),可以使用isinstance()方法進(jìn)行判斷。
from collections import Iterable type = isinstance('python', Iterable) print type
什么是迭代器
迭代器指的是可以使用next()方法來(lái)回調(diào)的對(duì)象,可以對(duì)可迭代對(duì)象使用iter()方法,將其轉(zhuǎn)換為迭代器。
temp = iter([1, 2, 3]) print type(temp) print next(temp)
此時(shí)temp就是一個(gè)迭代器。所以說(shuō),迭代器基于兩個(gè)方法:
- next:返回下一個(gè)項(xiàng)目
- iter 返回迭代器本身
可理解為可被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象就是迭代器,在定義一個(gè)裝飾器時(shí)將需要同時(shí)定義這兩個(gè)方法。
迭代器的優(yōu)勢(shì)
在構(gòu)建迭代器時(shí),不是將所有的元素一次性的加載,而是等調(diào)用next方法時(shí)返回元素,所以不需要考慮內(nèi)存的問(wèn)題。
迭代器應(yīng)用場(chǎng)景
那么,具體在什么場(chǎng)景下可以使用迭代器呢?
- 數(shù)列的數(shù)據(jù)規(guī)模巨大
- 數(shù)列有規(guī)律,但是不能使用列表推導(dǎo)式描述。
生成器
生成器是一種高級(jí)迭代器,使得需要返回一系列元素的函數(shù)所需的代碼更加的簡(jiǎn)單和高效(不像創(chuàng)建迭代器代碼那般冗長(zhǎng))。
生成器函數(shù)
生成器函數(shù)基于yield指令,可以暫停一個(gè)函數(shù)并返回中間結(jié)果。當(dāng)需要一個(gè)將返回一個(gè)序列或在循環(huán)中執(zhí)行的函數(shù)時(shí),就可以使用生成器,因?yàn)楫?dāng)這些元素被傳遞到另一個(gè)函數(shù)中進(jìn)行后續(xù)處理時(shí),一次返回一個(gè)元素可以有效的提升整體性能。
常見(jiàn)的應(yīng)用場(chǎng)景是使用生成器的流數(shù)據(jù)緩沖區(qū)。
生成器表達(dá)式
生成式表達(dá)式是一種實(shí)現(xiàn)生成器的便捷方式,將列表推導(dǎo)式的中括號(hào)替換為圓括號(hào)。
和列表推導(dǎo)式的區(qū)別:列表生成式可以直接創(chuàng)建一個(gè)表,但是生成器表達(dá)式是一種邊循環(huán)邊計(jì)算,使得列表的元素可以在循環(huán)過(guò)程中一個(gè)個(gè)的推算出來(lái),不需要?jiǎng)?chuàng)建完整的列表,從而節(jié)省了大量的空間。
g = (x * x for x in range(10))
總結(jié):生成器是一種高級(jí)迭代器。生成器的優(yōu)點(diǎn)是延遲計(jì)算,一次返回一個(gè)結(jié)果,這樣非常適用于大數(shù)據(jù)量的計(jì)算。但是,使用生成器必須要注意的一點(diǎn)是:生成器只能遍歷一次。
lambda表達(dá)式(匿名函數(shù))
lambda表達(dá)式純粹是為了編寫(xiě)簡(jiǎn)單函數(shù)而設(shè)計(jì),起到了一個(gè)函數(shù)速寫(xiě)的作用,使得簡(jiǎn)單函數(shù)可以更加簡(jiǎn)潔的表示。
lambda和def的區(qū)別
lambda表達(dá)式可以省去定義函數(shù)的過(guò)程,讓代碼更加的簡(jiǎn)潔,適用于簡(jiǎn)單函數(shù),編寫(xiě)處理更大業(yè)務(wù)的函數(shù)需要使用def定義。
lambda表達(dá)式常搭配map(), reduce(), filter()函數(shù)使用
-
map(): map函數(shù)接受兩個(gè)參數(shù),一個(gè)是函數(shù),一個(gè)是序列,其中,函數(shù)可以接收一個(gè)或者多個(gè)參數(shù)。map將傳入的函數(shù)依次作用于序列中的每個(gè)元素,將結(jié)果作為新的列表返回。
#將一個(gè)列表中的數(shù)字轉(zhuǎn)換為字符串 map(str, [1,2,3,4,5,6]) -
reduce():函數(shù)接收兩個(gè)參數(shù),一個(gè)是函數(shù),另一個(gè)是序列,但是,函數(shù)必須接收兩個(gè)參數(shù)reduce把結(jié)果繼續(xù)和序列的下一個(gè)元素做累積計(jì)算,其效果就是reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)。
-
filter():該函數(shù)用于篩選,將傳入的函數(shù),依次作用于每個(gè)元素,然后根據(jù)函數(shù)的返回值是True還是False,決定是留下還是丟棄該元素。
裝飾器
裝飾器本質(zhì)是一個(gè)Python函數(shù),它可以讓其它函數(shù)在沒(méi)有任何代碼變動(dòng)的情況下增加額外功能。有了裝飾器,我們可以抽離出大量和函數(shù)功能本身無(wú)關(guān)的雷同代碼并繼續(xù)重用。經(jīng)常用于具有切面需求的場(chǎng)景:包括插入日志、性能測(cè)試、事務(wù)處理、緩存和權(quán)限校驗(yàn)等。
那么為什么要引入裝飾器呢?
場(chǎng)景:計(jì)算一個(gè)函數(shù)的執(zhí)行時(shí)間。
一種方法就是定義一個(gè)函數(shù),用來(lái)專(zhuān)門(mén)計(jì)算函數(shù)的運(yùn)行時(shí)間,然后運(yùn)行時(shí)間計(jì)算完成之后再處理真正的業(yè)務(wù)代碼,代碼如下:
import time def get_time(func): startTime = time.time() func() endTime = time.time() processTime = (endTime - startTime) * 1000 print "The function timing is %f ms" %processTime def myfunc(): print "start func" time.sleep(0.8) print "end func" get_time(myfunc) myfunc()
但是這段代碼的邏輯破壞了原有的代碼邏輯,就是對(duì)所有func函數(shù)的調(diào)用都需要使用get_time(func)來(lái)實(shí)現(xiàn)。
那么,有沒(méi)有更好的展示方式呢?當(dāng)然有,那就是裝飾器。
編寫(xiě)簡(jiǎn)單裝飾器
結(jié)合上述實(shí)例,編寫(xiě)裝飾器:
def get_time(func): def wrapper(): startTime = time.time() func() endTime = time.time() processTime = (endTime - startTime) * 1000 print "The function timing is %f ms" %processTime return wrapper print "myfunc is:", myfunc.__name__ myfunc = get_time(myfunc) print "myfunc is: ", myfunc.__name__ myfunc()
這樣,一個(gè)簡(jiǎn)單的完整的裝飾器就實(shí)現(xiàn)了,可以看到,裝飾器并沒(méi)有影響函數(shù)的執(zhí)行邏輯和調(diào)用。
在Python中,可以使用"@"語(yǔ)法糖來(lái)精簡(jiǎn)裝飾器的代碼,將上例更改為:
@ get_time def myfunc(): print "start func" time.sleep(0.8) print "end func" print "myfunc is: ", myfunc.__name__ myfunc()
** 裝飾器的調(diào)用順序**
裝飾器可以疊加使用,若多個(gè)裝飾器同時(shí)裝飾一個(gè)函數(shù),那么裝飾器的調(diào)用順序和@語(yǔ)法糖的聲明順序相反,也就是:
@decorator1 @decorator2 def func(): pass
等效于:
func = decorator1(decorator2(func()))
被裝飾的函數(shù)帶參數(shù)
上述實(shí)例中,myfunc()是沒(méi)有參數(shù)的,那如果添加參數(shù)的話,裝飾器該如何編寫(xiě)呢?
#被裝飾的函數(shù)帶參數(shù) def get_time3(func): def wrapper(*args, **kwargs): startTime = time.time() func(*args, **kwargs) endTime = time.time() processTime = (endTime - startTime) * 1000 print "The function timing is %f ms" %processTime return wrapper @ get_time3 def myfunc2(a): print "start func" print a time.sleep(0.8) print "end func" a = "test" myfunc2(a)
帶參數(shù)的裝飾器
裝飾器有很大的靈活性,它本身支持參數(shù),例如在上述實(shí)例中,@get_time裝飾器唯一的參數(shù)就是執(zhí)行業(yè)務(wù)的函數(shù),當(dāng)然也可以在裝飾器中添加參數(shù),加以邏輯判斷。
內(nèi)置裝飾器
Python中,常見(jiàn)的類(lèi)裝飾器包括:@staticmathod、@classmethod和@property
- @staticmethod:類(lèi)的靜態(tài)方法,跟成員方法的區(qū)別是沒(méi)有self參數(shù),并且可以在類(lèi)不進(jìn)行實(shí)例化的情況下調(diào)用。
- @classmethod:跟成員方法的區(qū)別是接收的第一個(gè)參數(shù)不是self,而是cls(當(dāng)前類(lèi)的具體類(lèi)型)
- @property:表示可以直接通過(guò)類(lèi)實(shí)例直接訪問(wèn)的信息。
以上,是本次整理的Python高級(jí)用法,本文將持續(xù)更新。
相關(guān)文章
Python常見(jiàn)反爬蟲(chóng)機(jī)制解決方案
這篇文章主要介紹了Python常見(jiàn)反爬蟲(chóng)機(jī)制解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06python回調(diào)函數(shù)中使用多線程的方法
這篇文章主要介紹了python回調(diào)函數(shù)中使用多線程的方法,需要的朋友可以參考下2017-12-12python+Django實(shí)現(xiàn)防止SQL注入的辦法
這篇文章主要介紹了python+Django實(shí)現(xiàn)防止SQL注入的辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10python實(shí)現(xiàn)庫(kù)存商品管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)庫(kù)存商品管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02Python imutils 填充圖片周邊為黑色的實(shí)現(xiàn)
今天小編就為大家分享一篇Python imutils 填充圖片周邊為黑色的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-01-01詳解如何使用Pandas處理時(shí)間序列數(shù)據(jù)
時(shí)間序列數(shù)據(jù)在數(shù)據(jù)分析建模中很常見(jiàn),例如天氣預(yù)報(bào),空氣狀態(tài)監(jiān)測(cè),股票交易等金融場(chǎng)景,本文給大家詳細(xì)介紹了如何使用Pandas處理時(shí)間序列數(shù)據(jù),文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-01-01Python HTMLTestRunner如何下載生成報(bào)告
這篇文章主要介紹了Python HTMLTestRunner如何下載生成報(bào)告,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09python擴(kuò)展庫(kù)numpy入門(mén)教程
這篇文章主要為大家介紹了python擴(kuò)展庫(kù)numpy入門(mén)教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11Django之全局使用request.user.username的實(shí)例詳解
這篇文章主要介紹了Django之全局使用request.user.username的實(shí)例詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05