問題描述
Python 中的其他空對象評估為 False —— 我怎樣才能讓迭代器/生成器也這樣做?
Other empty objects in Python evaluate as False -- how can I get iterators/generators to do so as well?
推薦答案
默認(rèn)情況下,Python 中的所有對象都評估為 True
.為了支持 False
評估,對象的類必須具有 __len__
方法(0
-> False
),或 __nonzero__
方法 (False
-> False
).注意:__nonzero__
==> __bool__
在 Python 3.x 中.
By default all objects in Python evaluate as True
. In order to support False
evaluations the object's class must have either a __len__
method (0
-> False
), or a __nonzero__
method (False
-> False
). Note: __nonzero__
==> __bool__
in Python 3.x.
因為迭代器協(xié)議有意保持簡單,并且因為有許多類型的迭代器/生成器在嘗試生成它們之前無法知道是否還有更多值要生成,所以 True
/False
評估不是迭代器協(xié)議的一部分.
Because the iterator protocol is intentionally kept simple, and because there are many types of iterators/generators that aren't able to know if there are more values to produce before attempting to produce them, True
/False
evaluation is not part of the iterator protocol.
如果你真的想要這種行為,你必須自己提供.一種方法是將生成器/迭代器包裝在提供缺失功能的類中.
If you really want this behavior, you have to provide it yourself. One way is to wrap the generator/iterator in a class that provides the missing functionality.
請注意,此代碼僅在引發(fā) StopIteration
后評估為 False
.
Note that this code only evaluates to False
after StopIteration
has been raised.
作為獎勵,此代碼適用于 pythons 2.4+
As a bonus, this code works for pythons 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
如果您還想要前瞻(或窺視)行為,則此代碼可以解決問題(它的計算結(jié)果為 False
before StopIteration
被提出):
If you also want look-ahead (or peek) behavior, this code will do the trick (it evaluates to False
before StopIteration
is raised):
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
請記住,當(dāng)?shù)讓拥?生成器的時間與其產(chǎn)生的值相關(guān)時,窺視行為是不合適的.
Keep in mind that peek behaviour is not appropriate when the timing of the underlying iterator/generator is relevant to its produced values.
另外請記住,第三方代碼,可能還有標(biāo)準(zhǔn)庫,可能依賴于迭代器/生成器,總是評估為 True
.如果你想在沒有 bool 的情況下查看,請刪除 __nonzero__
和 __bool__
方法.
Also keep in mind that third-party code, and possibly the stdlib, may rely on iterators/generators always evaluating to True
. If you want peek without bool, remove the __nonzero__
and __bool__
methods.
這篇關(guān)于如何讓生成器/迭代器在用盡時評估為 False?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!