关于参数传递:在Python中,在迭代kwargs时决定顺序的是什么?

In Python, what determines the order while iterating through kwargs?

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

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

然后我调用了这个函数

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

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

1
2
3
4
3
a3  :  3
a2  :  2
a4  :  4

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


kwargs是一本字典。字典是无序的 - 简单地说,订单是未指定的和实现细节。在引擎盖下偷看将显示订单变化很大,具体取决于项目的哈希值,插入顺序等,因此您最好不要依赖与之相关的任何内容。


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

It is best to think of a dictionary as an unordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary).

但你可以按照某种顺序进行处理,例如:

  • 使用sorted()

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

    1
    2
    3
    4
    5
    6
    7
    8
    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))))


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

1
2
3
4
5
6
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'])


不幸的讽刺是,** kwargs的统一意味着以下方法不起作用(至少不是人们所期望的方式):

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

由于keyworded args首先构建在无序的dict中,因此您不能依赖它们按照列出的顺序插入到OrderedDict中。 :(


由于kwargs是一个Python字典,它实现为一个哈希表,因此它的排序不会保留,而且实际上是随机的。

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


kwargs是一个字典,在Python中,它们不是有序的,因此结果基本上是(伪)随机的。