• John Si 置顶
    2019-06-21
    我不知道如何把这技巧运用在编程中,老师能否举几个例子来说明一下呢?谢谢

    作者回复: 例子已经在文中举了不少,对于如何娴熟地在编程中运用,这个需要长时间的积累,从阅读别人高质量的源代码,自己主动有意识地在自己的项目中思考,最后才会形成质变,内化成自己的能力,从而清楚地知道哪里应该用高级语法,高级工具,哪里应该简单的一笔带过。Python 的生成器无疑是最有用的特性,但也是最不广泛被使用的特性,这一章的目的,能够让你对生成器有基本的了解,下次在代码中遇到,能够说,“这个我知道,这个我懂!”便已足够。加油!

     1
     15
  • Jingxiao 置顶
    2019-06-23
    思考题答案:
    很多同学的回复非常正确,生成器只能遍历一次,继续调用 next() 会 raise StopIteration。只有复位生成器才能重新进行遍历。
     1
     11
  • 时间小偷
    2019-06-21
    上一篇的分享mateclass写得看不懂,老师可否重新通俗写一下,分享嘉宾的风格跟老师不太一样啊
    
     48
  • Destroy、
    2019-06-21
    def is_subsequence(a, b):
        b = iter(b)
        print(b)

        gen = (i for i in a)
        print(gen)

        for i in gen:
            print(i)

        gen = ((i in b) for i in a)
        print(gen)

        for i in gen:
            print(i)

        return all(((i in b) for i in a))

    print(is_subsequence([1, 3, 5], [1, 2, 3, 4, 5]))
    print(is_subsequence([1, 4, 3], [1, 2, 3, 4, 5]))

    ########## 输出 ##########

    <list_iterator object at 0x000001E7063D0E80>
    <generator object is_subsequence.<locals>.<genexpr> at 0x000001E70651C570>
    1
    3
    5
    <generator object is_subsequence.<locals>.<genexpr> at 0x000001E70651C5E8>
    True
    True
    True
    False
    <list_iterator object at 0x000001E7063D0D30>
    <generator object is_subsequence.<locals>.<genexpr> at 0x000001E70651C5E8>
    1
    4
    3
    <generator object is_subsequence.<locals>.<genexpr> at 0x000001E70651C570>
    True
    True
    False
    False

    为什么这里的print(is_subsequence([1, 3, 5], [1, 2, 3, 4, 5]))会返回False?
    解释一下:
    因为
        gen = ((i in b) for i in a)
        print(gen)
        
        for i in gen:
            print(i)
    这段代码的 for i in gen 已经b的迭代器消耗完,此时的b已经是个空的迭代器。所以,再执行all(((i in b) for i in a)),就是False了。
    展开

    作者回复: 解释的很好

     1
     16
  • SCAR
    2019-06-21
    思考题:对于一个有限元素的生成器,如果迭代完成后,继续调用 next(),会跳出StopIteration:。生成器可以遍历多次吗?不行。也正是这个原因,老师代码复杂化那段代码,在
        gen = ((i in b) for i in a)
        for i in gen:
            print(i)
    之后应该是需要给b复位下,不然b会是空的,那么return回来永远会是False。

    这段判断是否是子序列的指针用的真是巧妙,区区几行,精华尽现。
    展开

    作者回复: 👍

    
     14
  • farFlight
    2019-06-21
    迭代完成后,继续调用 next()会出现StopIteration。
    生成器只能遍历一次,但是可以重新调用重新遍历。

    作者回复: 正确

    
     6
  • tt
    2019-06-21
    明白为啥要把b转换成迭代器了,是为了下面的代码中可以用next():

    while True:
        val = next(b)
        if val == i:
            yield True

    这样才可以利用next()可以保存指针位置的特性,从而确保子序列中元素的顺序。
    展开

    作者回复: 对,这里是个很巧妙的利用

    
     5
  • xiemanrui
    2019-06-29
    def is_subsequence(a, b):
        b = iter(b)
        print(b)

        gen = (i for i in a)
        print(gen)

        for i in gen:
            print(i)

        gen = ((i in b) for i in a)
        print(gen)

        for i in gen:
            print(i)

        return all(((i in b) for i in a))

    print(is_subsequence([1, 3, 5], [1, 2, 3, 4, 5]))
    print(is_subsequence([1, 4, 3], [1, 2, 3, 4, 5]))

    这个代码很容易让人误解,is_subsequence的返回结果永远是False的,因为迭代器b被用了两次了。
    展开
    
     4
  • Wing·三金
    2019-06-22
    思考题:其实开头就已经明示了答案,会出现 StopIteration Error。遍历是一次性,参考下面这段代码:

    def index_generator(L, target):
        for i, num in enumerate(L):
            if num == target:
                yield i

    result = index_generator([1, 6, 2, 4, 5, 23, 4, 54, 34, 3, 2], 2)
    print(list(result))
    print(list(result))

    ### output
    [2, 10]
    []

    补充一小点:上面的 isinstance(obj, Iterable) 中的 Iterable 需要先 from collections import Iterable。

    另外有个问题,py3 中的 range() 本质上也是 generator 吗?如果是,为何下面这段代码的结果会是这样呢?

    e = range(3)

    for i in e:
        print(i)
    for i in e:
        print(i)

    ### expected
    0
    1
    2
    ### real output
    0
    1
    2
    0
    1
    2

    请各位指教~!
    展开
     1
     3
  • Element 静婷
    2019-06-25
    老师好,请问子序列的问题中,[1,3,5]不是[1, 2, 3, 4, 5]吗?怎么返回false
    
     2
  • 許敲敲
    2019-06-22
    b = (i for i in range(5))

    print(2 in b)
    print(4 in b)
    print(3 in b)

    ########## 输出 ##########

    True
    True
    False

    这里面的判断4 in b后,指针已经在3 之后了吗?所以 3 in b 会返回 false

    反过来 如果
    b = (i for i in range(5))

    print(2 in b)
    print(3 in b)
    print(4 in b)

    ########## 输出 ##########

    True
    True
    True

    这么理解对吗?

    展开
    
     2
  • Redevil
    2019-06-21
    前三个布尔值打印的是a的三个元素在不在b中的判断结果
    第四个值是打印is_subsequence的最终返回值
    
     2
  • Hurt
    2019-06-21
    老师并没讲迭代器和可迭代对象区别,另外还有他们底层的实现,魔法方法
     1
     2
  • kyle
    2019-06-21
    gen = ((i in b) for i in a)
    实际上是先遍历 a,取出一个值赋给i,然后再判断i是否在b中,判断一次,b中的指针后移一位。

    所以,第一轮的输出应该是:TRUE,TRUE,TRUE(前三个是for循环打印的,因为a中有3个元素),TRUE(最后一个是函数返回的);

    第二轮输出是:TRUE,TRUE,FALSE,FALSE
    展开
    
     2
  • 鱼_XueTr
    2019-06-21
    会引发StopIteration。
    生成器只能使用一次。

    作者回复: 👍

    
     2
  • 蒋腾飞同学
    2019-09-23
    老师好 ,生成器(i for i in range(5))和tuple数据很像,都是可迭代的,请问有什么本质区别吗?都是小括号扩起来~
    
     1
  • 夜雨声烦
    2019-09-21
    对于'gen = ((i in b) for i in a)'部分的理解,"for i in a"很好理解,就是遍历生成器a,重点在"(i in b)",这个行代码的意思老师已经说过了,需要注意的是的迭代器的next就像是消费数据一样,消费了之后前面的数据就没了。以最后一个例子为例,b中存的是(0,1,2,3,4),执行print(2 in b)时会消费掉(0,1,2),执行print(4 in b)会消耗(3,4),因此执行print(3 in b)已经没数据了才会返回False。如果按照如下顺序都会返回true:
    b = (i for i in range(5))
    print(2 in b)
    print(3 in b)
    print(4 in b)

    还有def is_subsequence(a, b)代码块中,第一个数据最终应该输入True啊,怎么会输出false呢..
    展开
    
     1
  • 佛本是道
    2019-07-19
    生成器复位怎么操作?
    
     1
  • 超人
    2019-06-26
    看完文章后一直不明白为什么输出的是
    true,true,true,false
    true,true,false,false,以及最后的例子输出true,true,false
    看完看完评论后搞懂了,关键在下面代码
    while True:
        val = next(b)
        if val == i:
            yield True

    1,4,3列表,在判断4时,指针指向迭代器4的位置,判断3时,next是5,所以返回false



    展开
    
     1
  • Monroe He
    2019-06-24
    列表元组字典集合都是可迭代对象,它们可以通过 iter() 函数返回一个迭代器,再通过next()函数就可以实现遍历,for in语句将整个过程隐式化。
    gen = ((i in b) for i in a)
    print(gen)
    for i in gen:
        print(i)
    先得到a中的一个元素i; 迭代b,检查i是否与b当前位置相等,如果i与b当前位置元素相等,则返回True,b继续停留在当前位置,等待下次从当前位置开始迭代。

    问题:b是一个迭代器,如果在之前不将b转换为迭代器,而保持b为可迭代对象(也就是列表)为什么不行。因为之前说过for in 语句会隐式化地执行iter()函数,并利用next()函数进行遍历。既然可以隐式化的执行,为什么要将列表转为迭代器呢?
    展开
    
     1
我们在线,来聊聊吧