gpt4 book ai didi

python - 您如何称呼具有两个不同 "done"状态的迭代器?

转载 作者:太空狗 更新时间:2023-10-30 00:11:49 24 4
gpt4 key购买 nike

在查询具有未知长度的分页列表的 API 时,我发现自己实际上在做

def fetch_one(self, n):
data = json.load(urlopen(url_template % n))
if data is None:
self.finished = True
return
for row in data:
if row_is_weird(row):
self.finished = True
return
yield prepare(row)

def work(self):
n = 1
self.finished = False
while not self.finished:
consume(self.fetch_one(n))
n += 1

workfetch_one 之间的分离使得测试变得非常容易,但是通过实例变量的信号意味着我不能有多个 work 同时进行,这很糟糕。我想出了一个我认为更简洁的解决方案,但它涉及一个具有两个“完成”状态的迭代器,我不知道该怎么调用它。我确信这种模式存在于其他地方,所以我很感激指点(或为什么这是愚蠢的原因):

class Thing(object):
def __init__(self, gen):
self.gen = gen
self.finished = False

def __iter__(self):
return self

def __next__(self):
try:
v = next(self.gen)
except StopThisThing:
self.finished = True
raise StopIteration
else:
return v
next = __next__

然后我会像这样使用它

@thinged
def fetch_one(self, n):
data = json.load(urlopen(url_template % n))
if data is None:
raise StopThisThing()
for row in data:
if row_is_weird(row):
raise StopThisThing()
yield prepare(row)

def work(self):
n = 1
while True:
one = self.fetch_one(n)
consume(one)
if one.finished:
break
n += 1

那么我创造的这个东西是什么?

最佳答案

我认为您可以通过产生一些特殊的东西来避免这种情况。

我必须构建自己的可运行示例,以表明我的意思:

def fetch_one(n):
lst = [[1,2,3], [4,5,6], [7,8,9]][n]
for x in lst:
if x == 6:
yield 'StopAll'
return
yield x

def work():
n = 0
in_progress = True
while in_progress:
numbers_iterator = fetch_one(n)
for x in numbers_iterator:
if x == 'StopAll':
in_progress = False
break
print('x =', x)
n += 1

work()

输出:

x = 1
x = 2
x = 3
x = 4
x = 5

我比 self.finished 或类似您构建的装饰器更喜欢它,但我认为仍然可以找到更好的东西。 (也许这个答案可以帮助你)。

更新:一个更简单的解决方案可能是将 fetch_one 转换为一个带有自己的 finised 标志的类。

此解决方案的装饰器方法可能是:

class stopper(object):
def __init__(self, func):
self.func = func
self.finished = False

def __call__(self, *args, **kwargs):
for x in self.func(*args, **kwargs):
if x == 6:
self.finished = True
raise StopIteration
yield x
else:
self.finished = True

基本上您不再关心 fetch_one 是如何工作的,只关心 yield 是否正常。

使用示例:

@stopper
def fetch_one(n):
lst = [[1,2,3], [4,5,6], [7,8,9]][n]
#lst = [[1,2,3], [], [4,5,6], [7,8,9]][n] # uncomment to test for/else
for x in lst:
yield x

def work():
n = 0
while not fetch_one.finished:
for x in fetch_one(n):
print('x =', x)
n += 1

关于python - 您如何称呼具有两个不同 "done"状态的迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9650623/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com