可选参数,需要它们的某些组合

时间:2014-06-27 17:40:59

标签: python optional-parameters

我有一般性问题以及具体用例。

可选参数很简单:def func(a, b, c=None): ...然后可以在正文中使用c,只需先写if c:,或沿着这些行写一些东西。但是,当需要某些参数组合时呢?一般情况是考虑存在或不存在确切参数的任意情况。对于函数def func(a, b, c=None, d=None, e=None, f=None): ...,这将包括愚蠢的事情,例如:提供c和d但不提供e和f,或仅提供e,或提供c,d,e和f中的至少3个。但我的用例并不需要这样的普遍性。

对于def func(a, b, c=None, d=None): ...,我想要提供c和d中的一个。

我想到的解决方案包括:
- 在体内,手动检查c和d中有多少不是None,如果它不是1,则返回错误,说明需要指定1 离。

def func(a, b, c=None, d=None):
    how_many_provided = len([arg for arg in [c, d] if arg]) # count the non-None optional args
    if not how_many_provided == 1:
        return "Hey, provide exactly 1 of 'c' and 'd'"
    if c:
        # stuff to do if c is provided
    elif d:
        # stuff to do if d is provided

- 将函数更改为def func(a, b, e, f): ...,其中e表示c或d,f表示e表示哪一个。
恩。

def func(a, b, e, f):
    if f == 'c':
        # stuff to do if c is provided, with e as c
    if f == 'd':
        # stuff to do if d is provided, with e as d

这些可行,但这样做的标准/接受/ pythonic方式是什么?

3 个答案:

答案 0 :(得分:2)

您可以使用关键字args dict:

def func(a, b, **kwargs):
  valid_args = len(kwargs) == 1 and ('c' in kwargs or 'd' in kwargs)

  if not valid_args:
      return "Hey, provide exactly 1 of 'c' and 'd'"
  if 'c' in kwargs:
      # stuff to do if c is provided
  elif 'd' in kwargs:
      # stuff to do if d is provided

答案 1 :(得分:2)

我想说在你的简单案例中,用户最简单的方法是重构单独的函数。每个功能完成所描述的不同工作,然后是常见的工作,例如为你的最后一个案例

def funcC(a, b, c):
        # stuff to do if c is provided, with e as c
    common_func(a,b,c, None)

def funcD(a, b, d):
    # stuff to do if d is provided, with e as d
    common_func(a,b,None, d)

然后,用户知道哪些参数很重要,并且只能使用有效的可能组合,用户不必猜测或有机会错误地调用它们。您提供的功能可以提供调用者不提供的参数所需的任何内容。

通过谷歌搜索"标志参数"可以找到更长的解释。例如Martin Fowler Stack Overflow这些往往会提到布尔参数,但这实际上是一个不同的代码路径,取决于没有其他影响的参数。

要寻找的另一个词是"控制耦合"

答案 2 :(得分:1)

这是另一个,它将允许指定参数,并区分未给出的c=Nonec,同时仍明确提供参数名称:

undefined = object()

def func(a, b, c=undefined, d=undefined):
    if (c is undefined) ^ (d is undefined):
        raise TypeError("Hey, provide exactly 1 of 'c' and 'd'")

    ...

在Python 3上,仅关键字参数使其更加出色,确保调用者明确指定cd

def func(a, b, *, c=undefined, d=undefined):
    if (c is undefined) ^ (d is undefined):
        raise TypeError("Hey, provide exactly 1 of 'c' and 'd'")