与检查空条件巨蟒发电机(python generator with check for empty

2019-07-30 09:50发布

蟒蛇发电机是好的替代品在大多数情况下列表期望,我想检查空状态,这是不可能用普通的发电机。 我想编写一个包装这将允许检查空的条件,但仍然是懒惰,并给出发电机的利益。

class mygen:
  def __init__(self,iterable):
    self.iterable = (x for x in iterable)
    self.peeked = False
    self.peek = None
  def __iter__(self):
    if self.peeked:
      yield self.peek
      self.peeked = False
    for val in self.iterable:
      if self.peeked:
        yield self.peek
        self.peeked = False
      yield val
    if self.peeked:
      yield self.peek
      self.peeked = False
  def __nonzero__(self):
    if self.peeked:
      return True
    try:
      self.peek = self.iterable.next()
      self.peeked = True
      return True
    except:
      return False
  1. 我认为它正确的行为就像一个普通的发电机。 有我缺少任何一个角落的情况下?
  2. 这看起来并不优雅。 有没有做同样的更好更Python的方式?

用法示例:

def get_odd(l):
    return mygen(x for x in l if x%2)

def print_odd(odd_nums):
  if odd_nums:
      print "odd numbers found",list(odd_nums)
  else:
      print "No odd numbers found"

print_odd(get_odd([2,4,6,8]))
print_odd(get_odd([2,4,6,8,7]))

Answer 1:

我通常不会实现这种发电机。 有一个惯用的方式如何测试一个迭代器it是筋疲力尽:

try:
    next_item = next(it)
except StopIteration:
    # exhausted, handle this case

代一些具体项目的LBYL成语这个成语EAFP似乎混乱,不利于在所有。

这就是说,这里是我将如何实现这一点,如果我真的想:

class MyIterator(object):
    def __init__(self, iterable):
        self._iterable = iter(iterable)
        self._exhausted = False
        self._cache_next_item()
    def _cache_next_item(self):
        try:
            self._next_item = next(self._iterable)
        except StopIteration:
            self._exhausted = True
    def __iter__(self):
        return self
    def next(self):
        if self._exhausted:
            raise StopIteration
        next_item = self._next_item
        self._cache_next_item()
        return next_item
    def __nonzero__(self):
        return not self._exhausted


Answer 2:

使用itertools.tee实现非零测试,并简单地缓存它创建:

from itertools import tee

class NonZeroIterable(object):
    def __init__(self, iterable):
        self.__iterable, test = tee(iter(iterable))
        try:
            test.next()
            self.__nonzero = True
        except StopIteration:
            self.__nonzero = False                 

    def __nonzero__(self):
        return self.__nonzero

    def __iter__(self):
        return self.__iterable

小演示:

>>> nz = NonZeroIterable('foobar')
>>> if nz: print list(nz)
... 
['f', 'o', 'o', 'b', 'a', 'r']
>>> nz2 = NonZeroIterable([])
>>> if not nz2: print 'empty'
... 
empty

这个NonZeroIterable的版本缓存的标志; 因此,它只是告诉你,如果迭代器处于起步非空。 如果您需要能够在其他点来测试迭代在它的生命周期,用斯文的版本代替; 那里的__nonzero__ 每次迭代后的标志会告诉你,如果有更多的项目来还。

在你的例子旁注

示例代码的方式过于简单,并为您的用例,不是一个很好的论据; 首先测试用于非emptyness(超过输入列表中潜在地通过迭代来SEACH其中用于奇数),但无论如何,然后排出整个迭代器。 下面的代码会同样有效,也不会要求你去创造办法,打破蟒蛇成语:

def print_odd(odd_nums):
    odd_nums = list(odd_nums)
    if odd_nums:
        print "odd numbers found", odd_nums
    else:
        print "No odd numbers found"


文章来源: python generator with check for empty condition