Python中的其他空对象评估为False - 我如何才能获得迭代器/生成器呢?
Python中的其他空对象评估为False - 我如何才能获得迭代器/生成器呢?
Guido不希望生成器和迭代器以这种方式运行。
默认情况下,对象为true。只有当它们定义返回零的__len__或返回的__nonzero__时,它们才可以是假的 假 (后者在Py3.x中称为__bool__)。
您可以将其中一种方法添加到自定义迭代器中,但它与Guido的意图不匹配。他拒绝将__len__添加到即将到来的长度已知的迭代器中。这就是我们得到__length_hint__的方式。
因此,判断迭代器是否为空的唯一方法是调用 下一个() 在它上面看看它是否会升起 的StopIteration。
在ASPN上,我相信有一些配方使用这种技术进行前瞻性包装。如果获取了一个值,则会将其保存为即将进行的next()调用。
Guido不希望生成器和迭代器以这种方式运行。
默认情况下,对象为true。只有当它们定义返回零的__len__或返回的__nonzero__时,它们才可以是假的 假 (后者在Py3.x中称为__bool__)。
您可以将其中一种方法添加到自定义迭代器中,但它与Guido的意图不匹配。他拒绝将__len__添加到即将到来的长度已知的迭代器中。这就是我们得到__length_hint__的方式。
因此,判断迭代器是否为空的唯一方法是调用 下一个() 在它上面看看它是否会升起 的StopIteration。
在ASPN上,我相信有一些配方使用这种技术进行前瞻性包装。如果获取了一个值,则会将其保存为即将进行的next()调用。
默认情况下,Python中的所有对象都评估为 True
。为了支持 False
评估对象的类必须有一个 __len__
方法 (0
- > False
),或者a __nonzero__
方法 (False
- > False
)。注意: __nonzero__
==> __bool__
在Python 3.x.
因为迭代器协议有意保持简单,并且因为有许多类型的迭代器/生成器在尝试生成它们之前无法知道是否有更多值要生成, True
/False
评估不是迭代器协议的一部分。
如果你真的想要这种行为,你必须自己提供。一种方法是将生成器/迭代器包装在提供缺少功能的类中。
请注意,此代码仅评估为 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
如果你还想要前瞻(或偷看)行为,这个代码将完成这个诀窍(它评估为 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
请记住,当底层迭代器/生成器的时间与其生成的值相关时,查看行为是不合适的。
还要记住,第三方代码以及可能的stdlib可能依赖于始终进行求值的迭代器/生成器 True
。如果你想偷看没有布尔,删除 __nonzero__
和 __bool__
方法。
“空事物”自动不是迭代器。容器可以是空的,也可以不是,并且可以在容器上获取迭代器,但这些迭代器在耗尽时不会出现错误。
迭代器不会变得虚假的一个很好的例子是 sys.stdin
。制作的问题 sys.stdin
当它到达输入的末尾时,如果没有尝试消耗它的输入,就无法真正知道你是否已经到达这样一个流的末尾。想要迭代器是假的主要原因是'偷看'看看下一个项是否有效;但对于 sys.stdin
,这显然不实用。
这是另一个例子
(x for x in xrange(1000) if random.randrange(0, 2))
没有办法知道这个生成器是否会返回任何更多的数字而不做一堆工作,你实际上必须找出下一个值是什么。
解决方案是从迭代器中获取下一个值。如果它是空的,你的循环将退出,或者你会得到一个 StopIteration
例如,如果你不在循环中。