【问题标题】:How do I create a Python function with optional arguments?如何创建带有可选参数的 Python 函数?
【发布时间】:2012-03-21 08:20:05
【问题描述】:

我有一个带有多个参数的 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]

【问题讨论】:

标签: python function arguments optional-arguments


【解决方案1】:

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

【讨论】:

  • 谢谢。虽然我不能在我的代码中使用这么多的灵活性,并且它并不能解决我在列表中使用各种空洞进行调用的问题,但它是在不同项目中使用的一个很好的工具。 Russel Borogove 给了我解决问题所需的确切答案,我很高兴。
  • @Nix,我真的很喜欢你的回答。但是,您能否澄清一下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
  • 如果您担心时间复杂度。这将是一个问题
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    这样做很简单

    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(these threee dots are ellipsis which are somewhat like pass
    
    def foo(b=None, a): ... #and this isn't
    

    【讨论】:

      【解决方案4】:

      以更恰当的方式:

      import Optional from typing
      
      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

      【讨论】:

      • 但是这些注解在运行时不用于强制甚至检查参数类型。所以这不是正确的方法,它实际上并没有做 OP 想要的。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        为了更好地了解传递参数时可能发生的情况,参考各种选项非常有帮助:位置或关键字(argarg="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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-08
          • 1970-01-01
          • 2011-06-20
          • 2021-03-28
          • 2011-12-03
          • 2019-11-07
          • 1970-01-01
          相关资源
          最近更新 更多