如何编写一个Python函数接受*参数和关键字参数?

3

我感觉这里一定有些简单的东西我没有注意到。

我想要做的是:

>>> def x(*args, a=False):
...   print args, a

>>> x(1,2)
(1,2) False

>>> x(1,2,3, a=True)
(1,2,3) True

但是你不能这样定义一个函数。

我知道这样会起作用,但它看起来不太好:

>>> def x(*args, **kwargs):
...   if 'a' in kwargs:
...       a = kwargs['a']
...   else
...       a = False
...   print args, a

如何最好地完成这个任务?
我正在使用Python 2.6。


1
我知道你在使用 2.6,但如果这是一个简单的脚本,我想知道是否可能将其移植到 3.0。我刚刚在 3.2 中测试了你的完整代码,它完美地运行了(可能是由于 Py3 的“头”和“尾”的概念非常棒)。 - jonesy
4个回答

5

我认为你的方法是唯一可行的。但你可以将其表述得更加优美:

def x(*args, **kwargs):
    a = kwargs.get('a', False)
    print args, a

x(1,2,3,a=42)

我可能夸大了替代方案的丑陋程度 :p - Jake
你可能想要添加类似于 assert 'a' in kwargs, "a is required" 或者 if 'a' not in kwargs: raise TypeError("x takes one keyword argument, none given") 这样的代码来帮助调试问题。 - S.Lott

3

刚发现这个http://www.python.org/dev/peps/pep-3102/

该链接是关于Python编程语言中的类型提示,提供了一种新的方法来在代码中注释变量和函数的类型。这种方法可以帮助开发者更好地理解代码并减少错误。

The first change is to allow regular arguments to appear after a varargs argument:

def sortwords(*wordlist, case_sensitive=False):
   ...

This function accepts any number of positional arguments, and it also accepts a keyword option called 'case_sensitive'.

所以它将在Python 3中出现


2
如果你能使用的话,Python 3 已经发布了。 - aaronasterling

0

其实,*args只是一个变量参数列表,而**kwargs只是一个字典关键字参数。

除非我误解了,为什么不直接这样做呢?

def x(args, a=False):
    print args, a

x((1,2),True) #<- just passes in a list instead of special list and dict

output
(1,2) True

x((1,2))

output
(1,2) False

没有变量 *argument 列表和检测 **kwargs 关键字只限参数字典,不够符合 Python编程风格,但可能适用于您的需求。


这是我想到的最好的解决方案,但我希望有更好的选择。 - Jake

0

你必须要么选择第二个选项,要么重新排列参数,使得默认参数在第一位:

def x(a=False, *args):

1
考虑到这一点,但我必须调用x(False, 1,2,3)而不仅仅是x(1,2,3),在这种情况下,它可能是def x(a, *args): - Jake

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