关键字参数后的位置参数以及*参数后的普通参数

3

我必须使用Python 2.7,但是我遇到了一个在Python 3中没有的问题。

def foo(*dirs, arg2, arg3=None, arg4=None, arg5=False, arg6=False):

我会这样调用函数:

foo('folder_name', arg2=100, arg3=['string', 'string2'], arg4='test6', arg5=True, arg6=False)


但是我收到了一个错误消息,内容如下:
                     def foo(*dirs, arg2, arg3=None, arg4=None, arg5=False, arg6=False):
                                       ^
SyntaxError: invalid syntax

在函数定义中,我看到写着“*参数后面的常规参数”。经过一些研究,我发现*dirs必须是最后一个指定的参数。
因此,我可以将函数参数更改为以下内容:
def foo(arg2, arg3=None, arg4=None, arg5=False, arg6=False, *dirs):

但是,当我这样做时,会收到一个错误消息:

SyntaxError: non-keyword arg after keyword arg

我不确定如何解决这个问题。有人知道解决方法吗?任何帮助将不胜感激!


def foo(arg2, *dirs, arg3=None, arg4=None, arg5=False, arg6=False,): 这个函数定义中的参数是什么意思呢?arg2 是一个必需的参数,后面跟着零个或多个位置参数 *dirsarg3arg4 是可选的命名参数,默认值为 None。而 arg5arg6 是布尔类型的可选参数,默认值分别为 False - Jean-François Fabre
很不幸,这两种方法都不起作用。我仍然收到regular parameter after * parameter的错误信息。 - says
在定义中为arg2添加默认值,然后arg2必须用作关键字参数(无论如何都要这样做),但顺序没问题。另外,FYI,对Python2.7的支持已于一周前停止。 - h4z3
我尝试过了,但是当我在调用*dirs的末尾处调用foo时,仍然会出现 SyntaxError: non-keyword arg after keyword arg。 我是这样进行调用的:foo(arg2 = 15,arg3 = ['hello there'],arg4 ='test',arg5 = True,arg6 = False, 'folder_name')。 不确定为什么仍然会出现错误。 - says
2个回答

1
我发现一个解决方法,但如果有其他想法,我很乐意尝试。
我将函数定义中的*dirs更改为关键字参数dirs=None,然后调用foo(dirs='folder_name', other arguments)就可以正常工作了。

1
如果dirs参数只指定了一个参数(位置或关键字)用于foo,例如一个字符串或一个字符串列表,换句话说,如果你想像这样调用foo:
foo("folder_name", other args)

或者

foo(["folder_name1", "folder_name2, ...], other args)

如果不需要在名称前加上*,那么你就不需要在函数参数中添加星号。而你答案中提到的“解决方法”实际上是正确的方法。请参见:https://docs.python.org/2/tutorial/controlflow.html#more-on-defining-functions
但是,如果dirs指定了任意序列的参数,并且你想要能够执行以下操作:
foo(other args, "folder_name1", "folder_name2",...)

如您所描述的,Python 2和Python 3存在差异。如您所见,在Python 3中存在仅限关键字参数,相比之下Python 2则不存在。具体信息请参见https://docs.python.org/3/glossary.html#term-parameterhttps://docs.python.org/2/glossary.html#term-parameter

在函数定义的参数列表前包含一个单一的var-positional参数或裸*,可以定义关键字参数。

因此,使用Python 3定义foo时不会出现问题。

def foo(*dirs, arg2, arg3=None, arg4=None, arg5=False, arg6=False):

并像这样调用:

foo('folder_name', arg2=100, arg3=['string', 'string2'], arg4='test6', arg5=True, arg6=False)

注意,在调用中,你正确地在"folder_name"之后提供了所有参数(甚至是arg2)作为关键字参数,因此在Python3中起作用。
但在Python2中,没有关键字-only参数。所以,正如你提到的,你既不能有* parameter之后的常规参数,也不能有关键字参数之后的非关键字参数。这就是为什么即使你将*dirs留在参数列表的最后,你也不能使用前面的参数作为关键字参数来调用foo。不过,你可以仍然将*dirs留在参数列表的最后,并且在调用foo时将之前的参数作为位置参数提供。例如(python 2.7):
def bar(a=1, b=2, *c):   # see below
    return (a, b, c)
bar(1, 2, 3)      # => (1, 2, (3,))
bar(1, b=3, 3)    # => Error: non-keyword arg after keyword arg
bar(1, 2)         # => (1 2 ())
bar(1)            # => Error: bar() takes at least 2 arguments (1 given)

因此,正如您所见,即使它允许您使用默认值为a、b定义bar(请参见上面链接中的位置或关键字),但它们不会被使用,即a和b是位置(必需的)。

最后,还要检查Python2文档中的这些链接:https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-listshttps://docs.python.org/2/faq/programming.html#what-is-the-difference-between-arguments-and-parameters


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接