【问题标题】:How to check in python that at least one of the default parameters of the function specified如何在python中检查指定函数的至少一个默认参数
【发布时间】:2021-02-23 10:04:00
【问题描述】:

在python中检查函数的至少一个默认参数是否被指定的最佳实践是什么?

假设我们有一些函数:

def some_function(arg_a=None, arg_b=None, arg_c=False)

带有一些默认参数。就我而言,我需要检查是否指定了 arg_a 或 arg_b。所以我想到了实现这样的东西:

def some_function(arg_a=None, arg_b=None, arg_c=False):
    ...
    if arg_a is not None:
        ...
    elif arg_b is not None:
        ...
    else:
        raise ValueError('Expected either arg_a or arg_b args')
    ...
    ...

那么,有什么更 Pythonic 的方式来实现这种功能呢?

【问题讨论】:

  • 参数必须这样设置吗?为了强制用户使用其中一个或另一个,我可能会定义函数some_function(arg, using_a) - 这样就没有不指定一个或另一个的选项
  • 同意总的来说这是一个糟糕的模式。您不应该尝试以这种方式重载函数。如果您确信这是最适合您的用例的,这里有很多很好的答案。

标签: python function parameter-passing


【解决方案1】:

取决于您期望的 arg_a 和 arg_b 的值,但这通常就足够了。

if not arg_a and not arg_b:
    raise ValueError(...)

假设arg_a 和arg_b 不都是布尔值,并且不能有零、空字符串/列表/元组等作为参数。

根据你的需要,如果你需要区分None和'falsies'例如False、0、""、[]、{}、()等,你可以更精确:

if arg_a is None and arg_b is None:
    raise ValueError(...)

【讨论】:

  • 如果 arg_a 或 arg_b 是空字符串、空列表或另一个 'falsey' 值,这将失败,而不仅仅是没有指定它们。
  • arg_a == arg_b == None: 或 arg_a is arg_b is None:
【解决方案2】:

您可以使用all 检查它们是否都等于None 并提高ValueError:

if all(v is None for v in {arg_a, arg_b}):
    raise ValueError('Expected either arg_a or arg_b args')

这消除了那些if-elif 子句并将所有检查分组在同一个地方:

f(arg_a=0) # ok    
f(arg_b=0) # ok
f()        # Value Error  

或者,any():

if not any(v is not None for v in {arg_a, arg_b}):
    raise ValueError('Expected either arg_a or arg_b args')

但这肯定更加模糊。

最终,这真的取决于pythonic的解释究竟是什么。

【讨论】:

  • 好的,但是在你的代码之后我必须再放一次 if-elif,因为我需要初始化一些依赖于 arg_a 或 arg_b 的数据
【解决方案3】:

如果你有很多这样的命名参数,默认值不匹配,你可以考虑使用kwargs:

def some_function(**kwargs):
    reqd = ['arg_a', 'arg_b']
    if not all(i in kwargs for i in reqd):
        raise ValueError('Expected either {} args'.format(' or '.join(reqd)))

    arg_a = kwargs.get('args_a')
    arg_b = kwargs.get('args_b')
    arg_c = kwargs.get('args_c', False)

【讨论】:

  • 当我看到你的帖子时,我做了一个类似的帖子。但是,我使用有效参数的set 并从 kwargs 中的键集中减去它以检查不正确的参数。
  • @cdarke 这很好。看起来会更干净,但要考虑从 kwargs 中创建另一个集合
  • 在 Py3 中,您可以对从 dict.keys() 返回的视图对象使用集合操作,或者在 Py2 中使用 dict.viewkeys()
【解决方案4】:

检查是否至少有一个函数的默认参数 指定

使用locals、dict.values和any函数的解决方案:

def some_function(arg_a=None, arg_b=None, arg_c=False):
    args = locals()
    if (any(args.values()) == True):
        print('Ok')
    else:
        raise ValueError('At least one default param should be passed!')

some_function(False, 1)            # Ok
some_function('text', False, None) # Ok
some_function(0, False, None)      # Error

https://docs.python.org/2/library/functions.html#any

【讨论】:

    【解决方案5】:

    既然你提出了这样的模式,arg_a、arg_b 和arg_c 可能有一些统一的含义。如果是这样,你可以...

    from enum import Enum
    
    class Group(Enum):
        A = auto()
        B = auto()
        C = auto()
    
    def some_function(val: int, t: Group):
        if t == Group.A:
            # do stuff with val
        elif t == Group.B:
            # do other stuff with val
        elif t == Group.C:
            # do other stuff with val
    
    some_function(1, Group.A)
    

    在这里,调用者必须同时指定一个值以及该值对应的内容。这对于python中缺乏适当的枚举支持有点小题大做,我不知道它是否是pythonic。然而,它会被类型检查器拾取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 2011-06-19
      • 2016-05-10
      • 2011-12-06
      • 1970-01-01
      相关资源
      最近更新 更多