如何定义具有可选参数的函数?

我有一个Python函数,它有几个参数。在某些情况下,可以省略其中一些参数。

def some_function (self, a, b, c, d = None, e = None, f = None, g = None, h = None):
#code

参数dh是字符串,每个字符串都有不同的含义。重要的是,我可以选择在任何组合中传递哪些可选参数。例如,(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]
831684 次浏览

尝试像这样调用它:obj.some_function( '1', 2, '3', g="foo", h="bar" )。在必需的位置参数之后,可以通过名称指定特定的可选参数。

只要使用*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之后的键值参数

很简单,只要这么做

def foo(a = None):
print(a)

而不是None,你可以输入任何应该在适当的位置,如果没有参数,例如,如果你不像这样写参数的值foo(),那么它将打印None,因为没有给出参数,如果你给它一个像foo("hello world")这样的参数,那么它将打印hello world…哦,好吧,我忘了告诉你们这些类型的参数,即可选参数,这意味着,让我们采用前面的函数并添加另一个参数

def foo(a = None, b):
print(a)

现在如果你要执行你的python文件它会引发一个异常说Non-default arguments follow 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

检查:

from typing import Optional


def foo(a: str, b: Optional[str] = None) -> str or None:
pass

先选必填参数,后选参数。可选参数总是带有=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")

为了更好地理解传递参数时可能发生的情况,参考各种选项非常有帮助:位置或关键字(argarg="default_value"),仅位置(在参数列表中/,之前),仅关键字(在参数列表中*,之后),变量位置(通常是*args)或变量关键字(通常是**kwargs)。请参阅Python文档以获得优秀的总结;这个问题的其他各种答案利用了这些变化中的大多数。

因为在你的例子中总是有参数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将允许union (x|y)(或Optional[…])功能,这可能会为其他方法打开一些大门,但我使用的是Anaconda spyder,所以我想我必须等待一个新的版本才能使用python 3.10。