12

在 python 中,我编写了这个函数来教自己如何**kwargs在 Python 中工作:

def fxn(a1, **kwargs):
    print a1
    for k in kwargs:
        print k, " : ", kwargs[k]

然后我用

fxn(3, a2=2, a3=3, a4=4)

这是我的 Python 解释器打印的输出:

3
a3  :  3
a2  :  2
a4  :  4

为什么 for 循环在 a2 之前打印 a3 的值,即使我先将 a2 输入到我的函数中?

4

6 回答 6

24

kwargs是一本字典。字典是无序的——简单地说,顺序是未指定的,并且是一个实现细节。窥视引擎盖会显示顺序根据项目的哈希值、插入顺序等变化很大,因此您最好不要依赖任何与之相关的东西。

于 2012-01-23T19:43:57.997 回答
11

这是一本字典。而且,如文档中所述,字典没有顺序(来自http://docs.python.org/tutorial/datastructures.html#dictionaries):

最好将字典视为一组无序的键:值对,并要求键是唯一的(在一个字典中)。

但是您可以按某种顺序对其进行处理,如下所示:

  • 使用sorted()

    def fxn(a1, **kwargs):
        print a1
        for k in sorted(kwargs): # notice "kwargs" replaced by "sorted(kwargs)"
            print k, " : ", kwargs[k]
    
  • 或使用OrderedDict类型(您可以将OrderedDict对象作为包含所有键值对的参数传递):

    from collections import OrderedDict
    
    def fxn(a1, ordkwargs):
        print a1
        for k in ordkwargs:
            print k, " : ", ordkwargs[k]
    
    fxn(3, OrderedDict((('a2',2), ('a3',3), ('a4',4))))
    
于 2012-01-23T19:44:25.913 回答
10

这最终在3.6 版本中引入:dict现在已排序,因此保留了关键字参数顺序。

Python 3.6.0 (default, Jan 13 2017, 13:27:48) 
>>> def print_args(**kwargs):
...     print(kwargs.keys())
... 
>>> print_args(first=1, second=2, third=3)
dict_keys(['first', 'second', 'third'])
于 2017-01-13T11:49:53.997 回答
5

不幸的讽刺是 **kwargs 的命令化意味着以下将不起作用(至少不是人们期望的方式):

od = OrderedDict(a=1, b=2, c=3)

由于带关键字的 args 首先内置到无序字典中,因此您不能依赖它们会按照它们列出的顺序插入到 OrderedDict 中。:(

于 2012-01-23T20:29:50.020 回答
2

由于kwargs是一个 Python字典,它被实现为一个哈希表,它的顺序没有被保留并且实际上是随机的。

实际上,作为对许多编程语言中最近的安全问题的修复,将来甚至可能会在调用程序(调用 Python 解释器)之间改变顺序。

于 2012-01-23T19:50:14.347 回答
1

kwargs是一个字典,在 Python 中这些是没有顺序的,所以结果本质上是(伪)随机的。

于 2012-01-23T19:43:41.877 回答