如果存在另一个参数,则需要参数
Require parameter if another argument is present
以下是我想做的一个例子。
def f(a, b, c):
if a == 'method1':
c = 0
return b + c
在这个函数中,如果满足条件a='method1'
,则不需要参数c
。
不过,我可以用 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)
,这正是我想要的。问题是,我仍然可以在调用 f(a='method1',b=1,c=1)
中更改参数 c
,我不希望用户能够这样做。
我能否在函数签名中强制执行此条件,而不是在主体中(即我不想在主体中使用 if
)。或者如果有其他更好的解决方案,请告知。
类似
def f(a, b, c = 0 if a == 'method1', else c is required):
return b + c
提前致谢。
嗯...这几乎看起来像是你应该能够用 functools.singledispatch
和 typing.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
现在这不是您所要求的,但参数在签名中是强制执行的。
如果对 singledispatch
和 Literal
的实现有更多了解的人过来,也许他们可以解释两者之间的相互作用。
一个更简单的方法是简单地定义 c
以默认为某个无效值。
def f(a, b, c=None):
if a == 'method1':
c = 0
return b + c
这解决了如果用户忘记为 method1
之外的方法设置 c
的问题,他们将收到一条(可能是神秘的)错误消息。但是,如果他们在使用 method1
时设置 c
,则该值将被默默忽略并可能导致混淆,这并没有解决这个问题。
a
、b
和 c
都是在运行时动态分配的。您无法在签名中弥补这一点。它需要在运行时检测到,您也可以像在其他任何地方一样在 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)
以下是我想做的一个例子。
def f(a, b, c):
if a == 'method1':
c = 0
return b + c
在这个函数中,如果满足条件a='method1'
,则不需要参数c
。
不过,我可以用 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)
,这正是我想要的。问题是,我仍然可以在调用 f(a='method1',b=1,c=1)
中更改参数 c
,我不希望用户能够这样做。
我能否在函数签名中强制执行此条件,而不是在主体中(即我不想在主体中使用 if
)。或者如果有其他更好的解决方案,请告知。
类似
def f(a, b, c = 0 if a == 'method1', else c is required):
return b + c
提前致谢。
嗯...这几乎看起来像是你应该能够用 functools.singledispatch
和 typing.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
现在这不是您所要求的,但参数在签名中是强制执行的。
如果对 singledispatch
和 Literal
的实现有更多了解的人过来,也许他们可以解释两者之间的相互作用。
一个更简单的方法是简单地定义 c
以默认为某个无效值。
def f(a, b, c=None):
if a == 'method1':
c = 0
return b + c
这解决了如果用户忘记为 method1
之外的方法设置 c
的问题,他们将收到一条(可能是神秘的)错误消息。但是,如果他们在使用 method1
时设置 c
,则该值将被默默忽略并可能导致混淆,这并没有解决这个问题。
a
、b
和 c
都是在运行时动态分配的。您无法在签名中弥补这一点。它需要在运行时检测到,您也可以像在其他任何地方一样在 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)