Python中的推导式!

列表表达式

  • 产生列表(生成列表)

一般的表达形式:[handle(item) for item in iterable if condition]

简单示例:我们先挑选0-10里所有的奇数计算其3次方的结果,并存入一个列表。

[i**3 for i in range(11) if i%2==1]
[1, 27, 125, 343, 729]

对比列表表达式的效率

创建一个用以计时的装饰器:

from time import time
def timer(func):
    def warper(*args):
        start = time()
        func(*args)
        print("{}: 运行时间{:.3f}s".format(func.__name__, time()-start))
    return warper
@timer
def func1():
    res = []
    for i in range(100000):
        if i%2 == 0:
            res.append(i)
func1()
func1: 运行时间0.009s
%timeit [i for i in range(100000) if i%2==0]
4.84 ms ± 201 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
@timer
def func2():
    [i for i in range(100000) if i%2==0]
func2()
func2: 运行时间0.006s

即便是放在函数中运行,整体的效率还是要比append()这种方式快。在产生列表的时候建议使用优雅的列表表达式来实现!

一个困惑的实验

[print(i) for i in range(10) if i%2==1]
1
3
5
7
9





[None, None, None, None, None]

在交互式环境中,我们发现。在列表表达式中完成一个过程(目的不在产生一个数组),尽管我们成功打印了0-9的所有的奇数。但是在内存中我们创建了同等尺寸的一个None组成的数组。

尽管列表表达式可以约束一个序列的过程执行,但是个人不推荐这么使用!

字典表达式

我们用形如:{item: val for item in iterable if condition},可以创建一个字典(完成初始化)。

names = ['sand', 'leo', 'nacy', 'tony']
records = {name: 0 for name in names}
records
{'sand': 0, 'leo': 0, 'nacy': 0, 'tony': 0}

我们可以使用字典表达式来完成一个静态字典的初始化。

动态字典生成,我个人更推荐使用collections中的defaultdict

生成器表达式

形如:(item for item in iterable if condition), 我们会得到一个生成器。

generator = (i for i in range(10) if i%2==1)
generator
<generator object <genexpr> at 0x10af569e0>
for i in generator:
    print(i)
1
3
5
7
9

列表表达式更进一步的优雅

生成器和列表表达式比较最明显的就是在内存上的节省了。计算0-9所有奇数的和,我们优雅点实现:

sum([i for i in range(10) if i%2==1])
25
sum((i for i in range(10) if i%2==1))
25
  • 好消息,这里的括号可以缺省。
sum(i for i in range(10) if i%2==1)
25
help(sum)
Help on built-in function sum in module builtins:

sum(iterable, /, start=0)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers
    
    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.

这里揭示了一点,如果函数接受iterable的参数,我们都可以用列表表达式传递,同样我们也可以使用生成器表达式实现。

例如pandas.concat()接受一个dataframe的序列作为参数,那么我们可以用生成器表达式传入需要合并的数据集的同时可以节约内存空间。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值