我有一个过滤列表的生成器功能:
def gen_func(numbers):
for number in numbers:
if "?" in number:
yield number
for item in gen_func(["trunk", "tr?ee", "+lea?f"]):
print(item)
输出:
tr?ee
lea?f
我尝试编写一个迭代器,期望获得相同的输出,但是我得到的None作为第一项返回:
class GenClass:
def __init__(self, numbers):
self.current = 0
self.numbers = numbers
def __iter__(self):
return self
def __next__(self):
next_value = self.current
if next_value >= len(self.numbers):
raise StopIteration
output = self.numbers[self.current]
self.current += 1
if "?" in output:
return output
genclass = GenClass(["trunk", "tr?ee", "+lea?f"])
for num in genclass:
print(num)
输出:
None
tr?ee
lea?f
如何仅获取tr?ee
和lea?f
而不是上面的内容?
另外,这个迭代器有意义吗?还是我在这里滥用了迭代器?
答案 0 :(得分:1)
您需要将__next__
的代码更改为:
next_value = self.current
if next_value >= len(self.numbers):
raise StopIteration
output = self.numbers[self.current]
while "?" not in output:
self.current += 1
output = self.numbers[self.current]
self.current += 1
return output
这将返回:
tr?ee
+lea?f
本质上,您遍历数字,并且仅在数字包含?
时返回。
答案 1 :(得分:1)
您可以使用 yield 代替 return 并仅使用__iter__。
class GenClass:
def __init__(self, numbers):
self.numbers = numbers
def __iter__(self):
for value in self.numbers:
if '?' in value:
yield value
genclass = GenClass(["trunk", "tr?ee", "+lea?f"])
for num in genclass:
print(num)
Out:
tr?ee
+lea?f
我上面的解决方案不是 iterator ,而是 iterable ,谢谢juanpa.arrivillaga。我认为最好将 iterable 和 iterator 分开,在这种情况下,您可以分别实现GenClass和 iterator 。因此,如果您要遍历GenClass实例一次,则可以重复它而无需重置计数器(Daniel Mesejo解决方案中的GenClassIterator)。
class GenClass:
def __init__(self, numbers):
self.numbers = numbers
def __iter__(self):
return GenClassIterator(self.numbers)
class GenClassIterator:
def __init__(self, numbers):
self.numbers = numbers
self.current = 0
def __next__(self):
next_value = self.current
if next_value >= len(self.numbers):
raise StopIteration
output = self.numbers[self.current]
while "?" not in output:
self.current += 1
output = self.numbers[self.current]
self.current += 1
return output
def __iter__(self):
return self
答案 2 :(得分:0)
从numbers
弹出项目,直到符合条件的项目,然后将其退回。
import collections
class GenClass:
def __init__(self, numbers):
self.numbers = collections.deque(numbers)
def __iter__(self):
return self
def __next__(self):
while True:
try:
next_value = self.numbers.popleft()
except IndexError as e:
raise StopIteration
if "?" in next_value:
return next_value
答案 3 :(得分:0)
您可以调用next(self)返回所需的值而无需返回None
class GenClass:
def __init__(self, numbers):
self.current = 0
self.numbers = numbers
def __iter__(self):
return self
def __next__(self):
next_value = self.current
if next_value >= len(self.numbers):
raise StopIteration
output = self.numbers[self.current]
self.current += 1
if "?" in output:
return output
else:
return next(self) # Skip value
genclass = GenClass(["trunk", "tr?ee", "+lea?f"])
for num in genclass:
print(num)
这是更新的版本,在迭代过程中不会存储所有值
class GenClass:
def __init__(self, numbers):
self.numbers = iter(numbers)
def __iter__(self):
return self
def __next__(self):
output = next(self.numbers)
if "?" in output:
return output
else:
return next(self)