【发布时间】:2021-09-13 17:23:44
【问题描述】:
我有一个带有多个可选参数的函数,其默认值取决于非可选参数。
目前看起来是这样的:
def foo(x, y, option_1=None, option_2=None, option_3=None, option_4=None):
if option_1 is None:
option_1 = choose_option_1(x, y)
if option_2 is None:
option_2 = choose_option_2(x, y)
if option_3 is None:
option_3 = choose_option_3(x, y)
if option_4 is None:
option_4 = choose_option_4(x, y)
return _foo(x, y, option_1, option_2, option_3, option_4)
但是这种风格打破了不重复代码的规则,而是使用循环。
所以我可以选择做这样的事情:
def foo_2(x, y, option_1=None, option_2=None, option_3=None, option_4=None):
options = [option_1, option_2, option_3, option_4]
funcs = [choose_option_1, choose_option_2, choose_option_3, choose_option_4]
for i in range(len(options)):
if options[i] is None:
options[i] = funcs[i](x, y)
return _foo(x, y, *options)
但是,我认为第二个选项实际上比第一个选项可读性差。
但无论哪种情况,我认为代码看起来都不必要地充实、沉重,比最佳代码更难理解。
是否有更简洁、更易读(也许更 Python 式)的替代方案?
编辑:如果你想自己运行这段代码,这里有一些你可以用来实现 foo 的占位符函数:
def choose_option_1(x, y):
return x + y
def choose_option_2(x, y):
return x - y
def choose_option_3(x, y):
return x * y
def choose_option_4(x, y):
return x / y
def _foo(x, y, option_1, option_2, option_3, option_4):
return x + y + option_1 + option_2 + option_3 + option_4
【问题讨论】:
-
现实生活中的答案是避免这种情况。我个人尝试完全避免使用默认参数,除非默认行为对于任何调用者来说都是真正显而易见的(例如排序函数中的
key参数是标识函数)。如果您的默认值是在运行时从其他输入中计算出来的,那么它可能不会很明显,这表明界面中存在一些更深层次的问题,但根据玩具示例无法诊断出它。鉴于设计,我认为代码很好,但代码的复杂性表明设计存在问题。 -
有时,重复代码比替代代码更好。 DRY 是一个指导方针,而不是严格的规则。
标签: python python-3.x loops default-parameters