声明,这些读书笔记我都是跳跃性的去找对我项目有帮助的,有一些废话我就直接删除了,所以一般不会特定的保留顺序,如果需要参考原版,请参考书中的内容。

9.数据交换值的时候不推荐使用中间变量。

之前大家一般都会使用中间变量来交换值,现在推荐直接交互。比如

x,y = y,x

那我们更深入一点,为什么会快呢。

一般情况下,python表达式的计算顺序都是从左到右的,但是遇到表达式赋值的时候,表达式右边的操作数(优先级)要先于表达式左边的操作数计算。因些表达式expr3,expr4 = expr1,expr2 的计算优先顺序是

expr1 ,expr2 -> expr3 ,expr4

表达式右边在内存中创建元组,计算时不用重复创建对象,只需要将标识符重新分配就可以达到交换值的目的。这里我们分析一下字节码:

import dis

def swap_third():
    a = 1
    b = 2
    c = a
    a = b
    b = c
    #print a,b

def swap_two():
    a = 1
    b = 2
    a,b = b,a
    #print a,b

print dis.dis(swap_two)
print '================'
print dis.dis(swap_third)

输出:

 12           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

 13           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

 14          12 LOAD_FAST                1 (b)
             15 LOAD_FAST                0 (a)
             18 ROT_TWO             
             19 STORE_FAST               0 (a)
             22 STORE_FAST               1 (b)
             25 LOAD_CONST               0 (None)
             28 RETURN_VALUE        
None
================
  4           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

  5           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

  6          12 LOAD_FAST                0 (a)
             15 STORE_FAST               2 (c)

  7          18 LOAD_FAST                1 (b)
             21 STORE_FAST               0 (a)

  8          24 LOAD_FAST                2 (c)
             27 STORE_FAST               1 (b)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        
None

我们查看标号为18的动作:这里的指令ROT_TWO主要作用是交换栈的最顶层元素,它比执行一个Load_Fast 和 Store_Fast 要快。

10 充分利用Lazy evaluation的特性

惰性计算指的是仅仅在需要真正需要执行的时候才计算表达式的值,充分利用Lazy evaluation的带来的好处主要体现在以下两个方面。

1) 避免不必要的计算,带来性能上的提升。

对于python中的条件表达式if x and y ,在x 为 false 的情况下 y表达式的值将不再计算。而于if x or y,当x的值为true的时候将直接返回,不再计算y的值。因此编码中应该充分利用这一特性。

  1. 节省空间,使得无限循环的数据结构成为可能。python中最典型的就是yield 生达器表达式了。它仅每次需要的时候才会返回相应的计算值 。

两个例子一个经典的斐波那契數列,一个是读取文件中使用的

def fab(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        # print b
        a, b = b, a + b
        n = n + 1 
        
        
def read_file(fpath): 
    BLOCK_SIZE = 1024 
    with open(fpath, 'rb') as f: 
        while True: 
            block = f.read(BLOCK_SIZE) 
            if block: 
                yield block 
            else: 
                return

15.使用enumerate()获取序列的索引和值

def print_index_and_value():
    a = ['a','b','c','d']
    for i,p in enumerate(a):
        print i,p