python进阶小技巧
Python進(jìn)階小技巧
記錄3個(gè)近日學(xué)習(xí)到的python進(jìn)階技巧,既不是初級(jí)技巧,也不是非常高級(jí)的奇技淫巧,所以姑且稱(chēng)為進(jìn)階技巧,分別是:with, singledispatch和Flattening。
1. 實(shí)現(xiàn)自定義方法的with
1.1 Magic Method
Magic Method直譯成魔術(shù)方法,簡(jiǎn)單的說(shuō)就是python中用雙下劃線包裹起來(lái)的方法,《流暢的Python》一書(shū)中也把這類(lèi)方法叫做dunder(double underline) method,雙下方法。Python中類(lèi)的構(gòu)造函數(shù)__init__就是一種最常見(jiàn)的魔術(shù)方法。要實(shí)現(xiàn)with,就需要2種魔術(shù)方法:__enter__和__exit__。
__enter__方法用于管理執(zhí)行with后返回的實(shí)例,并且可以賦值給as關(guān)鍵詞之后的變量。
__exit__則顧名思義,定義了with退出時(shí)的操作,并對(duì)異常進(jìn)行處理。
下面寫(xiě)一個(gè)非常簡(jiǎn)單的demo
from websocket import create_connectionclass Demo:def __init__(self, uri):self.ws = create_connection(uri)def __enter__(self):return self.wsdef __exit__(self):self.ws.close()demo非常簡(jiǎn)單,創(chuàng)建一個(gè)websocket連接,并且可以使用with方法來(lái)調(diào)用。如果不使用with,那么每次建立連接之后,都需要手動(dòng)顯式的去close掉,否則就會(huì)有一些僵尸連接長(zhǎng)期的掛在那里。用demo中的寫(xiě)法,那么在with執(zhí)行完畢后,__exit__方法會(huì)自動(dòng)的來(lái)替你關(guān)閉這個(gè)連接,省心省力。
1.2 contextlib
1.1中的魔術(shù)方法,固然是非常的清晰明了,但是我實(shí)現(xiàn)上面那么簡(jiǎn)單的功能,就要?jiǎng)?chuàng)建一個(gè)類(lèi),實(shí)現(xiàn)3種魔法方法,顯得繁瑣了些。為此,python提供了一個(gè)非常簡(jiǎn)便的裝飾器——contextlib。使用contextlib重寫(xiě)一下上面那段代碼:
from contextlib import contextmanager@contextmanager def demo(uri):ws = create_connection(uri)try:yield wsfinally:ws.close()可以把其中的try部分理解成剛才的__enter__方法,finally部分則對(duì)應(yīng)__exit__方法。
兩種寫(xiě)法各有千秋,完全可以根據(jù)喜好和具體場(chǎng)景來(lái)選擇合適的實(shí)現(xiàn)方法。我還是更喜歡Magic Method實(shí)現(xiàn)的方法,__enter__和__exit__看起來(lái)更清晰和直白,使用裝飾器的方法相比之下有種過(guò)于隱晦的感覺(jué)。
2. 單重派發(fā)singledispatch
作為一個(gè)python程序員,你完全可以在不知道functools存在的情況下寫(xiě)幾萬(wàn)行業(yè)務(wù)代碼而沒(méi)有任何障礙,但若能熟練使用functools模塊中的各種功能,你就可以寫(xiě)出妖艷風(fēng)騷的多的pythonic代碼。
singledispatch正是functools里的一種方法,single很好理解,就是單個(gè)的,dispatch詞匯量達(dá)標(biāo)的同學(xué)也都知道,是派遣派出的意思,合在一起就是單重派發(fā)了,它所做的事情,就是把不同數(shù)據(jù)類(lèi)型的參數(shù),派發(fā)到同名,但內(nèi)容不同的函數(shù)模塊去。
比如這一段代碼:
def foo(arg):if isinstance(arg, str):print(f"{arg} is str")elif isinstance(arg, int):print(f"{arg} is int")else:print(f"{arg} is unknown")foo的功能一目了然,就是根據(jù)參數(shù)arg的不同類(lèi)型來(lái)輸出不同的內(nèi)容,現(xiàn)在用singledispatch來(lái)重寫(xiě)一下這段代碼:
from functools import singledispatch@singledispatch def foo(arg):print(f"{arg} is unknown")@foo.register def _(arg: int):print(f"{arg} is int")@foo.register def _(arg: str):print(f"{arg} is str")從python3.7開(kāi)始,可以通過(guò)類(lèi)型注解的方式實(shí)現(xiàn)單重派發(fā),之前的版本,需要在register中指定類(lèi)型。
上面兩種寫(xiě)法孰優(yōu)孰劣我也不做評(píng)判,我把這個(gè)記錄下來(lái)僅僅是因?yàn)?#xff0c;我終于發(fā)現(xiàn)了類(lèi)型注解的一個(gè)實(shí)際用處!!從3.5出現(xiàn)以來(lái),我一直以為類(lèi)型注解只是一種毫無(wú)卵用的另類(lèi)注釋而已!
3. 拉平(Flattening)
問(wèn):怎么用最簡(jiǎn)單的代碼把[[1], [2, 3], [4, 5, 6]]變成[1, 2, 3, 4, 5, 6]?
我的第一反應(yīng)是這樣的:
一個(gè)字,low,那怎么寫(xiě)逼格更高呢:
a = [[1], [2, 3], [4, 5, 6]] l = sum(a, [])沒(méi)想到吧,sum還有這功能。當(dāng)然,如果是列表嵌套列表再嵌套列表的復(fù)雜格式,要拉平就寫(xiě)個(gè)lamda函數(shù)吧。
總結(jié)
以上是生活随笔為你收集整理的python进阶小技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: c#如何实现叫号操作_C#开发银行叫号系
- 下一篇: [dts]DTS实例分析