我有一个 Python 函数,它需要几个参数。在某些情况下可以省略其中一些参数。
def some_function (self, a, b, c, d = None, e = None, f = None, g = None, h = None):
#code
参数 d
到 h
是具有不同含义的字符串。重要的是,我可以选择以任意组合传递哪些可选参数。例如,(a, b, C, d, e)
,或 (a, b, C, g, h)
,或 (a, b, C, d, e, f
,或所有这些(这些是我的选择)。
如果我可以重载该函数,那就太好了——但我读到 Python 不支持重载。我试图在列表中插入一些必需的 int 参数 - 并得到一个参数不匹配错误。
现在我正在发送空字符串来代替前几个缺失的参数作为占位符。我希望能够仅使用实际值来调用函数。
有没有办法做到这一点?我可以传递一个列表而不是参数列表吗?
现在使用 ctypes 的原型看起来像:
_fdll.some_function.argtypes = [c_void_p, c_char_p, c_int, c_char_p, c_char_p, c_char_p, c_char_p, c_char_p]
只需使用 *args
参数,它允许您在 a,b,c
之后传递任意数量的参数。您必须添加一些逻辑来映射 args
->c,d,e,f
但它是一种重载的“方式”。
def myfunc(a,b, *args, **kwargs):
for ar in args:
print ar
myfunc(a,b,c,d,e,f)
它将打印 c,d,e,f
的值
同样,您可以使用 kwargs
参数,然后您可以命名参数。
def myfunc(a,b, *args, **kwargs):
c = kwargs.get('c', None)
d = kwargs.get('d', None)
#etc
myfunc(a,b, c='nick', d='dog', ...)
然后 kwargs
将有一个字典,其中包含 a,b
之后的所有键值参数
尝试将其称为:obj.some_function( '1', 2, '3', g="foo", h="bar" )
。在所需的位置参数之后,您可以按名称指定特定的可选参数。
这样做很容易
def foo(a = None):
print(a)
如果没有参数,您可以键入任何应该存在的内容而不是 None ,例如,如果您不会像 foo()
这样写入参数的值,那么它将打印 None 因为没有给出参数并且如果您会给它一个像 foo("hello world")
这样的参数然后它会打印 hello world
...哦,我只是忘了告诉你们这些类型的参数,即可选参数,需要在所有其他参数之后。这意味着,让我们使用前面的函数并添加另一个参数 b
def foo(a = None, b):
print(a)
现在,如果您要执行您的 python 文件,它将引发一个异常,说 Non-default arguments follows default arguments
,
SyntaxError: non-default argument follows default argument
所以你必须把可选或非默认参数放在所需的参数之后
意思是
def foo (a, b=None): ... #This one is right
def foo(b=None, a): ... #and this isn't
必需参数在前,可选参数在后。可选参数始终带有 =None
。
简单快速的例子:
def example_function(param1, param2, param3=None, param4=None):
pass
# Doesn't work, param2 missing
example_function("hello")
# Works
example_function("hello", "bye")
# Works. Both the same
example_function("hello", "bye", "hey")
example_function("hello", "bye", param3="hey")
# Works. Both the same
example_function("hello", "bye", "hey", "foo")
example_function("hello", "bye", param3="hey", param4="foo")
以更恰当的方式:
from typing import Optional
def foo(a: str, b: Optional[str]) -> str or None:
pass
这等于:
def foo(a: str, b: str or None = None) -> str or None
pass
有关详细信息:https://docs.python.org/3/library/typing.html#typing.Optional
为了更好地了解传递参数时可能发生的情况,参考各种选项非常有帮助:位置或关键字(arg
或 arg="default_value"
),仅位置(在参数列表中的 /,
之前),仅关键字(在参数列表中的 *,
之后)、var-positional(通常为 *args
)或 var-keyword(通常为 **kwargs
)。请参阅 Python 文档以获取出色的 summary;该问题的其他各种答案都使用了这些变化中的大多数。
由于您的示例中始终包含参数 a、b、c,并且您似乎以位置方式调用它们,因此您可以通过添加 /,
使其更加明确,
def some_function (self, a, b, c, /, d = None, e = None, f = None, g = None, h = None):
#code
使 Avión 的答案适用于矢量参数输入;
def test(M,v=None):
try:
if (v==None).all() == False:
print('argument passed')
return M + v
except:
print('no argument passed')
return M
其中 M 是一些矩阵,v 是一些向量。当我尝试使用 if 语句而不使用“try/except”语句时,test(M) 和 test(M,v) 都会产生错误。
正如 cem 所提到的,升级到 python 3.10 将允许联合 (x|y) (或 Optional[...])功能,这可能会为替代方法打开一些大门,但我使用的是 Anaconda spyder 所以我想我有等待新版本使用 python 3.10。
不定期副业成功案例分享
c = kwargs.get('c', None)
的用途?每个具有可选参数的函数都需要它吗?在您的代码中,您只有 2 个可选参数。如果用户想要另一个 arg 说e
怎么办?如何更改任何未知数量的可选参数的示例代码,例如:def my_func(a, b, *args, **kwagars): obj = <do something with a & b> obj.add(c) obj.add(d) continue obj.add(for e, f, g...)
?我必须在执行obj.add(c, d, ...)
之前包含c = kwargs.get('c', None) etc
吗?