有条件地将任意数量的默认命名参数传递给函数
Posted
技术标签:
【中文标题】有条件地将任意数量的默认命名参数传递给函数【英文标题】:Conditionally passing arbitrary number of default named arguments to a function 【发布时间】:2011-06-07 22:13:19 【问题描述】:是否可以有条件地将任意数量的命名默认参数传递给 Python 函数?
例如。有一个功能:
def func(arg, arg2='', arg3='def')
现在的逻辑是我有一个条件来确定是否需要传递 arg3,我可以这样做:
if condition == True:
func('arg', arg2='arg2', arg3='some value')
else:
func('arg', arg2='arg2')
问题是,我可以写一个简写吗:
func('arg', 'arg2', 'some value' if condition == True else # nothing so default gets picked
)
【问题讨论】:
【参考方案1】:我能想到的唯一方法是
func("arg", "arg2", **("arg3": "some value" if condition == True else ))
或
func("arg", "arg2", *(("some value",) if condition == True else ()))
但请不要这样做。使用您自己提供的代码,或类似的代码:
if condition:
arg3 = "some value",
else:
arg3 = ()
func("arg", "arg2", *arg3)
【讨论】:
你对**和*有什么看法? 不反对*
和**
。我只是认为原始代码更具可读性。我想我不喜欢a if c else b
。
或者,可以使用一些条件逻辑(在函数调用之外)构造参数字典。然后可以使用**
传递它们。使用大量参数时,这仍然是可读的。【参考方案2】:
这不是有效的 Python 语法,您必须在 else
之后添加一些内容。通常做的是:
func('arg', 'arg2', 'some value' if condition else None)
函数定义也相应改变:
def func(arg, arg2='', arg3=None):
arg3 = 'def' if arg3 is None else arg3
【讨论】:
【参考方案3】:如果你的函数有很多默认参数
def lots_of_defaults(arg1 = "foo", arg2 = "bar", arg3 = "baz", arg4 = "blah"):
pass
并且您想根据程序中发生的其他事情将不同的值传递给其中一些,一种简单的方法是使用**
解压缩您根据程序构造的参数名称和值的字典逻辑。
different_than_defaults =
if foobar:
different_than_defaults["arg1"] = "baaaz"
if barblah:
different_than_defaults["arg4"] = "bleck"
lots_of_defaults(**different_than_defaults)
这样做的好处是在调用函数时不会阻塞代码,如果有很多逻辑决定了调用的内容。如果您有任何没有默认值的参数,则需要小心,在传递字典之前包含您为这些参数传递的值。
【讨论】:
【参考方案4】:你可以写一个辅助函数
def caller(func, *args, **kwargs):
return func(*args, **k:v for k,v in kwargs.items() if v != caller.DONT_PASS)
caller.DONT_PASS = object()
使用此函数调用另一个函数并使用caller.DONT_PASS
指定您不想传递的参数。
caller(func, 'arg', 'arg2', arg3 = 'some value' if condition else caller.DONT_PASS)
请注意,caller()
仅支持有条件地传递关键字参数。要支持位置参数,您可能需要使用模块 inspect
来检查函数。
【讨论】:
以上是关于有条件地将任意数量的默认命名参数传递给函数的主要内容,如果未能解决你的问题,请参考以下文章
如何有条件地将参数传递给 Flutter/Dart 中的 Widget?