3

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

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

我知道我们可以使用:

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)

因为他不知道没有命令 dict(即使他应该知道)

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

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

[编辑 2]:

似乎PEP 0468 -- 在函数中保留 **kwargs 的顺序正朝着这个方向发展。

4

4 回答 4

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 是标准库的一部分,所以我不认为可以从中挤出更多的性能。

于 2013-08-06T10:16:58.113 回答
3

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

  • 该函数总是得到一个无序的字典。
  • 该函数总是得到一个有序的字典——给定这个,我们不知道这个顺序是否有任何意义,就像用户传入一个无序的数据结构,顺序将是任意的,而数据类型意味着顺序。
  • 该函数获取传入的任何内容 - 这看起来很理想,但并不是那么简单。

的情况如何some_func(a=1, b=2, **unordered_dict)?原始关键字参数中存在隐式排序,但随后 dict 是无序的。在订购与否之间没有明确的选择。

鉴于此,我会说对关键字参数进行排序是没有用的,因为无法判断该顺序是否只是任意顺序。这会混淆函数调用的语义。

鉴于此,将其作为调用的一部分所获得的任何好处都将丢失 - 相反,只需期待 anOrderedDict作为参数。

于 2013-08-06T10:29:09.893 回答
0

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

于 2013-08-06T12:00:40.423 回答
0

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

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

如何检索传递给函数调用的关键字参数的原始顺序?

于 2013-12-01T16:00:50.563 回答