如何管理Python循环中的副作用?



在我的许多项目中,我遇到了以下Python循环模式:

for idx, item in enumerate(items):
# apply and accumulate
state = f(state, item)
# display status/log something depending on state/item/iteration
side_effect(idx, state, item)

现在,如果我想抽象出副作用的处理,它就会变得复杂。例如,我想打印前 10 个项目,然后只打印点,最后打印最后一项:

for idx, item in enumerate(items):
# apply and accumulate
state = f(state, item)
# display status/log something depending on state/item/iteration
if idx < 10:
print(item)
elif idx == 10:
print('...')
if idx >= 10:
print(item)
# in general, we cannot assume how many items there are, but
# it's a bit ugly imo because item is out of scope here
# if we solve this by keeping a reference to last item, it's worse imo

假设我想使此行为成为许多循环的通用行为。为此,我在循环中使用了一个上下文管理器,该管理器在循环内部也称为来处理副作用,如下所示:

with Printer(...) as printer:
for idx, item in enumerate(items):
# apply and accumulate
state = f(state, item)
# display status/log something depending on state/item/iteration
printer.do_your_thang(item)

打印机跟踪迭代,甚至可以在循环完成__exit__时采取行动,因此此时仍然可以更新其状态

我遇到的问题是,它为使用此类上下文管理器的每个循环添加缩进,并且上下文管理器未绑定到循环。你有更好的解决这个问题的想法吗?

你可以为enumerate创建一个包装器:

def printer(gen):
for idx, item in gen:
if idx < 10:
print(item)
elif idx == 10:
print('...')
yield idx, item
if idx >= 10:
print(item)

并像这样使用:

for idx, item in printer(enumerate(items)):
# apply and accumulate
state = f(state, item)

最新更新