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] 
是否足够直观,简洁?
阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页