是否有一种简单的方法来测试生成器是否没有项目,比如peek, hasNext, isEmpty之类的?
当前回答
下面是一个包装生成器的简单装饰器,因此如果为空,它将返回None。如果您的代码需要知道生成器在循环遍历之前是否会生成任何东西,那么这可能很有用。
def generator_or_none(func):
"""Wrap a generator function, returning None if it's empty. """
def inner(*args, **kwargs):
# peek at the first item; return None if it doesn't exist
try:
next(func(*args, **kwargs))
except StopIteration:
return None
# return original generator otherwise first item will be missing
return func(*args, **kwargs)
return inner
用法:
import random
@generator_or_none
def random_length_generator():
for i in range(random.randint(0, 10)):
yield i
gen = random_length_generator()
if gen is None:
print('Generator is empty')
一个有用的例子是在模板代码中—即jinj2
{% if content_generator %}
<section>
<h4>Section title</h4>
{% for item in content_generator %}
{{ item }}
{% endfor %
</section>
{% endif %}
其他回答
我用求和函数解出来了。请参阅下面我使用glob的示例。Iglob(返回一个生成器)。
def isEmpty():
files = glob.iglob(search)
if sum(1 for _ in files):
return True
return False
*这可能不适用于巨大的生成器,但对于较小的列表应该表现得很好
Quick-dirty解决方案:
next(generator, None)不是None
或者将None替换为任何你知道不在生成器中的值。
编辑:是的,这将跳过生成器中的一项。然而,有时我只是出于验证目的检查生成器是否为空,然后并不真正使用它。否则我就会这样做:
def foo(self):
if next(self.my_generator(), None) is None:
raise Exception("Not initiated")
for x in self.my_generator():
...
也就是说,如果您的生成器来自一个函数,如my_generator(),则此方法有效。
对于这种显而易见的方法,我很抱歉,但最好的方法是:
for item in my_generator:
print item
现在您已经检测到在使用生成器时它是空的。当然,如果生成器为空,项将永远不会显示。
这可能不完全适合您的代码,但这就是生成器的习惯用法:迭代,所以您可能会稍微改变您的方法,或者根本不使用生成器。
>>> gen = (i for i in [])
>>> next(gen)
Traceback (most recent call last):
File "<pyshell#43>", line 1, in <module>
next(gen)
StopIteration
在生成器结束时引发StopIteration,因为在您的情况下立即到达结束,因此引发异常。但通常你不应该检查下一个值是否存在。
你可以做的另一件事是:
>>> gen = (i for i in [])
>>> if not list(gen):
print('empty generator')
在我的例子中,我需要知道在我将一组生成器传递给一个函数之前,它是否已经填充,该函数合并了这些项,即zip(…)。解决方案与公认的答案相似,但又有足够的不同:
定义:
def has_items(iterable):
try:
return True, itertools.chain([next(iterable)], iterable)
except StopIteration:
return False, []
用法:
def filter_empty(iterables):
for iterable in iterables:
itr_has_items, iterable = has_items(iterable)
if itr_has_items:
yield iterable
def merge_iterables(iterables):
populated_iterables = filter_empty(iterables)
for items in zip(*populated_iterables):
# Use items for each "slice"
我的特定问题具有这样的属性,即可迭代对象要么为空,要么具有完全相同数量的条目。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录