[英]Return generator VS iterate with while until None
从下面的两个选项中,什么是更有吸引力的(可读代码,更多pythonic,效率等),用于遍历可迭代,并且如果将来我想添加更多逻辑(例如,对每个返回值添加1)?
一个选项返回生成器,另一个返回下一项,所有迭代完成后返回None
。
有没有更好的方法? 如果是,为什么? 是否存在某些方法没有的局限性?
class Option1():
def __init__(self):
self.current = 0
def get_next_batch(self, my_list):
if self.current == len(my_list):
self.current = 0
return None
self.current += 1
return [my_list[self.current-1]]
class Option2():
def __init__(self):
self.current = 0
def get_next_batch(self, my_list):
while self.current < len(my_list):
yield [my_list[self.current]]
self.current += 1
self.current = 0
raise StopIteration()
用法:
o1 = Option1()
o2 = Option2()
arr = [1,2,3,4,5]
a = o1.get_next_batch(arr)
while a is not None:
print a
a = o1.get_next_batch(arr)
for item in o2.get_next_batch(arr):
print item
两种情况下的输出:
[1]
[2]
[3]
[4]
[5]
您几乎可以肯定要选择第二个。 更少的线路,更少的出错机会。
但是,看到您不在迭代器外部使用current
,我只会将整个过程优化为:
def get_next_batch(my_list):
for item in my_list:
yield [item]
arr = [1,2,3,4,5]
for item in get_next_batch(arr):
print item
旁点。 始终使您的类从python 2.7中的object
继承,并且不要提高StopIteration
来终止python中的生成器-不推荐使用的行为可能导致bug。 使用return
代替。 例如。
def get_next_batch(my_list):
for item in my_list:
if item > 3:
return
yield [item]
batched = list(get_next_batch([1,2,3,4,5]))
expected = [[1], [2], [3]]
print batched == expected
您可以整理Option1
以使其易于在for循环中使用。 为此,您可以使用迭代器协议。 那是一个__iter__
方法,它返回self
和一个next
方法来获取下一个项目。 例如。
class UsingNext(object):
def __init__(self, mylist):
self.current = 0
self.mylist = mylist
def __iter__(self):
return self
def next(self): # __next__ in python 3
if self.current >= len(self.mylist):
raise StopIteration
if self.current == 2:
self.current += 1
return "special"
item = self.mylist[self.current]
self.current += 1
return [item]
class UsingYield(object):
def __init__(self, mylist):
self.mylist = mylist
def __iter__(self):
for current, item in enumerate(self.mylist):
if current == 2:
yield "special"
continue
yield [item]
arr = range(1, 6)
# both print
# [1]
# [2]
# special
# [4]
# [5]
for item in UsingNext(arr):
print item
for item in UsingYield(arr):
print item
在我看来,生成器版本更干净,更易于理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.