日常代码笔记,python的推导式&性能评估

  • 2019 年 10 月 6 日
  • 笔记

写代码跟写作类似,需要不断地练习,不断地阅读,获得灵感,然后反复修改(重构)。写代码有代码补全工具,然后我们还是需要不断地练习、实验自己的新想法。

之前对python的推导式没有仔细去了解,今天抽空练习了下,顺路重构下以前代码里比较耗时的逻辑。以下为正文,分享给大家:

推导式comprehensions(又称解析式)。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 常用的比如列表推导式、字典推导式。

01

列表推导式

代替for循环处理list,而且速度还快很多。对比下for循环跟[ ]的方式,代码如下:

import time    t1=time.time()  z=[]  for i in range(100000):      if i%2==0:          j=i+3          z.append(j)  t2=time.time()  print(t2-t1)
耗时0.015286922454833984        t1=time.time()  z=[i+3 for i in range(100000) if i%2==0]  t2=time.time()  print(t2-t1)    
耗时0.008960962295532227

除了从耗时上评估性能之外,还可以通过dis模块获取到对应的字节码指令来评估。何为字节码指令?指的是由一个字节长度的、代表着某种特定含义的数字(操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(操作数,Operands)而构成。

先来用代码实现下:

import dis    def f1():      z=[]      for i in range(10000):          if i%2==0:              j=i+3              z.append(j)  def f2():      z=[i+3 for i in range(10000) if i%2==0]    dis.dis(f1)

dis输出的字节码如下:

  4           0 BUILD_LIST               0                2 STORE_FAST               0 (z)      5           4 SETUP_LOOP              46 (to 52)                6 LOAD_GLOBAL              0 (range)                8 LOAD_CONST               1 (10000)               10 CALL_FUNCTION            1               12 GET_ITER          >>   14 FOR_ITER                34 (to 50)               16 STORE_FAST               1 (i)      6          18 LOAD_FAST                1 (i)               20 LOAD_CONST               2 (2)               22 BINARY_MODULO               24 LOAD_CONST               3 (0)               26 COMPARE_OP               2 (==)               28 POP_JUMP_IF_FALSE       14      7          30 LOAD_FAST                1 (i)               32 LOAD_CONST               4 (3)               34 BINARY_ADD               36 STORE_FAST               2 (j)      8          38 LOAD_FAST                0 (z)               40 LOAD_ATTR                1 (append)               42 LOAD_FAST                2 (j)               44 CALL_FUNCTION            1               46 POP_TOP               48 JUMP_ABSOLUTE           14          >>   50 POP_BLOCK          >>   52 LOAD_CONST               0 (None)               54 RETURN_VALUE

同样,也对列表推导式,输出字节码:

def f2():      z=[i+3 for i in range(10000) if i%2==0]    dis.dis(f2)

对比下方的字节码跟上文的f1的字节码长度,f2在操作步骤上就少很多。

 10           0 LOAD_CONST               1 (<code object <listcomp> at 0x10bb6c420)                2 LOAD_CONST               2 ('f2.<locals>.<listcomp>')                4 MAKE_FUNCTION            0                6 LOAD_GLOBAL              0 (range)                8 LOAD_CONST               3 (10000)               10 CALL_FUNCTION            1               12 GET_ITER               14 CALL_FUNCTION            1               16 STORE_FAST               0 (z)               18 LOAD_CONST               0 (None)               20 RETURN_VALUE

02

字典推导式

可以方便的用来交换键名与键值,如下:

mix = {'m': 300, 'i': 500,'x':1000}  lab = {v: k for k,v in mix.items()}  print(lab)  # {300:"m",500:"i",1000:"x"}

03

推荐2个在线学习的网站

HackerRank

为程序员们提供一个以编码谜题和现实生活中遇到的编码难题为基础的新兴的社交平台。

5 million developers.

codepen

是一个完全免费的前端代码托管服务,上面有很多特效代码,也是我常逛的~