我有一般性问题以及具体用例。
可选参数很简单: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方式是什么?
答案 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=None
和c
,同时仍明确提供参数名称:
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上,仅关键字参数使其更加出色,确保调用者明确指定c
或d
:
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'")