【问题标题】:In Python, what determines the order while iterating through kwargs?在 Python 中,是什么决定了遍历 kwargs 时的顺序?
【发布时间】:2012-02-17 03:42:17
【问题描述】:

在 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 输入到我的函数中?

【问题讨论】:

    标签: python parameter-passing keyword-argument


    【解决方案1】:

    kwargs 是一个字典。字典是无序的——简单地说,顺序是未指定的,并且是一个实现细节。深入了解会发现顺序会根据项目的哈希值、插入顺序等发生很大变化,因此您最好不要依赖与它相关的任何内容。

    【讨论】:

    • 最近版本的python没有变化吗?
    • @AdrienH:在 3.6 中确实如此,请参阅 this answer
    【解决方案2】:

    这是一本字典。而且,如文档中所述,字典没有顺序(来自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))))
      

    【讨论】:

    • 查看我关于 OrderedDict 的回答。
    • @PaulMcGuire:请参阅我对您的回答的评论。
    • 你不会写成fxn(3, **OrderedDict(etc...吗?哦,等等,我看到您将签名更改为使用字典,而不是一组关键字参数。如果您要更改签名,那么您不妨只传递一个键值元组列表。但是 OP 真的很想迭代 **kwargs。
    • @PaulMcGuire:我明确指出,kwargs 没有顺序,因此我提出了替代解决方案:1)遍历有序的kwargs,2)传递@ 987654330@ 而不是使用关键字参数。是的,您可以传递元组,但如果您传递元组,您将无法像 dictOrderedDict 那样使用它,对吗? :) 如果您使用我的第二个解决方案,则函数的主体不会发生太大变化(因为它必须在参数中传递元组的情况下进行更改)。比较 dictOrderedDicttuple 以了解我的意思。
    【解决方案3】:

    这终于在3.6 release 中引入:dicts 现在是有序的,因此保留了关键字参数的顺序。

    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 不是 Python 3.6 中的 OrderedDict。它们仍然是 dict,但现在已订购 dict
    【解决方案4】:

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

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

    由于关键字参数首先被构建到无序字典中,因此您不能相信它们会按照它们列出的顺序插入到 OrderedDict 中。 :(

    【讨论】:

    • 但以下将:od = OrderedDict((('a',1), ('b',2), ('c',3)))。所以基本上**kwargs,因为它是一个dict,不会有任何顺序,但你总是可以将OrderedDict作为参数传递,它会有你想要的顺序。
    【解决方案5】:

    由于kwargs 是一个Python 字典,它被实现为hash table,它的顺序没有被保留,实际上是随机的。

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

    【讨论】:

    • 不是随机的——事实上,它是完全确定的。只是不容易预测,因为它取决于哈希。
    • 你当然是对的。这就是我说“有效随机”的原因,以向读者表明他不应该尝试猜测它。附带说明一下,计算机所做的几乎所有事情都是确定的,但可能不容易预测:)
    【解决方案6】:

    kwargs 是一个字典,在 Python 中这些是无序的,因此结果本质上是(伪)随机的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      相关资源
      最近更新 更多