[英]better for-loop syntax for detecting empty sequences?
是否有更好的方法來編寫以下內容:
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”在這里僅適用於空序列,我知道它沒有)
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
針對一般情況引入空序列的特殊情況似乎是錯誤的 。 針對特定領域的問題應該有更好的解決方案。
它可能是itertools.tee的工作你在驗證時“觸發”序列,但之后你會得到一個未經修改的序列副本:
from itertools import tee
check, sequence = tee(sequence, 2)
try:
check.next():
except StopIteration:
#empty sequence
for item in sequence:
#do stuff
(這是值得nting是tee
沒有“正確”的事情在這里:它會加載只是在那一刻序列的第一個元素check.next()
被執行-這第一elment將在保持現有sequence
其余項目將。只能作為for
循環的一部分檢索或者只是保持簡單:如果你不能使用len,你就無法檢查序列的bool值是否為True,原因相同。
因此,你的方式足夠簡單 - 另一種方法是在“for”語句之前刪除名稱“item”並檢查它是否在循環之后存在:
del item
for item in sequence:
# do stuff
try:
item
except NameError:
# sequence is empty.
但是你的代碼應該比它更清晰。
來自JF 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)
不是最簡潔但客觀上最清楚...泥,不是嗎?
這不應該觸發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))
if not iterable_sequence.__length_hint__():
empty()
else:
for item in iterable_sequence:
dostuff()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.