如果存在另一个参数,则需要参数

时间:2020-03-03 15:47:13

标签: python python-3.x signature

以下是我想做的一个例子。

def f(a, b, c):
    if a == 'method1':
        c = 0
    return b + c

在此功能中,如果满足条件c,则不需要参数a='method1'。 不过,我仍然可以使用f(a='method1', b=1, c=2)调用该函数,其作用与f(a='method1', b=1, c=0)相同。

对此的一种解决方案是将参数c默认设置为0

def f(a, b, c=0):
    if a == 'method1':
        c = 0
    return b + c

现在我可以打电话给f(a='method1',b=1),这正是我想要的。问题是,我仍然可以在调用c中更改参数f(a='method1',b=1,c=1),但我不希望用户这样做。

我可以在函数签名中而不在正文中强制执行此条件吗(即,我不想在正文中使用if)。或者,如果还有更好的解决方案,请告知。

类似

def f(a, b, c = 0 if a == 'method1', else c is required):
    return b + c

谢谢。

2 个答案:

答案 0 :(得分:1)

嗯...这似乎似乎可以用functools.singledispatchtyping.Literal来完成,但是我不能让它们至少在python 3.7中一起工作(使用Literal来自typing_extensions模块)。我认为一般来说,singledispatch可能是唯一可以真正满足您要求的工具,因为不同的注册函数可以具有完全不同的签名。但是,为此,我们的方法需要为不同的类。

from functools import singledispatch

class Method1():
    pass

class OtherMethods():
    pass

@singledispatch
def f(method, b, c):
    return b + c

@f.register(Method1)
def _(method, b):
    return b

f(Method1(), 12)  # returns 12
f(Method1(), 12, 7) # raises an error
f(OtherMethods(), 12) # raises an error
f(OtherMethods(), 12, 7) # returns 19

现在,这并不是您真正要求的,而是在签名中强制使用了参数。

如果某个人更了解singledispatchLiteral的实现,也许他们可以解释两者之间的相互作用。

一件更容易做的事情就是简单地将c定义为默认值为某个无效值。

def f(a, b, c=None):
    if a == 'method1':
        c = 0
    return b + c

这解决了以下问题:如果用户忘记为c以外的方法设置method1,他们将收到一条(可能是错误的)错误消息。但是,这并不能解决以下事实:如果在使用c时设置method1,则该值将被静默忽略,并可能引起混乱。

答案 1 :(得分:1)

abc都是在运行时动态分配的。您无法在签名中弥补这一点。需要在运行时进行检测,您也可以像其他任何地方一样在if中进行检测。不过,您可以专门研究函数名称级别,而python将负责检测参数数量。

def f(b,c):
    return b + c

def f_method1(b):
    return f(b, 0)

def f_method2(half_a_c):
    return f(0, half_a_c*2)