为什么是Python’;s函数调用语义传入关键字参数是否未排序?

为什么是Python’;s函数调用语义传入关键字参数是否未排序?,python,Python,使用函数定义中的双星语法,我们得到了一个规则字典。问题是它会使用户输入顺序松动。有时,我们可能想知道关键字参数传递到函数的顺序 由于通常一个函数调用不涉及很多参数,我不认为这是一个性能问题,所以我想知道为什么默认情况下不维护顺序 我知道我们可以使用: from collections import Ordereddict def my_func(kwargs): print kwargs my_func(Ordereddict(a=1, b=42)) 但它不如: def my_func

使用函数定义中的双星语法,我们得到了一个规则字典。问题是它会使用户输入顺序松动。有时,我们可能想知道关键字参数传递到函数的顺序

由于通常一个函数调用不涉及很多参数,我不认为这是一个性能问题,所以我想知道为什么默认情况下不维护顺序

我知道我们可以使用:

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) 我认为有两种情况:

  • 我需要知道顺序,用户通过文档了解这种行为
  • 我不需要订单,所以我不在乎是否有订单
我没有想到,即使用户知道它使用订单,他也可以使用:

a = dict(a=1, b=42)
my_func(**a)
因为他不知道口述是不被命令的(即使他应该知道)

2) 我认为,在一些争论的情况下,开销不会很大,因此有一个新的可能性来管理争论的好处将优于这个缺点

但是(从乔的回答来看)开销似乎不可忽略

[编辑2]:


这似乎是朝着这个方向发展的。

因为字典不是按定义排序的。我认为这真的很简单。kwargs的要点是精确地处理那些未排序的形式参数。如果您确实知道顺序,则可以将其作为“正常”参数或
*args
接收

这是字典里的定义

CPython实现详细信息:键和值列在 非随机的任意顺序在Python中有所不同 实现,并取决于字典的插入历史 和删除

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是标准库的一部分,因此我不认为它会带来更多的性能。

作为反驳,下面是一个例子,说明这可能会导致复杂的语义。这里有几个案例:

  • 函数总是得到一个无序的字典
  • 函数总是得到一个有序的字典-鉴于此,我们不知道顺序是否有任何意义,就好像用户传递无序的数据结构一样,顺序将是任意的,而数据类型意味着顺序
  • 函数获取传入的任何内容-这似乎很理想,但并没有那么简单
一些函数(a=1,b=2,**无序)的情况如何?原始关键字参数中存在隐式排序,但dict是无序的。在订购与否之间没有明确的选择

有鉴于此,我认为对关键字参数进行排序是没有用的,因为不可能判断顺序是否是任意的。这会影响函数调用的语义


假定,将此作为调用的一部分所得到的好处是丢失的——相反,只期望一个<代码>有序的DICT < /C>作为一个参数。

< P>如果函数的参数是相关的,名称和顺序都很重要,请考虑使用特定的数据结构或定义一个类来保存它们。很可能,您希望它们在代码中的其他位置一起出现,并可能定义使用它们的其他函数/方法。

检索通过**kwargs传递的关键字参数的顺序对于我正在处理的特定项目非常有用。它是关于制作一种具有有意义尺寸的n-d numpy阵列(现在称为dimarray),对于地球物理数据处理特别有用

我在这里发布了一个带有示例的已开发问题:


我认为这更像是为什么而不是为什么-关键字参数需要排序是一种罕见的情况,而且排序字典不像
dict
s那样核心,所以它不是那样做的。@Lattyware我想说这种需要很少,因为它不可用。如果我能依靠保留的关键字参数的顺序,我会经常使用该功能。@piokuc真的吗?好吧,不管怎样,它都会使关键字参数的语义变得非常混乱-参见我的答案。
**kwargs
由于python 3.6是一个
有序的dict
,因此关键字参数顺序被保留。请看这里:这是一种很糟糕的计时方式,
timeit
模块的存在是有原因的。它既快又脏,可以测量经过的时间差。“很糟糕”吗?有一个系数是30。你应该回答“因为字典不是按定义排序的。”-我认为你把字典和哈希表搞混了。只是提醒我们,我们讨论的问题是“为什么Python的函数调用语义传入关键字参数不是按顺序排列的?”。例如,“为什么Python是按原样实现的”。哈希表是AFAIK中最快的字典实现。如果您知道一种实现有序字典的算法,它比哈希表更快(或者考虑到它在函数中的用例百分比,在某种意义上更慢),请告诉我们。这不是答案,因此应该删除。因此,他选择了(合理地)严格的问答形式。