2011-12-13 62 views
8

我读的善变的源代码,并发现了这样的FUNC DEF在commands.py:蟒蛇位置指定参数和关键字ARGS

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

在python,postional ARGS必须放在前面的关键字参数的个数。但在这里,patch1是一个关键字参数,后跟一个位置参数*patches。为什么这是好的?

+1

你解决了吗?如果你有,那么如果你选择让你解决问题为“接受”的答案,并且赞成所有有用的答案(如果你还没有这样做的话),那将是一件好事。 :) – mac

+0

对不起,我这些天一直很忙。现在我将阅读你的答案并选择一个答案。谢谢你们所有人:) – guoqiao

回答

8

随便看看到PEP 3102也似乎它的主题相关的this

总之,补丁和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 
+0

感谢您的示例和参考,我想我会得到我的答案。 python的论点非常灵活,在这个问题之前我对这件事一无所知。 – guoqiao

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!

+0

是的......在我看来,这是一个运行时模糊,而不是定义时间的歧义。由于OP涉及到函数定义[我正在描述函数定义](http://stackoverflow.com/a/8486166/1025391)。但我承认,这是一个很好的观点。 – moooeeeep

3

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

patch1不是一个关键字arg,它是一个具有指定的默认参数值的位置参数。

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


请看看来自官方教程本节:

现在让我用这个功能为例总结要点:

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

功能定义

你有一些由名(a1a2a3)明确定义的参数,其中a3将是,如果通话过程中没有提供默认的None初始化。需要在该函数的任何有效调用中提供参数a1a2

该函数可能会在字典kwargs(通过关键字提供)或列表args(当不由关键字提供时)中出现的附加参数调用。 如果argskwargs不会出现在函数定义中,调用方将不允许添加除函数定义中为函数调用明确命名的参数之外的更多参数。

在您需要先指定没有默认初始值的显式参数,第二,默认初始值,第三个参数列表,最后的关键字参数字典的明确参数的函数定义。

函数调用

有不同的方法来调用函数。例如将下面的调用产生相等的结果:

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和关键字参数不适合进入指定的参数列表函数定义将被插入关键字参数字典**kwargs

+0

我觉得这个定义有点模棱两可(虽然没有错)。在我的回答中查看编辑原因。 – mac

+0

谢谢!看到我对你的答案的评论:] – moooeeeep

+0

看我的例子,你可以使用patch1作为关键字参数,前提是没有位置参数。 – Abhijit

2

我相信当呼叫与功能:

function(arg1="value") 

这将使用一个“关键词”的说法,但是当定义函数的接口:

def function(arg1="value"): 

你定义一个“默认值” 。 ()

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

另请注意,在调用函数时,不能在关键字后有一个非关键字参数

+0

感谢您的回答。 – guoqiao