Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 检查发电机是否真的在一条线上产生了一些东西_Python_Iterator_Generator - Fatal编程技术网

Python 检查发电机是否真的在一条线上产生了一些东西

Python 检查发电机是否真的在一条线上产生了一些东西,python,iterator,generator,Python,Iterator,Generator,当结果是某个集合时,库的许多函数我使用returngenerators而不是lists 有时我只想检查结果是否为空,当然我不能写这样的东西: result = return_generator() if result: print 'Yes, the generator did generate something!' 现在,我提出了一种解决此问题而不消耗发电机的单衬套: result = return_generator() if zip("_", res

当结果是某个集合时,库的许多函数我使用return
generator
s而不是
list
s

有时我只想检查结果是否为空,当然我不能写这样的东西:

   result = return_generator()
   if result:
      print 'Yes, the generator did generate something!'
现在,我提出了一种解决此问题而不消耗发电机的单衬套:

   result = return_generator()
   if zip("_", result):
      print 'Yes, the generator did generate something!'
from itertools import tee
a, b = tee(xrange(0))
try:
    next(a)
    print list(b)
except StopIteration:
    print "f1 was empty"


a, b = tee(xrange(3))
try:
    next(a)
    print list(b)
except StopIteration:
    print "f2 was empty"

>>>
[0, 1, 2, 3]
f2 was empty

我想知道是否有更干净的方法来解决这个问题,只需一行?

而不是返回发电机,直接使用它?下面是一个生成器示例,它可能返回结果,也可能不返回结果-如果有结果,则执行操作;如果没有结果,则不执行操作

#!/usr/bin/python

import time

def do_work():
    if int(time.time()) % 2:
        for a in xrange(0,100):
            yield a

for thing in do_work():
    print thing

这个
zip
东西会吃掉第一件物品,所以这也不是一个好主意

您只能通过获取并保存到需要时,才能检测生成器是否有项目。下面的课程将帮助你做到这一点

如果需要,它从迭代器中获取一个项并保存它

如果请求清空(
如果myiterwatch:…
),它将尝试获取并返回是否可以获取

如果请求下一个项目,它将返回检索到的项目或新项目

class IterWatch(object):
    def __init__(self, it):
        self.iter = iter(it)
        self._pending = []
    @property
    def pending(self):
        try:
            if not self._pending:
                # will raise StopIteration if exhausted
                self._pending.append(next(self.iter))
        except StopIteration:
            pass # swallow this
        return self._pending
    def next(self):
        try:
            return self.pending.pop(0)
        except IndexError:
            raise StopIteration
    __next__ = next # for Py3
    def __iter__(self): return self
    def __nonzero__(self):
        # returns True if we have data.
        return not not self.pending
        # or maybe bool(self.pending)
    __bool__ = __nonzero__ # for Py3

这以一种非常通用的方式解决了这个问题。如果您有一个只想测试的迭代器,那么可以使用

guard = object()
result = return_generator()
if next(result, guard) is not guard:
    print 'Yes, the generator did generate something!'
next(a,b)
如果迭代器
a
耗尽,则返回
b
。因此,在我们的例子中,如果它返回守卫,它不会生成任何东西,否则它会生成


但是您的
zip()
方法也是非常有效的…

这里有一种方法使用itertools tee函数复制生成器:

   result = return_generator()
   if zip("_", result):
      print 'Yes, the generator did generate something!'
from itertools import tee
a, b = tee(xrange(0))
try:
    next(a)
    print list(b)
except StopIteration:
    print "f1 was empty"


a, b = tee(xrange(3))
try:
    next(a)
    print list(b)
except StopIteration:
    print "f2 was empty"

>>>
[0, 1, 2, 3]
f2 was empty

以下是我能想到的两个最简单的解决方案:

def f1():
    return (i for i in range(10))

def f2():
    return (i for i in range(0))


def has_next(g):
    try:
        from itertools import chain
        return chain([g.next()],g)
    except StopIteration:
        return False

g = has_next(f1())
if g:
    print list(g)

g = has_next(f2())
if g:
    print list(g)


def has_next(g):
    for i in g:
        return chain([i],g)
    return False

g = has_next(f1())
if g:
    print list(g)

g = has_next(f2())
if g:
    print list(g)

唉,我今天真是脑子不好。我急切地等待有能力回答这个问题的人P@detly不,它不会消耗发电机。你可以编写一个生成器,在生成和测试时打印。是的,我在测试它时意识到了这一点(尽管它消耗了第一项)。这就是为什么我删除了我最初的评论:正常情况下,这可能会起作用,但也有可能在某些情况下,这不起作用。好吧,我正处于我的座位边缘。。什么样的情况?@glglgl:比如说?(这可能值得在您现有的答案中详细说明。)考虑在使用生成的项目之前,您必须准备一些东西。这种准备可能很昂贵,如果没有要处理的项目,可以省略。可以将准备工作放入循环并设置标志(如果已完成),但将其置于循环之前看起来更好(IMHO)。是的,考虑到我以后要使用生成器的情况,我必须采取措施恢复消耗的“第一个元素”。但我认为这是非常罕见的,因为在这种情况下,我只需在生成器上迭代,甚至事先都没有检查。感谢您解释
next
:)+1的第二个参数,让我学到了一些东西。有什么是itertools不能做的吗?谢谢。只要小心,如果其中一个iterable(a或b)远远领先于另一个iterable,那么它生成的所有值都必须存储在一个列表中,以便另一个iterable稍后获得。因此,此解决方案可能会占用大量内存。我建议了一个更好的解决方案。
def(n):return(在范围(n)内的I表示I))
tee(f(10))
tee(f(0))
将是另一种选择。
for I in g:return chain([I],g)
我花了一段时间才理解。但这很好:-)