python实战11代码洁癖

缘由

先说垃圾代码:表面是代码垃圾,实际是逻辑垃圾,思路不清或不够简单。简单代码需要更深入思考,建立更简单,简洁,明了的思路。python具有很高的灵活性,所以这一点尤其重要。

类型注解

大型程序中非常必要,弥补python弱类型在开发中的沟通成本(接口调用方需阅读接口实现或代码注释才知传参类型)。

from typing import List, Sequence
 
def square(elems: Sequence[float]) -> List[float]:
    return [x**2 for x in elems]

列表生成式替代循环([i for xx])

大多数循环都可以用列表生成式替代,列表生成式另一个好处是很方便的就可以实现并行化.

拍平嵌套的多重循环(product)笛卡尔积

itertools.product()

In [68]: list(product('ABCD', 'xy'))
Out[68]:
[('A', 'x'),
 ('A', 'y'),
 ('B', 'x'),
 ('B', 'y'),
 ('C', 'x'),
 ('C', 'y'),
 ('D', 'x'),
 ('D', 'y')]

_替代无用临时变量i

其他语言对于无意义的循环个数常用临时变量i,j等表示,python中推荐使用_(开源代码大多此规则,认为是一种约定习惯)

[x for x in range(3) for _ in range(2)]
[0,0,1,1,2,2]

批量化一致性操作优于依次ifelse判断

循环内部做if-else劣于先批量做处理再filter过滤。(不绝对)对于统一性的批量处理,numpy等本身会做一定优化,可以通过Numba进行进一步优化。而且一致性的批量处理符合cpu的cache的LRU规则,大概率命中cache。所以不建议内部有if-else这样的判断逻辑(如果不同分支时间差异很大,另当别论)简单来说就是操作集中化,每个步骤都做简单的,多步骤组合。优于一个大循环内做不同的分支处理逻辑。

猜测如下代码那个速度最快

import time
a = time.time()
b, c = list(), list()
for i in range(10000):
    if not i % 7:
        b.append(i)
    else:
        c.append(i)
print(time.time() - a)

a = time.time()
b = list()
c = list()
[b.append(i) if not i % 7 else c.append(i) for i in range(10000)]
print(time.time() - a)

a = time.time()
b = [i for i in range(10000) if not i % 7]
c = [i for i in range(10000) if i % 7]
print(time.time() - a)

结论:最慢,中间,最快比较奇怪的是第一个和第二个,为何第二个比第一个快,测试多次都是同样结果,本人也不大理解!!

用a and b(a or b)替代if a:b(a if a is not none else b)的简单表达式

副作用mypy静态类型检查会报错(在b没有返回值时)