web-dev-qa-db-ja.com

PythonイテレータのhasNext?

PythonイテレータにはhasNextメソッドがありませんか?

133
Juanjo Conti

いいえ、そのような方法はありません。反復の終了は例外によって示されます。 ドキュメント を参照してください。

89
avakar

next(iterator, default_value)を使用して、StopIterationに代わるものがあります。

例:

>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None

そのため、例外の方法が望ましくない場合は、Noneまたはイテレータの末尾のその他の事前に指定された値を検出できます。

193
Derrick Zhang

本当に必要has-next機能(Javaの参照実装からアルゴリズムを忠実に転写しているため、またはプロトタイプを書いているためwill終了したらJavaに簡単に転写する必要があります)、小さなラッパークラスで簡単に取得できます。例えば:

class hn_wrapper(object):
  def __init__(self, it):
    self.it = iter(it)
    self._hasnext = None
  def __iter__(self): return self
  def next(self):
    if self._hasnext:
      result = self._thenext
    else:
      result = next(self.it)
    self._hasnext = None
    return result
  def hasnext(self):
    if self._hasnext is None:
      try: self._thenext = next(self.it)
      except StopIteration: self._hasnext = False
      else: self._hasnext = True
    return self._hasnext

今のようなもの

x = hn_wrapper('ciao')
while x.hasnext(): print next(x)

放出する

c
i
a
o

要求に応じ。

next(sel.it)をビルトインとして使用するには、Python 2.6以上が必要です。古いバージョンのPythonを使用している場合は、代わりにself.it.next()を使用します(使用例のnext(x)についても同様)。 [[このノートは冗長であると合理的に思うかもしれません。Python 2.6は1年以上前から存在しますが、応答でPython 2.6の機能を使用する場合はそうではありません。 、一部のコメント作成者などは、それらがare 2.6の機能であることを指摘する義務があると感じています。したがって、このようなコメントを一度だけ回避しようとしています。

33
Alex Martelli

StopIterationのすべての言及に加えて、Python "for"ループは単にあなたが望むことをします:

>>> it = iter("hello")
>>> for i in it:
...     print i
...
h
e
l
l
o
12
Brian Clapper

イテレータオブジェクトから__length_hint __()メソッドを試してください。

iter(...).__length_hint__() > 0
7
juj

hasNextはややStopIteration例外に変換されます。例:

>>> it = iter("hello")
>>> it.next()
'h'
>>> it.next()
'e'
>>> it.next()
'l'
>>> it.next()
'l'
>>> it.next()
'o'
>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
5
miku

teeイテレータを使用して、itertools.teeを使用し、ティードイテレータでStopIterationを確認できます。

4
sykora

いいえ。最も類似した概念は、おそらく StopIteration例外 です。

3
James Thompson

pythonにはnext()があるだけで、ドキュメントによると、これ以上要素がないと例外をスローすると思います。

http://docs.python.org/library/stdtypes.html#iterator-types

2
Charles

これを検索することになったユースケースは次のとおりです

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        try:
            x = next(fi)
        except StopIteration:
            fi = iter(f)
            x = next(fi)
        self.a[i] = x 

hasnext()が利用可能な場合、次のようにすることができます

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        if not hasnext(fi):
            fi = iter(f) # restart
        self.a[i] = next(fi)

私にとってはきれいです。明らかにユーティリティクラスを定義することで問題を回避できますが、その後に起こることは20種類の異なるほぼ同等の回避策がそれぞれの癖で急増していることであり、異なる回避策を使用するコードを再利用する場合は、単一のアプリケーションで複数のほぼ同等のものを使用するか、同じアプローチを使用するようにコードを選択して書き換えます。 「一度やればうまくやる」という格言はひどく失敗する。

さらに、イテレーター自体には、例外を発生させる必要があるかどうかを確認するために実行する内部「hasnext」チェックが必要です。この内部チェックは非表示になるため、アイテムを取得して例外をキャッチし、スローされた場合はハンドラーを実行してテストする必要があります。これは不要なIMOの非表示です。

1
John Allsup

推奨される方法はStopIterationです。 tutorialspoint のフィボナッチの例を参照してください

#!usr/bin/python3

import sys
def fibonacci(n): #generator function
   a, b, counter = 0, 1, 0
   while True:
      if (counter > n): 
         return
      yield a
      a, b = b, a + b
      counter += 1
f = fibonacci(5) #f is iterator object

while True:
   try:
      print (next(f), end=" ")
   except StopIteration:
      sys.exit()
0
Ramin Darvishov

そのような質問/問題に対する良いアプローチは、dir(object/method/iterator/type/class/...)にあるものをチェックすることです

dir(iterator)__length_hint__を返すことがわかります

iterator.__length_hint__()は、反復が終了するまで正です。

それでおしまい。

0