python空条件_检查空条件的python生成器

在大多数情况下,python生成器是列表的良好替代品,我希望在其中检查空条件,这是普通生成器无法实现的。 我正在尝试编写一个包装器,该包装器将允许检查空条件,但仍然很懒,并提供了生成器的好处。

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

我认为它的行为像普通生成器一样正确。 有拐角处的情况吗

我迷路了?

这看起来并不优雅。 有没有更好的Pythonic方式可以做到这一点?

用法示例:

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]))

(x for x in iterable)是编写iter(iterable)的缓慢而冗长的方式。

您是否要__nonzero__()返回当前是否还有剩余的项目,或者可迭代对象从一开始就是否为空?

我想剩下什么。

相关:stackoverflow.com/q/661603/281545

我通常不会实施这种

发电机。有一种惯用的方法如何测试迭代器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

我确实看到了检查是否为空的要点;如果您要循环遍历迭代器的元素,或者在没有元素时进行一些特殊的操作,这可能会非常方便。不过,对于简单的预见迭代器,+ 1。

@larsmans:我确实也看到了检查一个空的迭代器的意义,所以我将使用惯用的方法来执行此操作。 :)

我只想提到__nonzero __()在Python3中变成__bool __(),以防有人阅读

使用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缓存标志;因此,它仅告诉您迭代器在开始时是否为非空。如果需要在生命周期的其他阶段进行测试,请使用Sven版本。在每次迭代后,__nonzero__标志都会告诉您是否还有更多项目需要处理。

您的示例的旁注

您的示例代码太简单了,对于您的用例来说不是一个很好的论据。您首先要测试非空性(可能会遍历输入列表以获取奇数),然后无论如何都要耗尽整个迭代器。以下代码将同样高效,并且不需要您发明打破python惯用语的方法:

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"

这与原始代码有所不同。在原始代码中,__nonzero__()返回迭代器是否已耗尽。

@SvenMarnach:但是他从来没有那样使用它。更新后的版本会在耗尽时进行切换。

根据我的理解,OP的想法是__nonzero__应该测试基础生成器是否至少产生了一次,无论其当前是否耗尽。因此,第一个片段是正确的。

@SvenMarnach:瞧,这就是为什么整个事情首先都不是个好主意的原因。此外,无论如何,我们都将__nonzero__的概念延伸到断点。

@ thg435:好吧,这不是原始代码所做的事情,并且帖子还不是很清楚。让我们等待OP所说的。

我对第二个版本的最后评论(现已删除)很难理解,所以我再试一次。我认为第二个版本是荒谬的,因为__nonzero__()方法没有明确定义的语义。它既不返回iterable从一开始就是否为空,也不返回是否还有剩余项,而是在两者之间做些事情。

@SvenMarnach:不幸的是,OP的意图也是如此。无论如何都会删除该示例,在这种情况下,您的解决方案会更好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值