Python高性能计算之推导和生成器

  在Python中,推导和生成器都是非常常用的,而且它们都是经过极度优化的操作,速度非常快,另外一点是它们的代码可读性也比较强,非常适合用来替代显式的for循环。

  当然,有些可能对推导器和生成器不太熟悉,这里我们先介绍一下。

推导器在生成列表时经常会用到,采用方括号来表示,并且里面用一个for循环来生成所需数据。

data = [x for x in range(10)]
data2 = [x for x in range(10) if x % 2 == 0]

这种写法就等效于:

data = []
for i in range(10):
	data.append(i)

可以很明显看出,两种方法的功能一样,但第一种写法更加简洁。

  生成器跟推导器的语法类似,但把方括号[]改成圆括号(),下面代码中g就是一个生成器。

g = (x for x in range(10))
<generator object <genexpr> at 0x122ba9a50>

生成器遵守迭代器协议,是逐个生产出元素,而不是创建一个完整的列表,然后把列表传递到某个构造函数中,所以生成器有个很大的好处就是节省内存。

  下面我们用推导器和生成器

  比如计算从1加到100000,使用for循环和推导器、生成器的代码如下:

n = 1000000

def loop():
    res = []
    for i in range(n):
        res.append(i)
    return res

def comprehesion():
    return sum([i for i in range(n)])

def generator():
    return sum(i for i in range(n))

运行时间对比:

%timeit loop()
90.5 ms ± 833 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit comprehesion()
82.6 ms ± 931 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit generator()
73 ms ± 2.46 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

可以看出,使用推导器和生成器的运行速度都要比显示for循环的方式要快。

  在生成字典时,使用推导的方式,效率也会更高一些。

def loop_dict():
    res = {}
    for i in range(n):
        res[i] = i
    return res

def comprehesion_dict():
    return {i: i for i in range(n)}
%timeit loop_dict()
101 ms ± 1.85 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit comprehesion_dict()
92.1 ms ± 2.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

  当推导器配合filter和map使用时,效果更佳,看下面的例子:

def map_comprehension(nums):
    a = [n * 2 for n in nums]
    b = [n **2 for n in a]
    c = [n ** 0.33 for n in b]
    return max(c)

def map_normal(nums):
    a = map(lambda n: n * 2, nums)
    b = map(lambda n: n ** 2, a)
    c = map(lambda n: n ** 0.33, b)
    return max(c)

使用memory_profiler分析两个函数占用的内存情况:

%load_ext memory_profiler

nums = range(100000)

%memit map_comprehension(nums)
peak memory: 148.05 MiB, increment: 10.34 MiB

%memit map_normal(nums)
peak memory: 138.57 MiB, increment: 0.00 MiB

可以看到,第一种方法占用了10.34MB的内存,第二个方法占用的内存是0MB,就是因为第二种方法使用了迭代模式。

欢迎关注微信公众号:Quant_Times
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值