我有一堆逻辑,在一个API的不同部分重复了好几次,其中几乎所有的东西都是一样的,只是有时要做一个额外的工作,而且永远不一样。
说白了,这里是发生的 "形状"。
do_some_preparation()
for item in iterable:
do_several_things_that_are_always_the_same()
maybe_do_something_specific()
# where the specific part requires:
# - context from the loop
# - context from where the whole action is started
我认为有两种可能的设计模式可以解决这个问题:回调或生成器。
def handle_the_thing(..., callback=None):
do_some_preparation()
for item in iterable:
do_several_things_that_are_always_the_same()
if callback:
callback(loop_context)
# case with no specific action
handle_the_thing(...)
# case with some specific action
def do_thing_A(): ...
handle_the_thing(..., do_thing_A)
# case with another specific action
def do_thing_B(): ...
handle_the_thing(..., do_thing_B)
def handle_the_thing(...):
do_some_preparation()
for item in iterable:
do_several_things_that_are_always_the_same()
yield loop_context
# case with no specific action
for _ in handle_the_thing(...):
pass
# case with some specific action
for var_from_loop in handle_the_thing(...):
# do your thing A
# case with another specific action
for var_from_loop in handle_the_thing(...):
# do your thing B
那么问题是,哪一个是最pythonic和可维护的correct?
甚至还有其他方法来解决这个问题吗?
请记住,所有这些东西都是相当依赖的,我不能很容易地在它自己的函数中提取每个部分.我之所以费心,是因为有一些复杂的动作,在公共部分都是相关的,我宁愿避免在几个地方维护它们。
就个人而言,我认为这两种情况都有优势,但我猜测生成器的用途更广。但也许这是一种常见的模式?
你的见解是完全正确的。生成器似乎是个好办法。
为了解决没有特殊动作的情况下看起来很奇怪的问题,我将增加一个 yield_contexts
参数为 handle_the_thing
.
def handle_the_thing(..., yield_contexts=True):
do_some_preparation()
for item in iterable:
do_several_things_that_are_always_the_same()
if yield_contexts:
yield loop_context
# case with no specific action -> CLEANER!
handle_the_thing(..., yield_contexts=False)
# case with some specific action -> IDENTICAL!
for var_from_loop in handle_the_thing(...):
# do your thing A