我正在学习在python中使用位置参数,并试图在与默认参数混淆时看看它们是如何工作的: -
def withPositionalArgs(ae=9,*args):
print 'ae= ', ae
print 'args = ', args
a=1
b=2
c=[10,20]
withPositionalArgs(a,b,c)
这给了我输出:
ae= 1
args = (2, [10, 20])
如您所见,a
被视为ae
传递的值,b
以及c
被视为位置参数。< / p>
所以,我现在正在尝试在调用10
时为ae
分配withPositionalArgs
:
withPositionalArgs(ae=10,b,c)
但是,我不能这样做。我收到错误:
SyntaxError: non-keyword arg after keyword arg
我的问题是:
我做得对吗?是否允许使用默认参数或在python函数中的位置参数之前使用一个好的做法?
答案 0 :(得分:12)
在Python2中,不允许在位置参数之前放置具有默认值的参数。
必须首先使用位置参数,然后是具有默认值的参数(或者,在调用函数时,使用关键字参数),然后是*args
,然后是**kwargs
。
函数定义和函数调用都需要此顺序。
在Python3中,订单已经放宽。 (例如,*args
可以出现在函数定义中的关键字参数之前。)See PEP3102。
答案 1 :(得分:3)
我认为我们应该区分默认值与传递任意参数/键值对。没有默认值的行为是相同的:
def f(ae,*args, **kwargs):
print 'ae = ', ae
print 'args = ', args
print 'kwargs = ', kwargs
我们写这个的方式意味着第一个参数传递到元组f
中的args
,即f(1,2,3,a=1,b=2)
(序列变为显式参数,* args,** kwargs 。)这里:ae = 1, args = (2,3), kwargs = {'a': 1, 'b': 2}
。
如果我们尝试传入f(1,2,3,a=1,ae=3)
,我们会抛出TypeError: f() got multiple values for keyword argument 'ae'
,因为ae
的值会被尝试更改两次。
解决这个问题的一种方法是只在明确规定时设置ae
,我们可以(在def线之后):
def g(*args, **kwargs):
kwargs, kwargs_temp = {"ae": 9}, kwargs
kwargs.update(kwargs_temp) #merge kwargs into default dictionary
此次g(1,2,3,a=1,ae=3)
设置args=(1,2,3), kwargs={a=1,ae=3}
。
但是,我怀疑这不是最佳做法......
答案 2 :(得分:1)
Python3放松了订购。
现在您可以执行以下操作:
def withPositionalArgs(*args, ae=9):
print('ae=', ae)
print('args =', args)
a=1
b=2
c=[10, 20]
withPositionalArgs(a, b, c, ae=7)