Java程序猿学Python---集合推导式 Comprehension和生成表达式Generator Expression

集合表达式是Python强大的功能之一,每个Python必须学习基本功。

List推导式(List Comprehension)

快速创建List集合

>>> [x * x for x in range(10)]              # List comprehension: builds list
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]        # Like list(generator expr)
>>> [x for x in range(5) if x % 2 == 0]
[0, 2, 4]
>>> list(filter((lambda x: x % 2 == 0), range(5)))
[0, 2, 4]
>>> res = []
>>> for x in range(5):
        if x % 2 == 0:
            res.append(x)
>>> res
[0, 2, 4]

list comprehension相比于lambda和for循环都要简单的多。

>>> res = [x + y for x in [0, 1, 2] for y in [100, 200, 300]]
>>> res
[100, 200, 300, 101, 201, 301, 102, 202, 302]

list comprehension中可以嵌套多个for语句,相当于嵌套的for循环一样。

Set推导式(Set Comprehension)

快速创建不含重复元素的Set集合

>>> {x * x for x in range(10)}              # Set comprehension, 3.X and 2.7
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}        # {x, y} is a set in these versions too

用法和List Comprehension类似。

Dictionary推导式(Dictionary Comprehension)

快速创建Dictionary集合,类似于java中的Map。

>>> {x: x * x for x in range(10)}        # Dictionary comprehension, 3.X and 2.7
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

用法和List Comprehension类似。

生成表达式(Generator Expression)

生成表达式相对于推导式来说复杂一些,这里会慢慢道来。
首先看一下生成表达式和生成函数:

>>> (x * x for x in range(4))

>>> def gensquares():
        for x in range(4):
            yield x * x

这个表达式和函数的作用是一样的,只是生成表达式是生成函数的简写形式,或者说是简单形式。想要了解清楚生成表达式,先要理解生成函数。而生成函数和一般的函数基本一样,主要是多了一个关键字yield,类似普通函数中的return语句,但是yield语句不会立即返回结果,而是在需要的时候调用next方法(或内部的_next_方法)获取结果,类似java中的迭代器Iterable。

>>> f = gensquares()
>>> next(f)
0
>>> next(f)
1
>>> next(f)
4
>>> next(f)
9
>>> next(f)
Traceback (most recent call last):
  File "<pyshell#94>", line 1, in <module>
    next(f)
StopIteration
>>> 

有2点需要注意的:

  1. 生成器对象只能迭代一次,也就说只能顺序访问一次。
  2. 当生成对象访问完了之后再次访问会抛出StopIteration异常。

综上所述,生成表达式对于大数据量的集合迭代操作有天生的性能优势,因为每次迭代只是计算部分数据。

yield也可以在一个方法的多个地方使用:

>>> def both():
    for i in range(2): yield i
    for i in (x**2 for x in range(2)): yield i
>>> f = both()
>>> next(f)
0
>>> next(f)
1
>>> next(f)
0
>>> next(f)
1
>>> next(f)
Traceback (most recent call last):
  File "<pyshell#102>", line 1, in <module>
    next(f)
StopIteration
>>> 

yield from的用法

>>> def both():
    yield from range(2)
    yield from (x**2 for x in range(2))

这个方法和上一个例子中的方法是一样的,只不过是一种简单的写法而已。

send方法

>>> def gen():
        for i in range(10):
            X = yield i
            print(X)
>>> G = gen()
>>> next(G)             # Must call next() first, to start generator
0
>>> G.send(77)      # Advance, and send value to yield expression
77
1
>>> G.send(88)
88
2
>>> next(G)             # next() and X.__next__() send None
None
3

send(a)方法会将a传递给方法中的X (yield的返回值),并触发下一次迭代,这样send方法可以给下次迭代增加一些业务处理。没有send方法调用的情况下,yield表达式返回None。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shadon178

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值