当结果是某些集合时,我使用的许多函数返回generator
而不是list
。
有时我只想检查结果是否为空,当然我不能写出类似的内容:
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!'
我想知道是否有更简洁的方法来解决这个问题在一行?
答案 0 :(得分:4)
这是使用itertools tee函数的一种方法,它复制了生成器:
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
答案 1 :(得分:3)
这zip
个东西吃了第一个产品,所以这也不是一个好主意。
您只能通过获取并保持生成器来检测生成器是否有产品,直到需要为止。以下课程将帮助您完成此任务。
如果需要,它会从迭代器中获取一个项目并保留它。
如果要求清空(if 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)
用尽, b
将返回a
。因此,如果它在我们的情况下返回守卫,它就不会产生某些东西,否则就会产生。
但您的zip()
方法也完全有效......
答案 2 :(得分:2)
而不是返回发电机,只需使用它?这是一个可能会或可能不会返回结果的生成器示例 - 如果有结果操作,如果没有结果则不采取任何操作。
#!/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
答案 3 :(得分:1)
以下是我能想到的两种最简单的解决方案:
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)