python位置args和关键字args

时间:2011-12-13 08:13:26

标签: python func function

我正在阅读mercurial的源代码,并在commands.py中找到了这样的函数def:

def import_(ui, repo, patch1=None, *patches, **opts):
    ...
在python中,postional args必须放在关键字args之前。但是在这里,patch1是关键字参数,后跟位置参数*patches。为什么这样好?

4 个答案:

答案 0 :(得分:9)

只需查看PEP 3102,它似乎与this有某种关联。

总而言之,patch和opts可以接受变量参数,但后者是接受关键字参数。关键字参数作为字典传递,其中variable positional arguments would be wrapped as tuples

来自你的例子

def import_(ui, repo, patch1=None, *patches, **opts):

u1,repo and patch1之后的任何位置参数都将被包装为补丁中的元组。变量位置参数后面的任何关键字参数都将通过opts包装为Dictionary对象。

另一个重要的事情是,调用者有责任确保不违反条件non-keyword arg after keyword arg

因此违反此规定会引发语法错误。

例如

调用

 import_(1,2,3,test="test")
 import_(1,2,3,4,test="test")
 import_(1,2,3,4,5)
 import_(1,2,patch1=3,test="test")

有效,但

import_(1,2,3,patch1=4,5)

会引发语法错误SyntaxError: non-keyword arg after keyword arg

在第一个有效案例import_(1,2,3,test="test")

u1 = 1, repo = 2, patch1 = 3, patches = () and opts={"test":"test"}

在第二个有效案例import_(1,2,3,patch1=4,test="test")

u1 = 1, repo = 2, patch1 = 3 , patches = (4) and opts={"test":"test"}

在第三个有效案例import_(1,2,3,4,5)

u1 = 1, repo = 2, patch1 = 3 , patches=(4,5), and opts={}

在第四个有效案例import_(1,2,patch1=3,test="test")

u1 = 1, repo = 2, patch1 = 3 , patches=(), and opts={"test":"test"}
you can use patch1 as a keywords argument but doing so you cannot wrap any variable positional arguments within patches

答案 1 :(得分:3)

可能你会混淆函数定义和函数调用语法。

patch1不是关键字arg,它是一个位置arg,其默认参数值已分配。

*patches是一个参数列表,而不是位置参数。


请从官方教程中查看此部分:

现在让我用这个函数作为例子总结一下要点:

def f1(a1, a2, a3=None, *args, **kwargs):
  print a1, a2, a3, args, kwargs

功能定义

您有许多明确按名称(a1a2a3)定义的参数,其中a3将由{{1}默认初始化如果在通话期间没有提供。参数Nonea1需要在该函数的任何有效调用中提供。

可以使用字典a2(由关键字提供)或列表kwargs(不是由关键字提供)时出现的附加参数调用该函数。 如果函数定义中不存在argsargs,则除了函数调用的函数定义中明确命名的参数外,不允许调用者添加更多参数。

在函数定义中,您需要首先指定显式参数而不使用默认初始值设定项,第二个是使用默认初始值设定项的显式参数,第三个是参数列表,最后是关键字参数字典。

功能调用

有多种方法可以调用该功能。例如,以下调用会产生相同的结果:

kwargs

也就是说,函数参数可以通过它们的位置(位置或非关键字参数)或指定的名称(关键字参数)来解析。

调用函数时,需要先将非关键字参数放在首位,最后放置关键字参数,例如

f1(1, 2)       # pass a1 and a2 as positional arguments
f1(a2=2, a1=1) # pass a1 and a2 as keyword arguments
f1(1, a2=2)    # pass a1 as positional argument, a2 as keyword argument

现在,不适合函数定义中指定参数列表的位置参数将附加到参数列表# demonstrate how some additional positional and keyword arguments are passed f1(1, 2, 3, 4, 5, 6, 7, a4=8, a5=9, a6=10) # prints: # 1 2 3 (4, 5, 6, 7) {'a5': 9, 'a4': 8, 'a6': 10} ,以及不适合指定参数列表的关键字参数函数定义将插入关键字参数字典*args

答案 2 :(得分:2)

因为如果密钥参数的位置是明确的,那么将密钥传递给关键字参数可以是可选的。观察:

>>> def f(ui, patch1=None, *patches, **opts):
...     print patch1
... 
>>> f(1, 2)
2
>>> f(1, patch1='a', 3)
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> f(1, 'a', 3)
a

如您所见,省略patch1的键,使该参数成为非关键字,因此不会触发SyntaxError例外。


编辑: moooeeeep在他的回答中说

  

“patch1不是关键字arg,它是一个位置arg,分配了默认参数值。”

这没有错,但以下情况IMO说明了为什么这样的定义含糊不清:

>>> def f(ui, p1=None, p2=None, *patches, **opts):
...    print p1, p2
... 
>>> f(1, 'a', 'b', 3)  #p2 is a positional argument with default value?
a b
>>> f(1, p2='b')  #p2 is a keyword argument?
None b

HTH!

答案 3 :(得分:2)

我相信当调用一个函数时:

function(arg1="value")

这将使用“关键字”参数,但当定义函数的接口时:

def function(arg1="value"):

您正在定义“默认值”。 ()

所以回答你的问题;在位置参数之后具有默认值是完全正常的,因此在关键字之前调用具有非关键字参数的函数。

另请注意,在调用函数时,不能在关键字后面包含非关键字参数。