簡體   English   中英

用於檢測空序列的更好的for循環語法?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM