python列表推導式(列表生成式)的強大之處
毫無疑問程式設計師的工作是辛苦的,熬夜加班,未知的bug,頻繁變動的需求,老闆奇葩的想法,繁重的開發任務……
然而,仍然有那麼多的人堅守崗位,以便抱怨,一邊沉浸在程式碼的汪洋中
因為當解決一個困擾許久的bug,實現一個不常規的功能,當成功的從一段優化到極致的程式碼中再次優化提升執行效率,得到的滿足感是不可取代的,程式的世界很單純,付出汗水,得到回報
感嘆完畢,作為一個10多年IT從業者,用了差不多6年的java開發,期間也陸續學過或用過javascricpt,nodejs,lisp,perl,php,awk,golang,ruby,看出來了吧,基本上是哪個流行學下哪個,哪個有需要用下哪個。瞎折騰。
然而,他們都是學了忘,用了丟。精力有限,我希望語言足夠簡單,靈活,讓我用最少的學習代價,卻能發揮最大的頭腦創造和解決問題的能力。java是工程語言,強調的是結構化,規律,整體性,他的臃腫讓我除了工作以外,沒有任何慾望使用他。
直到我學了python,他確實很簡單,足夠靈活的同時,又不會令到程式碼失控。他能用java程式碼最多一半的程式碼量解決同樣的問題。
上一個實際的例子,看看他的靈活和強大:
一個需求,從日誌中查詢一個給定的字串,找到後,處理後續的行,拿出其中某些欄位並重新輸出到檔案。
日誌sample可能是這樣:
#2018-03-08 00:12:17,272 [INFO], [xxxxxxxxxxl][Inbound Msg Forwarder Thread for TID R0813] - TRIS Message sent: {R0813180308003004RTST23B26500 317211 V6.39 }
#2018-03-08 00:12:17,273 [INFO], [xxxxxxxxxx][Inbound Msg Forwarder Thread for TID R0813] - sent: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE RTST SYSTEM "rdsRTST.dtd">
<RTST>
<tid>R0813</tid>
<xmlMsgDateTime>2018-03-08 00:30:04 CST</xmlMsgDateTime>
<msgName>RTST</msgName>
<block>23B</block>
<stack>26</stack>
<group>500</group>
<termId>0813</termId>
<termType>3</termType>
<version>17211</version>
<activeChnl> </activeChnl>
<homeChnl> </homeChnl>
<interfaceVersion> V6.39 </interfaceVersion>
</RTST>
#2018-03-08 00:12:17,273 [INFO], [xxxxxxxxxx][Inbound Msg Forwarder Thread for TID R0813] - GSS authentication tid=R0813
#2018-03-08 00:12:17,273 [INFO], [xxxxxxxxxx][Inbound Msg Forwarder Thread for TID R0813] - GSS authentication MsgType=RTST
#2018-03-08 00:12:17,273 [INFO], [xxxxxxxxxx][Inbound Msg Forwarder Thread for TID R0813] - GSS authentication time = 1520439137273, 1520427471680, 28800000 => false
#2018-03-08 00:12:17,273 [INFO], [xxxxxxxxxx][Inbound Msg Forwarder Thread for TID R0813] - GSS authentication Entry Name = kerberos
#2018-03-08 00:12:17,331 [INFO], [xxxxxxxxxx][Inbound Msg Forwarder Thread for TID R0813] - received: <?xml version="1.0" encoding="UTF-8"?>
<BTST>
來看看面向過程的常規程式碼方案:
def _parsehhtlog(): result = {} lineflag = 0 tid = version = '' try: with open(_logpath + _getYesterday()) as file_object: for num, line in enumerate(file_object): if re.search("^<RTST>$", line): lineflag = num elif re.search("<tid>\w\d\d\d\d</tid>$", line) and lineflag != 0 and num == lineflag + 1: tid = line[7:12] elif re.search("<version>\d\d\d\d\d</version>$", line) and lineflag != 0 and num == lineflag + 9: version = line[11:16] result[tid] = version lineflag = 0 print("find a record:", tid, version) except IOError as err: print('IO exception:may be file path is error!') print(str(err)) return result
基本沒有任何優化,程式碼閱讀也很費力。其實找到指定匹配並處理後續行這個操作應該是一個連續的操作,這裡可以用生成式直接一步處理完畢,直接看程式碼:
def _parsehhtlog():
result, tid = {}, ''
try:
with open(_logpath) as file_object:
results = [[file_object.readline() for i in range(9)] \
for line in file_object if re.search("^<RTST>$", line)]
for value in results:
if re.search("<tid>\w\d\d\d\d</tid>$", value[0]):
tid = value[0][7:12]
if re.search("<version>\d\d\d\d\d</version>$", value[8]):
result[tid] = value[8][11:16]
print(tid, result[tid])
except IOError as err:
print('IO exception:', str(err))
return result
這樣是不是直觀了很多,複雜度上下降了很多,使用的變數也減少了,分步驟的處理方式也利於排錯和增加新功能。
當然,也許還有大神可以更加優化;上述程式碼是我用了一週時間利用上班間隙學習python後的成果。那麼大概python確實足夠簡單。像我這樣笨的人也可以學的這麼快和有信心。
再貼一個計算楊輝三角的解決方案:
/ \
1 1
/ \ / \
1 2 1
/ \ / \ / \
1 3 3 1
/ \ / \ / \ / \
1 4 6 4 1
/ \ / \ / \ / \ / \
1 5 10 10 5 1
l = [1]
while 1:
print(l)
l = [1] + [ l[n] + l[n+1] for n in range(len(l)-1) ] + [1]
是否足夠直觀,簡潔?