我一直在问到功能添加到以下功能:如何分割与标志控制的多个行为的功能
def maybe_do_thing(x, y, z, really_do_thing):
if really_do_thing:
return f(x, y, z) # returns a list
return [] # an empty list if we did nothing
具体来说,它应该也能够调用,通过附加的控制旗。显而易见的实现是:
def maybe_do_things(x, y, z, do_f, do_g):
results = []
if do_f:
results.extend(f(x, y, z))
if do_g:
results.extend(g(x, y)) # g needs slightly different params
return results
为了清楚起见,的f和g的任意子集可以被称为:两者,既不,或者只是一个,根据两个单独的标志。 f和g在概念上是相关的,所以按照这种方式将它们组合在一起是很有意义的,但对我来说感觉相当不满意:真正的maybe_do_things
只是多个通过多个标志伪装成一个函数的函数。
我很确定这是一个反模式,但我不知道它叫什么或正确的模式来解决它。我觉得我应该能够以一种方便的方式将它分成多个自给自足的函数,就像调用复合函数一样方便,或者以某种方式清理复合函数的API,使它不仅仅是一个大块。
就在每个调用点内联maybe_do_things
不是很好:这可能是很好的,如果主叫方提前知道其中的F和G将被执行的时间,但是这两个都是在运行时确定。因此,每个调用者都需要完整的当前函数体,以及表示现在重复的x/y/z变量的局部定义。
我不认为将来会有更多的功能被添加到这个功能中,所以至少我不必担心参数列表爆炸。也许我的“明显”实现实际上是最好的折衷?
如果调用者有足够的信息来知道是否传递'do_f'或'do_g',他们有足够的信息来只是自己打电话给对方。在不知道更多关于这些标志以及函数被调用的地方/方式的情况下分析这个有点困难。但是有一种可能性不是将'really_do_thing'想象为是否调用'f',将该参数称为'context'等的“标志”。然后每个呼叫站点传递一个包含所有必要信息的“上下文”来决定实际执行的操作。更好的做法可能是将背景变成一个具有f,g等等作为方法的对象。 – BrenBarn
是的,他们有足够的信息可以自己调用正确的功能。但是,将'maybe_do_things'函数传递给'maybe_do_things'函数要比将整个'if_i_do_f()函数传递给if_do_things(...,should_i_do_f())要容易得多,如果should_i_do_f():f(x,y,z )',如果'f'是一件复杂的事情。 – amalloy