是否可以将 OrderedDict 实例传递给使用 **kwargs
语法并保留排序的函数?
我想做的是:
def I_crave_order(**kwargs):
for k, v in kwargs.items():
print k, v
example = OrderedDict([('first', 1), ('second', 2), ('third', -1)])
I_crave_order(**example)
>> first 1
>> second 2
>> third -1
但实际结果是:
>> second 2
>> third -1
>> first 1
即,典型的随机字典排序。
我还有其他用途可以明确设置顺序,所以我想保留 **kwargs
而不仅仅是将 OrderedDict 作为常规参数传递
最佳答案
从 Python 3.6 开始,the keyword argument order is preserved .在 3.6 之前,这是不可能的,因为 OrderedDict
变成了 dict
。
首先要意识到你在**example
中传递的值不会自动变成**kwargs
中的值。考虑这种情况,其中 kwargs
将只有 example
的一部分:
def f(a, **kwargs):
pass
example = {'a': 1, 'b': 2}
f(**example)
或者在这种情况下,它的值将比示例中的值更多:
example = {'b': 2}
f(a=1, c=3, **example)
甚至根本没有重叠:
example = {'a': 1}
f(b=2, **example)
所以,你所要求的并不真正有意义。
不过,如果有某种方法可以指定您想要一个有序的 **kwargs
,不管关键字来自 哪里——显式关键字 args按照它们出现的顺序,然后是 **example
的所有项目,按照它们在 example
中出现的顺序(如果 example
是一个 dict
,但如果它是一个 OrderedDict
也可能有意义)。
定义所有繁琐的细节并保持性能可接受,结果比听起来更难。见 PEP 468和链接的线程,用于讨论这个想法。这一次似乎停滞不前,但如果有人拿起它并支持它(并编写一个引用实现供人们使用 - 这取决于可从 C API 访问的 OrderedDict
,但是有望在 3.5+ 中出现),我怀疑它最终会进入该语言。
顺便提一下,如果这个是可能的,它几乎肯定会在OrderedDict
本身的构造函数中使用。但是,如果您尝试这样做,您所做的只是将一些任意订单卡住为永久订单:
>>> d = OrderedDict(a=1, b=2, c=3)
OrderedDict([('a', 1), ('c', 3), ('b', 2)])
同时,你有什么选择?
嗯,显而易见的选择是将 example
作为普通参数传递,而不是解包:
def f(example):
pass
example = OrderedDict([('a', 1), ('b', 2)])
f(example)
或者,当然,您可以使用 *args
并将项目作为元组传递,但这通常更难看。
从 PEP 链接的线程中可能还有其他一些解决方法,但实际上,没有一个会比这更好。 (除了……IIRC,李浩毅根据他的 MacroPy 提出了一个解决方案来传递订单保留关键字参数,但我不记得细节了。如果你愿意使用 MacroPy 和编写的代码读起来不像 Python,但这并不总是合适的……)
关于python - 在 **kwargs 中使用 OrderedDict,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26748097/