舉例講解Python中的迭代器、生成器與列表解析用法
迭代器:初探
上一章曾經(jīng)提到過(guò),其實(shí)for循環(huán)是可用于任何可迭代的對(duì)象上的。實(shí)際上,對(duì)Python中所有會(huì)從左至右掃描對(duì)象的迭代工具而言都是如此,這些迭代工具包括了for循環(huán)、列表解析、in成員關(guān)系測(cè)試以及map內(nèi)置函數(shù)等。
“可迭代對(duì)象”的概念在Python中是相當(dāng)新穎的,基本這就是序列觀念的通用化:如果對(duì)象時(shí)實(shí)際保存的序列,或者可以再迭代工具環(huán)境中一次產(chǎn)生一個(gè)結(jié)果的對(duì)象,那就看做是可迭代的。
>>文件迭代器
作為內(nèi)置數(shù)據(jù)類型的文件也是可迭代的,它有一個(gè)名為_(kāi)_next__的方法,每次調(diào)用時(shí),就會(huì)返回文件中的下一行。當(dāng)?shù)竭_(dá)文件末尾時(shí),__next__會(huì)引發(fā)內(nèi)置的StopIteration異常,而不是返回空字符串。
這個(gè)接口就是Python中所謂的迭代協(xié)議:有__next__方法的對(duì)象會(huì)前進(jìn)到下一個(gè)結(jié)果,而在一系列結(jié)果的末尾時(shí),則會(huì)引發(fā)StopIteration。任何這類對(duì)象都認(rèn)為是可迭代的。任何這類對(duì)象也能以for循環(huán)或其他迭代工具遍歷,因?yàn)樗械ぞ邇?nèi)部工作起來(lái)都是在每次迭代中調(diào)用__next__,并且捕捉StopIteratin異常來(lái)確定何時(shí)離開(kāi)。
for line in open('script.py'):
print(line.upper(),end='')
上面的代碼就是文件迭代的一個(gè)例子,并且這種用法是最高效的文件讀取方法,主要有三個(gè)優(yōu)點(diǎn):這是最簡(jiǎn)單的寫(xiě)法,運(yùn)行快,并且從內(nèi)存使用情況來(lái)說(shuō)也是最好的。
替代的寫(xiě)法是:
for line in open('script.py').readlines():
print(line.upper(),end='')
這種調(diào)用方法會(huì)把文件一次性讀到內(nèi)存中,如果文件太大,那么內(nèi)存會(huì)被消耗光的。
>>手動(dòng)迭代:iter和next
為了支持手動(dòng)迭代代碼(用較少的錄入),Python3.0還提供了一個(gè)內(nèi)置函數(shù)next,它會(huì)自動(dòng)調(diào)用一個(gè)對(duì)象的__next__方法。給定一個(gè)對(duì)象X,調(diào)用next(X)等同于X.__next__(),但前者簡(jiǎn)單很多。
從技術(shù)角度來(lái)講,迭代協(xié)議還有一點(diǎn)值得注意。當(dāng)for循環(huán)開(kāi)始時(shí),會(huì)通過(guò)它傳給iter內(nèi)置函數(shù),以便從可迭代對(duì)象中獲得一個(gè)迭代器,返回的對(duì)象含有需要的next方法。調(diào)用iter的步驟對(duì)于文件來(lái)說(shuō)不是必須的,因?yàn)槲募?duì)象就是自己的迭代器,但是對(duì)于其他的一些內(nèi)置數(shù)據(jù)類型來(lái)說(shuō),就不一定了。
列表以及很多其他的內(nèi)置對(duì)象,不是自身的迭代器,因?yàn)樗鼈冎С侄啻未蜷_(kāi)迭代器。對(duì)這樣的對(duì)象,我們必須調(diào)用iter來(lái)啟動(dòng)迭代:
L=[1,2,3] iter(L) is L #return false L.__next__() #會(huì)報(bào)錯(cuò) I = iter(L) I.__next__() I.__next__()
雖然Python迭代工具自動(dòng)調(diào)用這些(iter,__next__)函數(shù),我們也可以使用它們來(lái)手動(dòng)地應(yīng)用迭代協(xié)議。
列表解析:初探
>>列表解析基礎(chǔ)知識(shí)
L=[1,2,3,4,5] L = [x+10 for x in L]
列表解析寫(xiě)在一個(gè)方括號(hào)中,因?yàn)樗鼈冏罱K是構(gòu)建一個(gè)新的列表的一種方式。它們以我們所組成的一個(gè)任意的表達(dá)式開(kāi)始,該表達(dá)式使用我們所組成的一個(gè)循環(huán)變量(x+10)。這后面跟著我們現(xiàn)在應(yīng)該看作是一個(gè)for循環(huán)頭部的部分,它申明了循環(huán)變量,以及一個(gè)可迭代對(duì)象(for x in L)
要運(yùn)行該表達(dá)式,Python在解釋器內(nèi)部執(zhí)行一個(gè)遍歷L的迭代,按照順序把x賦給每個(gè)元素,并且收集對(duì)各元素運(yùn)行左邊的表達(dá)式的結(jié)果。我們得到的結(jié)果列表就是列表解析所表達(dá)的內(nèi)容——針對(duì)L中的每個(gè)x,包含了x+10的一個(gè)新列表。
其實(shí)列表解析式并不是必須的,因?yàn)樗芡瓿傻墓ぷ鞫寄軌蛲ㄟ^(guò)for循環(huán)完成,但是列表解析式比手動(dòng)的for循環(huán)語(yǔ)句運(yùn)行得更快(往往速度快一倍),因?yàn)樗鼈兊牡诮忉屍鲀?nèi)部是以C語(yǔ)言的速度執(zhí)行的,而不是以手動(dòng)的Python代碼執(zhí)行的,特別是對(duì)于較大的數(shù)據(jù)集合,這是使用列表解析的一個(gè)主要的性能優(yōu)點(diǎn)。
當(dāng)我們考慮在一個(gè)序列中的每個(gè)項(xiàng)上執(zhí)行一個(gè)操作時(shí),都可以考慮使用列表解析。
>>擴(kuò)展的列表解析語(yǔ)法
實(shí)際上,列表解析可以有更高級(jí)的應(yīng)用。作為一個(gè)特別有用的擴(kuò)展,表達(dá)式中嵌套的for循環(huán)可以有一個(gè)相關(guān)的if子句,來(lái)過(guò)濾那些測(cè)試不為真的結(jié)果項(xiàng)。
lines = [line.rstrip() for line in open('script.py') if line[0]='p']
這條if子句檢查從文件讀取的每一行,看它的第一個(gè)字符是否是p;如果不是,從結(jié)果列表中省略改行。
事實(shí)上,如果我們?cè)敢獾脑挘斜斫馕隹梢宰兊酶訌?fù)雜——它們的完整語(yǔ)法允許任意數(shù)目的for子句,每個(gè)子句有一個(gè)可選的相關(guān)的if子句。
Python3.0中的新的可迭代對(duì)象
Pyton3.0中的一個(gè)基本的改變是,它比Python2.x更強(qiáng)調(diào)迭代。除了與文件和字典這樣的內(nèi)置類型相關(guān)的迭代,字典方法keys、values和items都在Python3.0中返回可迭代對(duì)象。 返回一個(gè)可迭代對(duì)象而不是返回一個(gè)結(jié)果列表的好處在于節(jié)省了內(nèi)存的空間。
>>多個(gè)迭代器VS單個(gè)迭代器
多個(gè)迭代器:在它們的結(jié)果中能保持不同位置的多個(gè)迭代器
單個(gè)迭代器:只能保持一個(gè)迭代器,在遍歷其結(jié)果之后,它們就用盡了。
通常通過(guò)針對(duì)iter調(diào)用返回一個(gè)新的對(duì)象,來(lái)支持多個(gè)迭代器;單個(gè)迭代器一般意味著一個(gè)對(duì)象返回其自身。
>>字典視圖迭代器
在Python3.0中,字典的keys、values和items方法返回可迭代的視圖對(duì)象,它們一次產(chǎn)生一個(gè)結(jié)果項(xiàng),而不是在內(nèi)存中一次產(chǎn)生全部結(jié)果列表。視圖項(xiàng)保持和字典中的那些項(xiàng)相同的物理順序,并且反映對(duì)底層的字典做出的修改。
和所有迭代器一樣,我們總可以通過(guò)把一個(gè)Python3.0字典視圖傳遞到list內(nèi)置函數(shù)中,從而強(qiáng)制構(gòu)建一個(gè)真正的列表。然而,這通常不是必須的。
此外,Python3.0字典仍然有自己的迭代器,它返回連續(xù)的鍵。因此,無(wú)需直接在此環(huán)境中調(diào)用keys:
for key in D:print(key,end='')
>>列表解析與map
列表解析在一個(gè)序列上的值應(yīng)用一個(gè)任意表達(dá)式,將其結(jié)果搜集到一個(gè)新的列表中并返回。從語(yǔ)法上說(shuō),列表解析是由方括號(hào)封裝起來(lái)的(為了提醒你它們構(gòu)造了一個(gè)列表)。它們的簡(jiǎn)單形式是在方括號(hào)中編寫(xiě)一個(gè)表達(dá)式,Python之后將這個(gè)表達(dá)式的應(yīng)用循環(huán)中每次迭代的結(jié)果搜集起來(lái)。例如,假如我們希望搜集字符串中的所有字符的ASCII碼,可以這樣做:
#循環(huán)的方法 res=[] for x in 'spam': res.append(ord(x)) #map函數(shù)的方法 res=list(map(ord,'spam')) #列表解析 res=[ord(x) for x in 'spam']
>>增加測(cè)試和嵌套循環(huán)
其實(shí),列表解析還要比上面說(shuō)的通用的多,我們可以在for之后編寫(xiě)一個(gè)if分支,用來(lái)增加選擇邏輯。
#列表解析 [x ** 2 for x in range(10) if x % 2 == 0] #map list(map((lambda x:x**2),filter((lambda x: x % 2==0),range(10))))
上述的兩行代碼都是搜集了0~9中的偶數(shù)的平方和,可以很明顯的看到,完成同樣的功能,列表解析的語(yǔ)句簡(jiǎn)單地多。
實(shí)際上,列表解析還能夠更加通用。你可以在一個(gè)列表解析中編寫(xiě)任意數(shù)量的嵌套的for循環(huán),并且每一個(gè)都有可選的關(guān)聯(lián)的if測(cè)試。通用結(jié)構(gòu)如下所示:
expression for target1 in iterable1 [if comdition1]
for target2 in iterable2 [if condition2] ...
for targetN in iterableN [if conditionN]
當(dāng)for分句嵌套在列表解析中時(shí),它們工作起來(lái)就像等效的嵌套的for循環(huán)語(yǔ)句。例如,如下的代碼:
res=[x+y for x in [0,1,2] for y in [100,200,300]]
與下面如此冗長(zhǎng)的代碼有相同的效果:
res=[] for x in [0,1,2]: for y in [100,200,30]: res.append(x+y)
>>列表解析和矩陣
使用Python編寫(xiě)矩陣的一個(gè)基本的方法就是使用嵌套的列表結(jié)構(gòu),例如,下面的代碼定義了兩個(gè)3x3的矩陣:
M=[[1,2,3], [4,5,6], [7,8,9]] N=[[2,2,2], [3,3,3], [4,4,4]]
列表解析也是處理這樣結(jié)構(gòu)的強(qiáng)大工具,它們能夠自動(dòng)掃描行和列。
取出第二列的所有元素:
[row[1] for row in M] #[2,5,8] [M[row][1] for row in (0,1,2)] #[2,5,8]
取出對(duì)角線上的元素:
[M[i][i] for i in range(len(M))] #[1,5,9]
混合多個(gè)矩陣,下面的代碼創(chuàng)建了一個(gè)單層的列表,其中包含了矩陣對(duì)元素的乘積。
[M[row][col] * N[row][col] for row in range(3) for col in range(3)] #[2,4,6,12,15,18,28,32,36]
下面的代碼再?gòu)?fù)雜一點(diǎn),構(gòu)造一個(gè)嵌套的列表,其中的值與上面的一樣:
[[M[row][col] * N[row][col] for col in range(3)] for row in range(3)] #[[2,4,6],[12,15,18],[28,32,36]]
res=[] for row in range(3): tmp=[] for col in range(3): tmp.append(M[row][col]*N[row][col]) res.append(tmp)
>>理解列表解析
基于對(duì)運(yùn)行在當(dāng)前Python版本下的測(cè)試,map調(diào)用比等效的for循環(huán)要快兩倍,而列表解析往往比map調(diào)用要稍快一些。速度上的差距來(lái)自底層實(shí)現(xiàn),map和列表解析是在解釋器中以C語(yǔ)言的速度來(lái)運(yùn)行的,比Python的for循環(huán)在PVM中步進(jìn)要快得多。
重訪迭代器:生成器
如今的Python對(duì)延遲提供更多的支持——它提供了工具在需要的時(shí)候才產(chǎn)生結(jié)果,而不是立即產(chǎn)生結(jié)果。特別地,有兩種語(yǔ)言結(jié)構(gòu)盡可能地拖延結(jié)果創(chuàng)建。
生成器函數(shù):編寫(xiě)為常規(guī)的def語(yǔ)句,但是是使用yield語(yǔ)句一次返回一個(gè)結(jié)果,在每個(gè)結(jié)果之間掛起和繼續(xù)它們的狀態(tài)。
生成器表達(dá)式:生成器表達(dá)式類似于上一小節(jié)的列表解析,但是,它們返回按需產(chǎn)生結(jié)果的一個(gè)對(duì)象,而不是構(gòu)建一個(gè)結(jié)果列表。
由于上面二者都不會(huì)一次性構(gòu)建一個(gè)列表,它們節(jié)省了內(nèi)存空間,并且允許計(jì)算時(shí)間分散到各個(gè)結(jié)果請(qǐng)求。
>>生成器函數(shù):yield VS return
之前我們寫(xiě)的函數(shù)都是接受輸入?yún)?shù)并立即返回單個(gè)結(jié)果的常規(guī)函數(shù),然而,也有肯能來(lái)編寫(xiě)可以送回一個(gè)值并隨后從其退出的地方繼續(xù)的函數(shù)。這樣的函數(shù)叫做生成器函數(shù),因?yàn)樗鼈冸S著時(shí)間產(chǎn)生值的一個(gè)序列。
一般來(lái)說(shuō),生成器函數(shù)和常規(guī)函數(shù)一樣,并且,實(shí)際上也是用常規(guī)的def語(yǔ)句編寫(xiě)的。然后,當(dāng)創(chuàng)建時(shí),它們自動(dòng)實(shí)現(xiàn)迭代協(xié)議,以便可以出現(xiàn)在迭代背景中。
狀態(tài)掛起
和返回一個(gè)值并退出的函數(shù)不同,生成器函數(shù)自動(dòng)在生成值的時(shí)刻掛起并繼續(xù)函數(shù)的執(zhí)行。因此,它們對(duì)于提前計(jì)算整個(gè)一系列值以及在類中手動(dòng)保存和恢復(fù)狀態(tài)都很有用。由于生成器函數(shù)在掛起時(shí)保存的狀態(tài)包含了它們的整個(gè)本地作用域,當(dāng)函數(shù)恢復(fù)時(shí),它們的本地變量保持了信息并且使其可用。
生成器函和常規(guī)函數(shù)之間的主要不同之處在于,生成器yield一個(gè)值,而不是return一個(gè)值。yield語(yǔ)句掛起該函數(shù)并向調(diào)用者發(fā)送一個(gè)值,但是,保留足夠的狀態(tài)以使得函數(shù)從它離開(kāi)的地方繼續(xù)。當(dāng)繼續(xù)時(shí),函數(shù)在上一個(gè)yield返回立即繼續(xù)執(zhí)行。從函數(shù)角度來(lái)看,這允許其代碼隨著時(shí)間產(chǎn)生一系列的值,而不是一次計(jì)算它們并在諸如列表的內(nèi)容中送回它們。
迭代協(xié)議整合
可迭代對(duì)象定義了一個(gè)__next__方法,它要么返回迭代中的下一項(xiàng),要么引發(fā)一個(gè)特殊的StopIteration異常來(lái)終止迭代。一個(gè)對(duì)象的迭代器用iter內(nèi)置函數(shù)接受。
如果支持該協(xié)議的話,Python的for循環(huán)以及其他的迭代技術(shù),使用這種迭代協(xié)議來(lái)便利一個(gè)序列或值生成器;如果不支持,跌打返回去重復(fù)索引序列。
要支持這一協(xié)議,函數(shù)包含一條yield語(yǔ)句,該語(yǔ)句特別編譯為生成器。當(dāng)調(diào)用時(shí),它們返回一個(gè)迭代器對(duì)象,該對(duì)象支持用一個(gè)名為_(kāi)_next__的自動(dòng)創(chuàng)建的方法來(lái)繼續(xù)執(zhí)行的接口。生成器函數(shù)也可能有一條return語(yǔ)句,總是在def語(yǔ)句塊的末尾,直接終止值的生成。
生成器函數(shù)應(yīng)用
def gensquares(N): for i in range(N): yield i ** 2
這個(gè)函數(shù)在每次循環(huán)時(shí)都會(huì)產(chǎn)生一個(gè)值,之后將其返回給它的調(diào)用者。當(dāng)它被暫定后,它的上一個(gè)狀態(tài)保存了下來(lái) 并且在yield語(yǔ)句之后把控制器馬上回收。它允許函數(shù)避免臨時(shí)再做所有的工作,當(dāng)結(jié)果的列表很大或者在處理每一個(gè)結(jié)果都需要很多時(shí)間時(shí),這一點(diǎn)尤其重要。生成器將在loop迭代中處理一系列值的時(shí)間分布開(kāi)來(lái)。
擴(kuò)展生成器函數(shù)協(xié)議:send和next 在Python2.5中,生成器函數(shù)協(xié)議中增加了一個(gè)send方法。send方法生成一系列結(jié)果的下一個(gè)元素,這一點(diǎn)像__next__方法一樣,但是它提供了一種調(diào)用者與生成器之間進(jìn)行通信的方法,從而能夠影響它的操作。
def gen(): for i in range(10): X =yield i print(X) G = gen() next(G) #0 G.send(77) #77 1 G.send(88) #88 2 next(G) #None 3
上面的代碼比較難于理解,而且書(shū)上的翻譯比較劣質(zhì),沒(méi)看懂。在網(wǎng)上查了一些資料,結(jié)合自己的理解,上述代碼的運(yùn)行過(guò)程應(yīng)該是這樣的:生成了一個(gè)函數(shù)對(duì)象,賦值給了G,然后調(diào)用了next() 函數(shù),生成了生成器的第一個(gè)值0,所以返回值是0。此時(shí)函數(shù)運(yùn)行到y(tǒng)ield語(yǔ)句,碰到y(tǒng)ield語(yǔ)句后立即掛起函數(shù),保存狀態(tài),等待下一次迭代。程序中之后又調(diào)用了send()方法,將77傳遞給了yield語(yǔ)句,yield語(yǔ)句將send()傳遞過(guò)來(lái)的值(此處是77)賦值給X,然后打印出來(lái)。然后函數(shù)繼續(xù)運(yùn)行,直到再次碰到y(tǒng)ield,此時(shí)是第二次碰到y(tǒng)ield,所以返回了1,接著函數(shù)又被掛起,等待下一次迭代。接著又調(diào)用了send(),同上次調(diào)用一樣,將傳進(jìn)的參數(shù)(此處是88)作為yield的返回值賦值給X,然后打印,接著繼續(xù)運(yùn)行函數(shù),直到再次碰到y(tǒng)ield,此時(shí)是第三次,因此輸出2。最后又再次調(diào)用了next()函數(shù),其實(shí)'next()'函數(shù)就是傳遞了一個(gè)None,因此,我們得到的結(jié)果是None和3。
此處需要注意的是,其實(shí)next()和send(None)是等價(jià)的。通過(guò)send()方法,我們就能夠和生成器實(shí)現(xiàn)通信。
>>生成器表達(dá)式:迭代器遇到列表解析
在最新版的Python中,迭代器和列表解析的概念形成了這種語(yǔ)言的一個(gè)新特性——生成器表達(dá)式。從語(yǔ)法上講,生成器表達(dá)式就像一般的列表解析一樣,但是它們是擴(kuò)在圓括號(hào)中而不是方括號(hào)中的。
[x ** 2 for x in range(4)] #List comprehension:build a list (x ** 2 for x in range(4)) #Genterator expression:make an iterable
從執(zhí)行過(guò)程上來(lái)講,生成器表達(dá)式很不相同:不是在內(nèi)存中構(gòu)建結(jié)果,而是返回一個(gè)生成器對(duì)象,這個(gè)對(duì)象將會(huì)支持迭代協(xié)議。
生成器表達(dá)式大體上可以認(rèn)為是對(duì)內(nèi)存空間的優(yōu)化,他們不需要像方括號(hào)的列表解析一樣,一次構(gòu)造出整個(gè)結(jié)果列表。它們?cè)趯?shí)際中運(yùn)行起來(lái)可能稍慢一些,所以它們可能只對(duì)于非常龐大的結(jié)果集合的運(yùn)算來(lái)說(shuō)是最優(yōu)的選擇。
>>生成器函數(shù)VS生成器表達(dá)式
生成器函數(shù)和生成器表達(dá)式自身都是迭代器,并由此只支持一次活躍迭代,我們無(wú)法有在結(jié)果集中位于不同位置的多個(gè)迭代器。
Python3.0解析語(yǔ)法概括
我們已經(jīng)在本章中關(guān)注過(guò)列表解析和生成器,但是,別忘了,還有兩種在Python3.0中可用的解析表達(dá)式形式:集合解析和字典解析。
[x*x for x in range(10)] #List comprehension:build list
(x*x for x in range(10)) #Generator expression:produces items
{x*x for x in range(10)} #Set comprehension:new in 3.0
{x:x*x for x in range(10) #Directionary comprehension:new in 3.0
需要注意的是,上面最后兩種表達(dá)方式都是一次性構(gòu)建所有對(duì)象的,它們沒(méi)有根據(jù)需要產(chǎn)生結(jié)果的概念。
總結(jié)
列表解析、集合解析、字典解析都是一次性構(gòu)建對(duì)象的,直接返回的。
生成器函數(shù)和生成器表達(dá)式不是在內(nèi)存中構(gòu)建結(jié)果的,它們是返回一個(gè)生成器對(duì)象,這個(gè)對(duì)象支持迭代協(xié)議,根據(jù)調(diào)用者需要產(chǎn)生結(jié)果。
集合解析、字典解析都支持嵌套相關(guān)的if子句從結(jié)果中過(guò)濾元素。
函數(shù)陷阱
>>本地變量是靜態(tài)檢測(cè)的
Python定義的在一個(gè)函數(shù)中進(jìn)行分配的變量名時(shí)默認(rèn)為本地變量的,它們存在于函數(shù)的作用域并只在函數(shù)運(yùn)行時(shí)存在。Python靜態(tài)檢測(cè)Python的本地變量,當(dāng)編譯def代碼時(shí),不是通過(guò)發(fā)現(xiàn)賦值語(yǔ)句在運(yùn)行時(shí)進(jìn)行檢測(cè)的。被賦值的變量名在函數(shù)內(nèi)部是當(dāng)做本地變量來(lái)對(duì)待的,而不是僅僅在賦值以后的語(yǔ)句才被當(dāng)做是本地變量。
>>沒(méi)有return語(yǔ)句的函數(shù)
在Python函數(shù)中,return(以及yield)語(yǔ)句是可選的。從技術(shù)上說(shuō),所有的函數(shù)都會(huì)返回了一個(gè)值,如果沒(méi)有提供return語(yǔ)句,函數(shù)將自動(dòng)返回None對(duì)象。
相關(guān)文章
Python的SQLalchemy模塊連接與操作MySQL的基礎(chǔ)示例
SQLalchemy是Python世界中驅(qū)動(dòng)MySQL的一款高人氣模塊,這里我們從入門(mén)開(kāi)始來(lái)看一下Python的SQLalchemy模塊連接與操作MySQL的基礎(chǔ)示例:2016-07-07
Python?Pipeline處理數(shù)據(jù)工作原理探究
如果你是一個(gè)Python開(kāi)發(fā)者,你可能聽(tīng)過(guò)"pipeline"這個(gè)術(shù)語(yǔ),但?pipeline?到底是什么,它又有什么用呢?在這篇文章中,我們將探討?Python?中的?pipeline?概念,它們是如何工作的,以及它們?nèi)绾螏椭憔帉?xiě)更清晰、更高效的代碼2024-01-01
python爬蟲(chóng)之pyppeteer庫(kù)簡(jiǎn)單使用
Puppeteer 是 Google 基于 Node.js 開(kāi)發(fā)的一個(gè)工具,有了它我們可以通過(guò) JavaScript 來(lái)控制 Chrome 瀏覽器的一些操作,當(dāng)然也可以用作網(wǎng)絡(luò)爬蟲(chóng)上,其 API 極其完善,功能非常強(qiáng)大2021-07-07
python讀取并定位excel數(shù)據(jù)坐標(biāo)系詳解
這篇文章主要介紹了python讀取并定位excel數(shù)據(jù)坐標(biāo)系詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-06-06
Python web框架fastapi中間件的使用及CORS跨域問(wèn)題
fastapi "中間件"是一個(gè)函數(shù),它在每個(gè)請(qǐng)求被特定的路徑操作處理之前,以及在每個(gè)響應(yīng)之后工作,它接收你的應(yīng)用程序的每一個(gè)請(qǐng)求,下面通過(guò)本文給大家介紹Python web框架fastapi中間件的使用及CORS跨域問(wèn)題,感興趣的朋友一起看看吧2024-03-03
PyQt5實(shí)現(xiàn)tableWidget 居中顯示
這篇文章主要介紹了PyQt5實(shí)現(xiàn)tableWidget 居中顯示方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

