Guido不希望生成器和迭代器以这种方式运行.
默认情况下对象为true.只有当它们定义返回零的__len__或返回False的 __nonzero__时(后者在Py3.x中称为__bool__),它们才可以是假的.
您可以将其中一种方法添加到自定义迭代器中,但它与Guido的意图不匹配.他拒绝将__len__添加到即将到来的长度已知的迭代器中.这就是我们得到__length_hint__的方式.
因此,判断迭代器是否为空的唯一方法是在其上调用next()并查看它是否引发了StopIteration.
在ASPN上,我相信有一些配方使用这种技术进行前瞻性包装.如果获取了一个值,它将被保存为即将进行的next()调用.
默认情况下,Python中的所有对象都评估为True
.为了支持False
评估,对象的类必须具有__len__
方法(0
- > False
)或__nonzero__
方法(False
- > False
).注意:__nonzero__
= 3.> __bool__
在Python 3.x中.
因为迭代器协议有意保持简单,并且因为有许多类型的迭代器/生成器在尝试生成它们之前无法知道是否有更多值要生成,所以True
/ False
evaluation不是迭代器协议的一部分.
如果你真的想要这种行为,你必须自己提供.一种方法是将生成器/迭代器包装在提供缺少功能的类中.
请注意,此代码仅在引发False
之后 进行求值StopIteration
.
作为奖励,此代码适用于蟒蛇2.4+
try:
next
except NameError: # doesn't show up until python 2.6
def next(iter):
return iter.next()
Empty = object()
class Boolean_Iterator(object):
"""Adds the abilities
True/False tests: True means there /may/ be items still remaining to be used
"""
def __init__(self, iterator):
self._iter = iter(iterator)
self._alive = True
def __iter__(self):
return self
def __next__(self):
try:
result = next(self._iter)
except StopIteration:
self._alive = False
raise
return result
next = __next__ # python 2.x
def __bool__(self):
return self._alive
__nonzero__ = __bool__ # python 2.x
Run Code Online (Sandbox Code Playgroud)
如果你还想要前瞻(或偷看)行为,这个代码将完成这个诀窍(它的评估结果是False
之前 StopIteration
):
try:
next
except NameError: # doesn't show up until python 2.6
def next(iter):
return iter.next()
Empty = object()
class Iterator(object):
"""Adds the abilities
True/False tests: True means there are items still remaining to be used
peek(): get the next item without removing it from the sequence
"""
def __init__(self, iterator):
self._iter = iter(iterator)
self._peek = Empty
self.peek()
def __next__(self):
peek, self._peek = self._peek, Empty
self.peek()
if peek is not Empty:
return peek
raise StopIteration
next = __next__ # python 2.x
def __bool__(self):
return self._peek is not Empty
__nonzero__ = __bool__ # python 2.x
def peek(self):
if self._peek is not Empty:
return self._peek
self._peek = next(self._iter, Empty)
return self._peek
Run Code Online (Sandbox Code Playgroud)
请记住,当底层迭代器/生成器的时间与其生成的值相关时,偷看行为是不合适的.
还要记住,第三方代码以及可能的stdlib可能依赖于始终进行求值的迭代器/生成器True
.如果你想偷看没有bool,删除__nonzero__
和__bool__
方法.
归档时间: |
|
查看次数: |
3576 次 |
最近记录: |