Chi*_*aca 6 python naming-conventions
在查询具有未知长度的分页列表的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
Run Code Online (Sandbox Code Playgroud)
之间的分裂work
,并fetch_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__
Run Code Online (Sandbox Code Playgroud)
然后我会用它
@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
Run Code Online (Sandbox Code Playgroud)
那么我创造的这件事是什么?
我认为你可以通过产生一些特别的东西来避免这种情况。
我必须构建自己的可运行示例,以展示我的意思:
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()
Run Code Online (Sandbox Code Playgroud)
输出:
x = 1
x = 2
x = 3
x = 4
x = 5
Run Code Online (Sandbox Code Playgroud)
与你构建的装饰器相比,我更喜欢这个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
Run Code Online (Sandbox Code Playgroud)
基本上你不再关心它是如何fetch_one
工作的,只关心产量是否可以。
使用示例:
@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
Run Code Online (Sandbox Code Playgroud)