使用函数定义中的双星语法,我们获得了一个常规字典。问题是它松开了用户输入顺序。有时,我们可能想知道传递给函数的关键字参数的顺序。
由于函数调用通常不涉及很多参数,我认为这不是性能问题所以我想知道为什么默认不是为了维护顺序。
我知道我们可以使用:
from collections import Ordereddict
def my_func(kwargs):
print kwargs
my_func(Ordereddict(a=1, b=42))
但它不那么简洁:
def my_func(**kwargs):
print kwargs
my_func(a=1, b=42)
[编辑1]:
1)我认为那里有2个案例:
我没想到即使用户知道它使用订单,他也可以使用:
a = dict(a=1, b=42)
my_func(**a)
因为他不知道没有下令(即使他应该知道)
2)我认为在一些论点的情况下开销不会很大,所以有一个新的可能性来管理论证的好处将优于这个缺点。
但似乎(来自Joe的回答)开销不可忽视。
[编辑2]:
似乎PEP 0468 -- Preserving the order of **kwargs in a function正朝这个方向发展。
答案 0 :(得分:7)
因为字典不按定义排序。我觉得这很简单。 kwargs
的要点是准确处理那些未订购的形式参数。如果您确实知道订单,那么您可以将其作为正常的'参数或*args
。
这是字典定义。
CPython实现细节:键和值列在 非随机的任意顺序因Python而异 实现,并取决于字典的插入历史 和删除。
http://docs.python.org/2/library/stdtypes.html#dict
Python的词典是整个语言工作方式的核心,因此它们经过高度优化。添加排序会影响性能并需要更多存储和处理开销。
你可能会遇到这样的情况,但我认为这种情况比普通情况更为特殊。添加功能'以防万一'对于非常热门的代码路径并不是一个明智的设计决策。
编辑:
仅供参考
>>> timeit.timeit(stmt="z = dict(x)", setup='x = ((("one", "two"), ("three", "four"), ("five", "six")))', number=1000000)
1.6569631099700928
>>> timeit.timeit(stmt="z = OrderedDict(x)", setup='from collections import OrderedDict; x = ((("one", "two"), ("three", "four"), ("five", "six")))', number=1000000)
31.618864059448242
在构建一个小小的正常情况下,速度差异大约为30倍。大小字典。 OrderedDict是标准库的一部分,因此我无法想象还有更多的性能可以从中挤出来。
答案 1 :(得分:3)
作为反驳论证,这里是一个复杂语义的例子。这里有几个案例:
some_func(a=1, b=2, **unordered_dict)
的案例怎么样?原始关键字参数中存在隐式排序,但是dict是无序的。订购与否之间没有明确的选择。
鉴于此,我会说排序关键字参数没有用,因为无法判断订单是否只是一个任意的。这会使函数调用的语义变得模糊。
鉴于此,将此作为调用的一部分所获得的任何好处都将丢失 - 相反,只需要OrderedDict
作为参数。
答案 2 :(得分:0)
如果函数的参数关联到名称和顺序都很重要,请考虑使用特定的数据结构或定义一个类来保存它们。您可能希望它们在代码中的其他位置一起使用,并可能定义使用它们的其他功能/方法。
答案 3 :(得分:0)
检索通过** kwargs传递的关键字参数的顺序在我正在处理的特定项目中非常有用。它是关于制作一种具有有意义尺寸的n-d numpy数组(现在称为dimarray),对地球物理数据处理特别有用。
我已在此处发布了一个已开发的问题示例:
How to retrieve the original order of key-word arguments passed to a function call?