In Python, what determines the order while iterati

2019-01-12 03:29发布

In python, I wrote this function to teach myself how **kwargs works in Python:

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

I then called this function with

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

Here was the output that my Python interpreter printed:

3
a3  :  3
a2  :  2
a4  :  4

Why did the for loop print the value of a3 before that of a2 even though I fed a2 into my function first?

6条回答
老娘就宠你
2楼-- · 2019-01-12 03:35

The unfortunate irony is that the dict-ification of **kwargs means that the following will not work (at least not the way one would expect):

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

Since the keyworded args are first built into an unordered dict, you cannot depend that they will be inserted into the OrderedDict in the order they are listed. :(

查看更多
冷血范
3楼-- · 2019-01-12 03:38

This has finally been introduced in the 3.6 release: dicts are now ordered, therefore the keyword argument order is preserved.

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'])
查看更多
可以哭但决不认输i
4楼-- · 2019-01-12 03:39

kwargs is a dictionary. Dictionaries are unordered - simply put, the order is unspecified and an implementation detail. Peeking under the hood will show that the order varies wildly depending on the hash values of the items, the order of insertion, etc. so you better don't rely on anything related to it.

查看更多
老娘就宠你
5楼-- · 2019-01-12 03:45

kwargs is a dictionary, in Python these are not ordered so the result is essentially (pseudo-) random.

查看更多
Anthone
6楼-- · 2019-01-12 03:49

Since kwargs is a Python dictionary, which is implemented as a hash table, its ordering is not preserved and is effectively random.

Actually, as a fix to a recent security issue in many programming languages, in the future the order may even change between invocations of your program (invocations of the Python interpreter).

查看更多
Lonely孤独者°
7楼-- · 2019-01-12 03:52

This is a dictionary. And, as mentioned in documentation, dictionary has no order (from 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).

But you can make it processed in some order, like that:

  • using sorted():

    def fxn(a1, **kwargs):
        print a1
        for k in sorted(kwargs): # notice "kwargs" replaced by "sorted(kwargs)"
            print k, " : ", kwargs[k]
    
  • or by using OrderedDict type (you can pass OrderedDict object as parameter containing all the key-value pairs):

    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))))
    
查看更多
登录 后发表回答