标签: generator

Ruby生成器与Python生成器

我一直在研究Ruby和Python生成器之间的相似之处/差异(Enumerators在Ruby中称为),并且据我所知,它们几乎相同.

然而,我注意到的一个区别是Python Generators支持一种close()方法,而Ruby Generators则不支持.从Python文档中可以看出该close()方法执行以下操作:

在生成器功能暂停的位置引发GeneratorExit.如果生成器函数然后引发StopIteration(通过正常退出,或者由于已经关闭)或GeneratorExit(通过不捕获异常),则关闭返回其调用者.

Ruby Enumerators不支持该close()方法有充分的理由吗?还是意外遗漏?

我还发现Ruby Enumerators支持一种rewind()方法,而Python生成器却没有......这也是有原因的吗?

谢谢

ruby python generator enumerator

20
推荐指数
2
解决办法
4542
查看次数

一起循环两个发电机

我有两个发电机说A()B().我想一起迭代两个生成器.就像是:

for a,b in A(),B():    # I know this is wrong
    #do processing on a and b
Run Code Online (Sandbox Code Playgroud)

一种方法是将两个函数的结果存储在列表中,然后遍历合并列表.像这样的东西:

resA = [a for a in A()]
resB = [b for b in B()]
for a,b in zip(resA, resB):
    #do stuff
Run Code Online (Sandbox Code Playgroud)

如果您想知道,那么两个函数都会产生相同数量的值.

但是我不能使用这种方法因为A()/B()返回了这么多的值.将它们存储在列表中会耗尽内存,这就是我使用生成器的原因.

有没有办法一次循环两个发电机?

python loops for-loop yield generator

20
推荐指数
1
解决办法
8745
查看次数

JavaScript中的递归生成器

我正在尝试为顺序遍历编写递归生成器.

class Tree {
  *inOrderTraversal() {
    function* helper(node) {
      if (node.left !== null) {
        // this line is executed, but helper is not being called
        helper(node.left); 
      }
      yield node.value;
      if (node.right !== null) {
        helper(node.right);
      }
    }

    for (let i of helper(this.root)) {
      yield i;
    }
  }
  // other methods omitted
}
Run Code Online (Sandbox Code Playgroud)

我这样称呼发电机:

const tree = new Tree();
tree.add(2);
tree.add(1);
tree.add(3);

for (let i of tree.inOrderTraversal()) {
    console.log(i); // only prints 2
}
Run Code Online (Sandbox Code Playgroud)

为什么发电机只能屈服2?为什么它至少没有产生1之前2? …

javascript recursion generator ecmascript-6

20
推荐指数
2
解决办法
4934
查看次数

从python生成器接收'return'值的最佳方法

从Python 3.3开始,如果生成器函数返回一个值,那么它将成为引发的StopIteration异常的值.这可以通过多种方式收集:

  • yield from表达式的值,暗示封闭函数也是一个生成器.
  • 将调用包含在try/except块中next().send()中.

但是,如果我只是想在for循环中迭代生成器 - 最简单的方法 - 似乎没有办法收集StopIteration异常的值,从而收集返回值.我使用一个简单的例子,其中生成器产生值,并在最后返回某种摘要(运行总计,平均值,时间统计等).

for i in produce_values():
    do_something(i)

values_summary = ....??
Run Code Online (Sandbox Code Playgroud)

一种方法是自己处理循环:

values_iter = produce_values()
try:
    while True:
        i = next(values_iter)
        do_something(i)
except StopIteration as e:
    values_summary = e.value
Run Code Online (Sandbox Code Playgroud)

但这会抛弃for循环的简单性.我无法使用,yield from因为这需要调用代码本身就是一个生成器.有没有比上面显示的roll-one-own for循环更简单的方法?

答案摘要

结合@Chad S.和@KT的答案,最简单的似乎是使用迭代器协议将我的生成器函数转换为类:

class ValueGenerator():
    def __iter__(self):
        yield 1
        yield 2
        # and so on
        self.summary = {...}

vg = ValueGenerator()
for i in vg:
    do_something(i)
values_summary = vg.summary
Run Code Online (Sandbox Code Playgroud)

如果我不能重构价值生产者,@ Ferdinand Beyer的答案是最简单的.

python generator

20
推荐指数
3
解决办法
6897
查看次数

Class中的鼻子测试生成器

是否可以在自定义类中运行nose测试生成器?我试图将示例转换为基于类的简单版本:

file: trial.py
>>>>>>>>>>>>>>
class ATest():
    def test_evens(self):
        for i in range(0, 5):
            yield self.check_even, i, i * 3

    def check_even(self, n, nn):
        assert n % 2 == 0 or nn % 2 == 0
Run Code Online (Sandbox Code Playgroud)

这导致了

$ nosetests -v trial.py
----------------------------------------------------------------------
Ran 0 tests in 0.000s
Run Code Online (Sandbox Code Playgroud)

我查看了更改日志,并认为这应该从版本0.9.0a1开始工作.

我哪里错了?

python generator nose

19
推荐指数
1
解决办法
7349
查看次数

Python使用异常控制流被认为是坏的?

行,

我过去曾多次看过这个,但最近我的问题在这里.所以,我很好奇为什么会这样,在python中,因为生成器使用异常来指示数据的结束.

如果对于每个使用python的人都这么糟糕,为什么语言将它包含在被认为是基本控制结构的内容中呢?对于那些想要阅读相关PEP的人,请访问此处.

python generator try-catch

19
推荐指数
1
解决办法
7746
查看次数

为什么这个闭包没有修改封闭范围内的变量?

这一点Python不起作用:

def make_incrementer(start):
    def closure():
        # I know I could write 'x = start' and use x - that's not my point though (:
        while True:
            yield start
            start += 1
    return closure

x = make_incrementer(100)
iter = x()
print iter.next()    # Exception: UnboundLocalError: local variable 'start' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

我知道如何解决这个错误,但请耐心等待:

这段代码工作正常:

def test(start):
    def closure():
        return start
    return closure

x = test(999)
print x()    # prints 999
Run Code Online (Sandbox Code Playgroud)

为什么我可以读取start闭包内的变量而不是写入它?导致这种start变量处理的语言规则是什么?

更新:我发现这个SO帖子相关(答案不仅仅是问题):读/写Python闭包

python closures generator

19
推荐指数
2
解决办法
6830
查看次数

我如何使`await ...`使用`yield return`(即在迭代器方法中)?

我有现有的代码,看起来类似于:

IEnumerable<SomeClass> GetStuff()
{
    using (SqlConnection conn = new SqlConnection(connectionString))
    using (SqlCommand cmd = new SqlCommand(sql, conn)
    {
        conn.Open();
        SqlDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            SomeClass someClass = f(reader); // create instance based on returned row
            yield return someClass;
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

看来我可以通过使用获益reader.ReadAsync().但是,如果我只修改一行:

        while (await reader.ReadAsync())
Run Code Online (Sandbox Code Playgroud)

编译器通知我await只能在标async有的方法中使用,并建议我修改方法签名为:

async Task<IEnumerable<SomeClass>> GetStuff()
Run Code Online (Sandbox Code Playgroud)

但是,这样做会导致GetStuff()无法使用,因为:

body GetStuff()不能是迭代器块,因为Task<IEnumerable<SomeClass>>它不是迭代器接口类型.

我确信我错过了异步编程模型的关键概念.

问题:

  • 我可以ReadAsync()在我的迭代器中使用吗?怎么样?
  • 我怎样才能以不同的方式思考异步范式,以便了解它在这种情况下的工作原理?

c# ado.net generator yield-return async-await

19
推荐指数
3
解决办法
9254
查看次数

如果Python生成器不再使用但尚未达到StopIteration,那么它是否会被垃圾收集?

当不再使用发电机时,应该进行垃圾收集,对吧?我尝试了以下代码,但我不确定哪个部分我错了.

import weakref
import gc

def countdown(n):
    while n:
        yield n
        n-=1

cd = countdown(10)
cdw = weakref.ref(cd)()
print cd.next()
gc.collect()
print cd.next()
gc.collect()
print cdw.next()
Run Code Online (Sandbox Code Playgroud)

在最后一行,我打电话给垃圾收集器,因为没有再打电话cd了.gc应该是自由的cd.但是当我打电话时cdw.next(),它仍然打印8.我再试了几次cdw.next(),它可以成功打印所有其余的,直到StopIteration.

我试过这个是因为我想了解生成器和协同程序是如何工作的.在David Beazley的PyCon演讲"关于协同程序和并发的好奇课程"的幻灯片28中,他说一个协程可以无限期地运行,我们应该用.close()它来关闭它.然后他说垃圾收集器会打电话.close().根据我的理解,一旦我们打电话给.close()自己,gc就会.close()再次打电话.会gc收到警告说它无法调用.close()已经关闭的协程吗?

谢谢你的任何投入.

python garbage-collection generator coroutine

19
推荐指数
2
解决办法
2120
查看次数

什么是ES6生成器以及如何在node.js中使用它们?

我今天在node.js聚会,我遇到的人说node.js有es6生成器.他说,这是对回调式编程的巨大改进,并将改变节点格局.Iirc,他说了一些关于调用堆栈和异常的内容.

我查了一下它们,但还没有找到任何以初学者友好的方式解释它们的资源.什么是生成器的高级概述,与回调的不同(或更好?)有何不同?

PS:如果你能提供一段代码来强调常见场景的差异(发出http请求或db调用),那将非常有用.

javascript generator node.js ecmascript-6

19
推荐指数
3
解决办法
6205
查看次数