有没有更好的方法来编写以下内容:
row_counter = 0
for item in iterable_sequence:
# do stuff with the item
counter += 1
if not row_counter:
# handle the empty-sequence-case
请记住,我不能使用len(iterable_sequence),因为1)并非所有序列都具有已知长度; 2)在某些情况下,调用len()可能会触发将序列的项加载到内存中(与sql查询结果一样)。
我问的原因是,我只是好奇是否有办法使上述更简洁和惯用。我正在寻找的是:
for item in sequence:
#process item
*else*:
#handle the empty sequence case
(假设“else”仅适用于空序列,我知道它没有)
答案 0 :(得分:8)
for item in iterable:
break
else:
# handle the empty-sequence-case here
或
item = next(iterator, sentinel)
if item is sentinel:
# handle the empty-sequence-case here
在每种情况下,如果一个项目存在,则会消耗它。
评论中提到的empty_adapter()
实施的一个例子:
def empty_adaptor(iterable, sentinel=object()):
it = iter(iterable)
item = next(it, sentinel)
if item is sentinel:
return None # empty
else:
def gen():
yield item
for i in it:
yield i
return gen()
您可以按如下方式使用它:
it = empty_adaptor(some_iter)
if it is not None:
for i in it:
# handle items
else:
# handle empty case
为一般情况引入空序列的特殊情况似乎错误。对于特定领域的问题,应该有更好的解决方案。
答案 1 :(得分:3)
这可能是itertools.tee的工作 您在验证时“触发”序列,但之后会留下未经修改的序列副本:
from itertools import tee
check, sequence = tee(sequence, 2)
try:
check.next():
except StopIteration:
#empty sequence
for item in sequence:
#do stuff
(值得tee
在这里做“正确”的事情:它会在check.next()
被执行的那一刻加载序列的第一个元素 - 并且这个第一个元素将保持可用sequence
。剩余的项目只会作为for
循环的一部分进行检索
或者只是保持简单:
如果你不能使用len,你也无法检查序列的bool值是否为True,原因相同。
因此,你的方式很简单 - 另一种方法是在“for”语句之前删除名称“item” 在循环之后检查它是否存在:
del item
for item in sequence:
# do stuff
try:
item
except NameError:
# sequence is empty.
但是你的代码应该比它更明确。
答案 2 :(得分:2)
来自J.F. Sebastian的第二个例子似乎是带有一个while循环的票。
NoItem = object()
myiter = (x for x in range(10))
item = next(myiter, NoItem)
if item is NoItem:
...
else:
while item is not NoItem:
print item
item = next(myiter, NoItem)
不是最简洁但客观上最清楚......泥,不是吗?
答案 3 :(得分:1)
这不应该触发len()
:
def handle_items(items):
index = -1
for index, item in enumerate(items):
print 'processing item #%d: %r' % (index, item)
# at this point, index will be the offset of the last item,
# i.e. length of items minus one
if index == -1:
print 'there were no items to process'
print 'done'
print
# test with an empty generator and two generators of different length:
handle_items(x for x in ())
handle_items(x for x in (1,))
handle_items(x for x in (1, 2, 3))
答案 4 :(得分:0)
if not iterable_sequence.__length_hint__():
empty()
else:
for item in iterable_sequence:
dostuff()