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

问题描述 投票:0回答:8

我有一个带有多个参数的 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]
python function arguments optional-parameters
8个回答
446
投票

只需使用

*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

之后键值化的参数的字典

316
投票

尝试这样称呼它:

obj.some_function( '1', 2, '3', g="foo", h="bar" )
。在必需的位置参数之后,您可以按名称指定特定的可选参数。


86
投票

这很容易

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

“无”可以替换为任何其他默认值。

例如,如果没有给函数提供参数

foo()
那么你认为它会打印什么?答案是“没有”。为什么?因为没有给出参数并且默认值为“None”

但是,如果你给它一个参数,例如

foo("hello world")
,那么......鼓声滚动......它会打印“hello world。”

还有一件事你应该记住,我显然忘记告诉了。这些“可选参数”需要位于所有其他参数的后面。这意味着,让我们在前面的函数中添加另一个参数

b

#def foo(a = None, b): 
#    print("Value of a is", a, " and value of b is", b)

def foo(a, b=None): 
    print("Value of a is", a, " and value of b is", b)

第一个函数(带注释的函数)将生成错误,因为可选参数“b”位于必需参数“a”之后。但第二个定义肯定有效。

因此,您必须将可选参数放在必需参数之后。


25
投票

先是必填参数,后是可选参数。可选参数始终带有

=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")

14
投票

检查这个:

from typing import Optional

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

1
投票

为了更好地了解传递参数时可能发生的情况,参考各种选项确实很有帮助:位置或关键字(

arg
arg="default_value"
)、仅位置(参数列表中的
/,
之前) 、仅关键字(参数列表中的
*,
之后)、var-位置(通常为
*args
)或 var-关键字(通常为
**kwargs
)。请参阅 Python 文档以获得精彩的总结;该问题的其他各种答案都利用了大多数这些变体。

由于您的示例中始终有参数 a、b、c 并且您似乎以位置方式调用它们,因此您可以通过添加

/,
,

使其更加明确
def some_function (self, a, b, c, /, d = None, e = None, f = None, g = None, h = None):
    #code

1
投票

使 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) (或可选 [...])功能,这可能为替代方法打开一些大门,但我正在使用 Anaconda spider,所以我想我必须等待新版本才能使用 python 3.10。


0
投票

Python 函数可以接受一些参数,以此为例,

def add(x,y):
    return x+ y

# calling this will require only x and y
add(2,3) # 5

如果我们想添加尽可能多的参数,我们只需使用

*args
,它应该是比您之前定义的正式参数数量更多的参数列表(
x
y
)。使用
*args
,可以将任意数量的额外参数附加到当前的形式参数。

def add(x, y, *args):
    return x + y + sum(args)
    
add(1,2,3,4,5,6) # 21
© www.soinside.com 2019 - 2024. All rights reserved.