用迭代器模块为Python提速

Python官方文档用'高效的循环'来形容itertools模块,有些tools会带来性能提升,而另外一些tools并不快,只是会节省一些开发时间而已,如果滥用还会导致代码可读性变差。我们不妨把itertools的兄弟们拉出来溜溜。

1. 数列累加

给定一个列表An,返回数列累加和Sn。举例说明:

输入: [1, 2, 3, 4, 5]

返回: [1, 3, 6, 10, 15]

使用accumulate,性能提升了2.5倍

from itertools import accumulate

def _accumulate_list(arr):
    tot = 0
    for x in arr:
        tot += x
        yield tot

def accumulate_list(arr):
    return list(_accumulate_list(arr))

def fast_accumulate_list(arr):
    return list(accumulate(arr))

arr = list(range(1000))

%timeit accumulate_list(arr)
61 µs ± 2.91 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit fast_accumulate_list(arr)
21.3 µs ± 811 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

2. 选择数据

给定一个列表data,一个用0/1表示的列表selectors,返回被选择的数据。举例说明:

输入: [1, 2, 3, 4, 5], [0, 1, 0, 1, 0]

返回: [2, 4]

使用compress,性能提升了2.8倍

from itertools import compressfrom random import randint

def select_data(data, selectors):    return [x for x, y in zip(data, selectors) if y]

def fast_select_data(data, selectors):    return list(compress(data, selectors))

data = list(range(10000))selectors = [randint(0, 1) for _ in range(10000)]

%timeit select_data(data, selectors)341 µs ± 17.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit fast_select_data(data, selectors)130 µs ± 3.19 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

3. 组合

给定一个列表arr和一个数字k,返回从arr中选择k个元素的所有情况。举例说明:

输入: [1, 2, 3], 2

返回: [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

使用permutations,性能提升了10倍

from itertools import permutations

def _get_permutations(arr, k, i):
    if i == k:
        return [arr[:k]]
    res = []
    for j in range(i, len(arr)):
        arr_cpy = arr.copy()
        arr_cpy[i], arr_cpy[j] = arr_cpy[j], arr_cpy[i]
        res += _get_permutations(arr_cpy, k, i + 1)
    return res

def get_permutations(arr, k):
    return _get_permutations(arr, k, 0)

def fast_get_permutations(arr, k):
    return list(permutations(arr, k))

arr = list(range(10))
k = 5

%timeit -n 1 get_permutations(arr, k)
15.5 ms ± 1.96 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit -n 1 fast_get_permutations(arr, k)
1.56 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

4. 筛选数据

给定一个列表arr,筛选出所有的偶数。举例说明:

输入: [3, 1, 4, 5, 9, 2]

返回: [(4, 2]

使用filterfalse,性能反而会变慢,所以不要迷信itertools

from itertools import filterfalse

def get_even_nums(arr):    return [x for x in arr if x % 2 == 0]

def fast_get_even_nums(arr):    return list(filterfalse(lambda x: x % 2, arr))

arr = list(range(10000))

%timeit get_even_nums(arr)417 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit fast_get_even_nums(arr)823 µs ± 22.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

5. 条件终止

给定一个列表arr,依次对列表的所有数字进行求和,若遇到某个元素大于target之后则终止求和,返回这个和。举例说明:

输入: [1, 2, 3, 4, 5], 3

返回: 6 (4 > 3,终止)

使用takewhile,性能反而会变慢,所以不要迷信itertools

from itertools import takewhile

def cond_sum(arr, target):
    res = 0
    for x in arr:
        if x > target:
            break
        res += x
    return res

def fast_cond_sum(arr, target):
    return sum(takewhile(lambda x: x <= target, arr))

arr = list(range(10000))
target = 5000

%timeit cond_sum(arr, target)
245 µs ± 11.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit fast_cond_sum(arr, target)
404 µs ± 13.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

6. 循环嵌套

给定列表arr1arr2,返回两个列表的所有元素两两相加的和。举例说明:

输入: [1, 2], [4, 5]

返回: [1 + 4, 1 + 5, 2 + 4, 2 + 5]

使用product,性能提升了1.25倍。

from itertools import product

def _cross_sum(arr1, arr2):    for x in arr1:        for y in arr2:            yield x + y

def cross_sum(arr1, arr2):    return list(_cross_sum(arr1, arr2))

def fast_cross_sum(arr1, arr2):    return [x + y for x, y in product(arr1, arr2)]

arr1 = list(range(100))arr2 = list(range(100))

%timeit cross_sum(arr1, arr2)484 µs ± 16.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit fast_cross_sum(arr1, arr2)373 µs ± 11.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

7. 二维列表转一维列表

给定二维列表arr,转为一维列表 举例说明:

输入: [[1, 2], [3, 4]]

返回: [1, 2, 3, 4]

使用chain,性能提升了6倍。

from itertools import chain

def _flatten(arr2d):
    for arr in arr2d:
        for x in arr:
            yield x

def flatten(arr2d):
    return list(_flatten(arr2d))

def fast_flatten(arr2d):
    return list(chain(*arr2d))

arr2d = [[x + y * 100 for x in range(100)] for y in range(100)]

%timeit flatten(arr2d)
379 µs ± 15.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit fast_flatten(arr2d)
66.9 µs ± 3.43 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

作者:李小文,先后从事过数据分析、数据挖掘工作,主要开发语言是Python,现任一家小型互联网公司的算法工程师。

(0)

相关推荐

  • 面试题-有1、2、3、4数字能组成多少互不相同无重复数的三位数?

    前言 有1.2.3.4数字能组成多少互不相同无重复数的三位数? 普通写法 这一题很多小伙伴能想到的最直接的方法是嵌套三个for循环,然后判断3个数字不相等,得到组合的情况 s = 0 for i in ...

  • 算法创作|纸牌三角形

    问题描述A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算).要求每个边的和相等.下图就是一种排法(如有对齐问题,参看p1.png).A9 64   837 5 2这样的排法可 ...

  • 4 比对到参考基因组输出bam文件

    进到align目录 对质量好的测序数据进行比对 1. 一个个比对,生成BAM文件 align目录 sample=SRR7696207 bwa mem -t 2 -R "@RG\tID:$sa ...

  • 【每周一坑】程序猿的浪漫

    最近公众号上的自媒体们炸了,因为苹果爸爸把腾讯爸爸的赞赏给关闭了! 讲真,这对咱们编程教室的影响还是很大的.之前每次发完文章,晚饭还能靠打赏加个鸡腿儿,这下泡汤-- 来看本周的题目. 前几日刷朋友圈时 ...

  • Python 列表去重的4种方式及性能对比

    列表去重是Python中一种常见的处理方式,任何编程场景都可能会遇到需要列表去重的情况. 列表去重的方式有很多,本文将一一讲解他们,并进行性能的对比. 让我们先制造一些简单的数据,生成0到99的100 ...

  • 机器学习:爱因斯坦的小贡献

    怎么,爱因斯坦(Albert Einstein)那会儿就有数据科学了吗? 倒不是这个意思,爱因斯坦也没有提出什么数学理论,但他提出了一个针对数学公式的符号简化办法,即爱因斯坦求和约定(Einstein ...

  • 第39天: Python itertools 模块

    简介 在 Python 中,迭代器是一种非常好用的数据结构,其最大的优势就是延迟生成,按需使用,从而大大提高程序的运行效率.而 itertools 作为 Python 的内置模块,就为我们提供了一套非 ...

  • 列表推导式:简洁高效更具 Python 风格的列表创建方法

    我们在<Python 中的列表和元组>中已经详细介绍了列表(list)的基本特性和使用方法,本文将着重介绍一种 Python 中用于创建 list 的简洁高效的语法形式:列表推导式. Py ...

  • Python导入模块,Python import用法(超级详细)

    http://c.biancheng.net/view/2397.html 使用 Python 进行编程时,有些功能没必须自己实现,可以借助 Python 现有的标准库或者其他人提供的第三方库.比如说 ...

  • 嘘,Python 优化提速的 8 个小技巧

    作者:张皓 链接:https://zhuanlan.zhihu.com/p/143052860 Python 是一种脚本语言,相比 C/C++ 这样的编译语言,在效率和性能方面存在一些不足.但是,有很 ...

  • Python迭代器

    迭代器是可以迭代的对象. 在本教程中,您将了解迭代器的工作原理,以及如何使用__iter__和__next__方法构建自己的迭代器. 迭代器在Python中无处不在. 它们优雅地实现在循环,推导,生成 ...

  • Python 优化提速的 8 个小技巧

    Python 是一种脚本语言,相比 C/C 这样的编译语言,在效率和性能方面存在一些不足.但是,有很多时候,Python 的效率并没有想象中的那么夸张.本文对一些 Python 代码加速运行的技巧进行 ...

  • Python Web开发哪些模块好用?这几类必知!

    关于Python Web开发和图形用户界面的模块有哪些?今天小编通过这篇文章为大家整理了一些常用的模块,我们一起来看看吧. Web开发: 1. Requests:Python内置模块(urllib和u ...

  • Python标准库模块之heapq

    该模块提供了堆排序算法的实现.堆是二叉树,最大堆中父节点大于或等于两个子节点,最小堆父节点小于或等于两个子节点. 创建堆 heapq有两种方式创建堆, 一种是使用一个空列表,然后使用heapq.hea ...

  • Python 模块安装

    Python 模块安装的命令格式为: pip install 模块名. Python  pip模块安装的更新命令格式为: python -m pip install --upgrade pip 模块安 ...

  • Python爬虫常用模块及工具!

    想要学好Python,除了合适的学习路线外,选择合适的工具也很重要,它可以提高我们的工作效率,也可以节省时间.这篇文章重点为大家介绍Python爬虫常用工具,快跟着小编来看看吧. 第一种:常用模块介绍 ...

  • Python模块详解

    Python模块详解