【问题标题】: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
)

【问题讨论】:

    标签: python function shorthand


    【解决方案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 来检查函数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-05
          • 2022-06-27
          相关资源
          最近更新 更多