По умолчанию все объекты в Python оцениваются как True
.Чтобы поддерживать оценки False
, класс объекта должен иметь либо метод __len__
(0
-> False
), либо метод __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
.Если вы хотите посмотреть без bool, удалите методы __nonzero__
и __bool__
.