java 迭代器的hasnext,在Python迭代器中具有hasNext?

Python迭代器是否没有hasNext方法?

相关:我如何知道一开始发电机是否为空?

使用next(iterator, default_value)可以替代StopIteration。

例如:

>>> a = iter('hi')

>>> print next(a, None)

h

>>> print next(a, None)

i

>>> print next(a, None)

None

因此,如果您不想使用异常方法,则可以检测到None或迭代器末尾的其他预先指定的值。

如果将"无"用作"前哨",则最好确保迭代器没有任何"无"。您还可以执行sentinel = object()和next(iterator, sentinel)并使用is进行测试。

在@samboosalis之后,我宁愿使用内置的unittest.mock.sentinel对象,该对象允许您先编写显式的next(a, sentinel.END_OF_ITERATION),然后编写if next(...) == sentinel.END_OF_ITERATION

这比例外还漂亮

不,没有这样的方法。迭代结束由异常指示。请参阅文档。

"请求宽恕比允许容易。"

"请求宽容比允许要容易。":检查迭代器是否具有下一个元素并不要求允许。在某些情况下,您想测试下一个元素的存在而不消耗它。如果有unnext()方法可以通过调用next()检查第一个元素是否存在,那么我将接受尝试捕获解决方案。

@Giorgio,如果不执行另一个生成元素的代码,就无法知道另一个元素是否存在(您不知道生成器是否将执行yield)。当然,编写存储next()结果并提供has_next()和move_next()的适配器并不难。

可以使用相同的思想来实现hasNext()方法(在成功时产生,缓存并返回true,或者在失败时返回false)。然后hasNext()和next()都将依赖于通用的基础getNext()方法和缓存项。如果真的很容易实现提供它的适配器,我真的不明白为什么next()不应该出现在标准库中。

@乔治,我不明白你在说什么。 next是标准;它抛出序列的末尾。适配器可以使用此next并缓存该值。没有人说它不应该在标准库中。我猜只是没有需求。

我了解,我认为不将其纳入标准的动机是技术上的。正如您所说,可能对它的需求根本不够。

@Giorgio,我大体上同意你的观点,尽管:如果hasNext()在标准库中,则所有迭代器都将被强制实现(或者如果不支持它,则返回错误……在那里进行设计决策)。对于某些迭代器而言,这些迭代器对时间的上下文高度敏感,因此迭代器中第一项的值可以在对hasNext()的调用与对next()的调用之间(可能在不同的模块中)改变,结果next()返回一个过时的值。我不知道,只是想看看争论的双方。我同意这样做会有帮助。

@LarsH:您的意思是例如从文件读取的迭代器可以在读取文件时更改?我同意这可能是一个问题(这会影响提供next()和hasNext()方法的任何库,而不仅仅是一个假设的Python库)。所以是的,如果要扫描的流的内容取决于何时读取元素,则next()和hasNext()会变得很棘手。

@Giorgio:是的,这就是我在想的一个例子。因此,当Python glob库的iglob()返回一个迭代器时,我们会遇到这个问题:一个迭代器,其返回值对时间敏感(即不是纯函数)。那么这是否意味着不应将诸如I / O之类的不纯函数作为迭代器使用?设计决策...

您都可以通过两种方式寻求许可。这不是C;)我想没有has_next(),因为它会使事情变得复杂。

python通常缺乏基本语言用法的结构,这些结构迫使诸如捕获异常之类的事情发生。然后,它或多或少地被认为是正确的做事方式而变得合理。另一个是缺少do .. while

如果您确实需要has-next功能(例如,因为您只是忠实地从Java的参考实现中转录算法,或者是因为您正在编写原型,则需要在完成后轻松将其转录为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已经存在一年多了-但是当我在响应中使用Python 2.6功能时,很多评论者或其他人有责任指出它们是2.6功能,因此,我尝试一次阻止此类评论;-)]]

"忠实地从Java参考实现中转录算法"是需要has_next方法的最糟糕原因。 Python的设计使得不可能使用filter来检查数组是否包含与给定谓词匹配的元素。 Python社区的傲慢和短视令人震惊。

很好的答案,我将其复制为说明从Java代码中获取的某些设计模式

我使用Python3,这段代码给了我TypeError: iter() returned non-iterator

@JonathanCast不确定我是否遵循。在Python中,通常使用map和any而不是filter,但是可以使用SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINEL或忘记SENTINEL而只使用try: except并捕获StopIteration。

除了提到StopIteration之外,Python的" for"循环还可以满足您的要求:

>>> it = iter("hello")

>>> for i in it:

...     print i

...

h

e

l

l

o

从任何迭代器对象尝试__length_hint __()方法:

iter(...).__length_hint__() > 0

我一直想知道为什么python拥有所有这些__ xxx __方法?他们看起来很丑。

正当问题!通常,它是内置函数公开的方法的语法(例如len,实际上是在调用len)。对于length_hint不存在这样的内置函数,但实际上它是一个挂起的建议(PEP424)。

@mP。这些功能在那里,因为有时需要它们。它们故意是丑陋的,因为它们被认为是不得已的方法:如果使用它们,您将知道自己做的是非Python的并且有潜在危险的操作(该操作可能随时停止工作)。

像__init__和__main__一样?恕我直言,无论您试图为其辩护,都有些混乱。

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"", line 1, in

StopIteration

StopIteration文档:http://docs.python.org/library/exceptions.html#exceptions.StopIteration

关于python中的迭代器和生成器的一些文章:http://www.ibm.com/developerworks/library/l-pycon.html

您可以使用itertools.tee tee迭代器,并在teed迭代器上检查StopIteration。

否。最相似的概念很可能是StopIteration异常。

哪些Python将异常用于控制流?听起来不错。

正确:应该使用异常来处理错误,而不是定义正常的控制流程。

我相信python只是具有next(),根据文档,它抛出一个异常是没有更多的元素。

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

以下是促使我进行搜索的用例:

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)

对我来说更干净显然,您可以通过定义实用程序类来解决问题,但是随后发生的事情是,您有二十多种不同的,几乎等同的解决方法,每个方法都有其怪癖,并且,如果您想重用使用不同解决方法的代码,则必须在您的单个应用程序中具有多个几乎相等的值,或者四处浏览并重写代码以使用相同的方法。"一次做就做好"的格言非常失败。

此外,迭代器本身需要进行内部" hasnext"检查,以查看是否需要引发异常。然后隐藏此内部检查,以便需要通过尝试获取项目,捕获异常并在抛出异常时运行处理程序来对其进行测试。这是不必要的隐藏IMO。

对于此用例,可以使用itertools.cycle

建议的方法是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()

解决此类问题的好方法是检查dir(object / method / iterator / type / class / ...)中的内容

您会看到dir(iterator)返回__length_hint__

iterator.__length_hint__()为正,直到迭代结束。

而已。

不能保证__length_hint__是准确的:python.org/dev/peps/pep-0424。

我解决问题的方法是保持到目前为止迭代对象的数量。我想使用对实例方法的调用来遍历一个集合。由于我知道集合的长度以及到目前为止已计算的项目数,因此有效地使用了hasNext方法。

我的代码的简单版本:

class Iterator:

# s is a string, say

def __init__(self, s):

self.s = set(list(s))

self.done = False

self.iter = iter(s)

self.charCount = 0

def next(self):

if self.done:

return None

self.char = next(self.iter)

self.charCount += 1

self.done = (self.charCount < len(self.s))

return self.char

def hasMore(self):

return not self.done

当然,示例是一个玩具,但是您知道了。在无法获取迭代器长度的情况下(例如生成器等),这将不起作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值